2013-11-03 72 views
0

我發現Linux內核中的自旋鎖現在都使用「ticket-based」自旋鎖。然而,在看過ARM的實現後,我感到困惑,因爲「load-add-store」操作根本不是原子操作。請參閱下面的代碼:基於門票的ARM自旋鎖競態條件

74 static inline void arch_spin_lock(arch_spinlock_t *lock) 
75 { 
76   unsigned long tmp; 
77   u32 newval; 
78   arch_spinlock_t lockval; 
79 
80   __asm__ __volatile__(
81 "1:  ldrex %0, [%3]\n" /*Why this load-add-store is not atomic?*/ 
82 "  add  %1, %0, %4\n" 
83 "  strex %2, %1, [%3]\n" 
84 "  teq  %2, #0\n" 
85 "  bne  1b" 
86   : "=&r" (lockval), "=&r" (newval), "=&r" (tmp) 
87   : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) 
88   : "cc"); 
89 
90   while (lockval.tickets.next != lockval.tickets.owner) { 
91     wfe(); 
92     lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner); 
93   } 
94 
95   smp_mb(); 
96 } 

正如你所看到的,上線81〜83,它加載鎖相> SLOCK爲「lockval」和一個增加它,然後將其保存回鎖相> SLOCK。

但是,我沒有看到任何地方,這是確保原子。所以它可能是這樣的:

不同cpu上的兩個用戶正在讀鎖 - > slock到他們自己的變量「lockval」在同一時間;然後他們分別添加一個「lockval」,然後將其存回。

這將導致這兩個用戶擁有相同的「號碼」,一旦「所有者」字段變爲該號碼,他們都將獲得鎖定並對某些共享資源執行操作!

我不認爲內核在自旋鎖中會有這樣的錯誤。我在哪裏錯了嗎?

回答

1

STREX is a conditional store,此代碼具有Load Link-Store Conditional語義,即使ARM不使用該名稱。

該操作要麼以原子方式完成,要麼失敗。

彙編程序塊測試失敗(tmp變量指示失敗)並使用新值(由另一個核心更新)重新嘗試修改。

+0

我明白了。所以鎖仍然發生在處理器指令中。謝謝。 – Jun