2016-09-20 59 views
1
void 
sema_down (struct semaphore *sema) 
{ 
    old_level = intr_disable(); 
    while (sema->value == 0) 
    { 
     list_push_back (&sema->waiters, &thread_current()->elem); 
     thread_block(); 
    } 
    sema->value--; 
    intr_set_level (old_level); 
} 

上面的一段代碼是PintOS中的mechanim鎖定互斥鎖。 PintOS是針對單處理器系統的。因爲這個事實,僅僅禁用中斷就足夠了。另一方不可能採取互斥體。多處理器體系結構和Ring 3

所以,讓我們考慮一個多處理器設計:

void 
sema_down (struct semaphore *sema) 
{ 
    old_level = intr_disable(); 
    while (!lock cmpxchg(1,0)) // it is just pseudocode-idea 
    { 
     list_push_back (&sema->waiters, &thread_current()->elem); 
     thread_block(); 
    } 
    intr_set_level (old_level); 
} 

old_level = intr_disable();。它關閉中斷,但僅在該CPU的情況下才是關鍵。

它可以是一個原型在MP架構中獲取互斥量的函數。但是,list_push_back存在問題。它也必須是安全的 - 多線程。但是,我們不能用互斥體來保證它的安全,因爲我們現在只是在實施它!

的主要問題是: 有沒有可能是兩個(或更多)的CPU是在環0級(內核)執行代碼?

而且,依賴於答案的第一個子問題:

  1. 如果沒有,有我上述沒有問題。但是 - 它如何實施?

  2. 如果是的話(這似乎不可能或很難實現),那麼我的上述考慮(這只是潛在問題的例子)。 我們是否需要使用spinlockslock-free structures

+1

您是否可以將帖子縮減爲單個明確的問題?自旋鎖和無鎖定編程如果用於同步訪問非常短的關鍵部分(如更新列表的部分)並且無法避免AFAIK,那麼它們並不壞。 –

+0

@MargaretBloom,我編輯,使它更清楚我問什麼。基本上,這是單題問題。我沒有擺脫我的子問題,因爲它們是依賴於上下文的,並且沒有必要將它們放在其他帖子中。 ( 我想是這樣)。我希望它對你更友善。 – Gilgamesz

+1

我對此特別困惑:「*是否有可能兩個(或更多)CPU在Ring 3級別(內核)*上執行代碼」。爲什麼你會發現令人驚訝的是不同的CPU可以執行相同的代碼?爲什麼* Ring 3 *(這是用戶模式)旁邊有一個*內核*? –

回答

3

是的,在SMP多CPU甚至可以在環0

每個CPU是對稱的從而它可以執行相同的代碼路徑作爲其他人(包括內核代碼)執行相同的代碼,除非該軟件實現某種同步。

Linux內核也面臨這個問題,並且最初實現了一個不太好的解決方案:A Big Kernel Lock,它在進入和退出內核時被獲取併發布。

這不是一個好的解決方案,因爲一次只有一個CPU可以執行內核代碼,但實現起來很快,並且它與您列表中的項目編號相同。

更好的解決方案是在整個內核中使用更精細的鎖。
既然它是內核實現了像例子中所示的互斥鎖或信號燈這樣的睡眠鎖,它不能依賴那些基本本身,並且必須使用自旋鎖或其他更簡單的鎖定形式。

幸運的是,這不是一個問題,自旋鎖(和its variants)實際上比互斥鎖好,或者關鍵路徑非常短(如更新列表)。

您可以從Linux上看看mutex_init,看看是否使用了自旋鎖來同步等待任務的隊列。

49 void 
50 __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key) 
51 { 
52   atomic_set(&lock->count, 1); 


53   spin_lock_init(&lock->wait_lock); 


54   INIT_LIST_HEAD(&lock->wait_list); 
55   mutex_clear_owner(lock); 
56 #ifdef CONFIG_MUTEX_SPIN_ON_OWNER 
57   osq_lock_init(&lock->osq); 
58 #endif 
59 
60   debug_mutex_init(lock, name, key); 
61 } 

所以對第二項的答案是肯定的。


在等待,而等待鎖睡覺你無法入睡。

+1

非常感謝:) – Gilgamesz

相關問題