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」,然後將其存回。
這將導致這兩個用戶擁有相同的「號碼」,一旦「所有者」字段變爲該號碼,他們都將獲得鎖定並對某些共享資源執行操作!
我不認爲內核在自旋鎖中會有這樣的錯誤。我在哪裏錯了嗎?
我明白了。所以鎖仍然發生在處理器指令中。謝謝。 – Jun