自旋鎖的目的是在短時間間內進行輕量級的鎖定,解決對某項共享資源的互斥使用,在等待鎖從新可用期間進行自旋,因此自旋鎖不該該被持有時間過長,若是須要長時間鎖定的話,推薦使用信號量。實際操做的數據結構以下:
數據結構
最終執行的代碼是體系結構相關的自旋鎖實現:arch_spin_lock。
fetch
static inline void arch_spin_lock(arch_spinlock_t *lock) { unsigned long tmp; u32 newval; arch_spinlock_t lockval; // 處理器通知內存系統將對某個地址的內存進行讀寫 prefetchw(&lock->slock); // 以獨佔的方式對 lock->tickets.next 執行 +1 操做 __asm__ __volatile__( "1: ldrex %0, [%3]\n" " add %1, %0, %4\n" " strex %2, %1, [%3]\n" " teq %2, #0\n" " bne 1b" : "=&r" (lockval), "=&r" (newval), "=&r" (tmp) : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) : "cc"); // 判斷是否輪到本身擁有自旋鎖 while (lockval.tickets.next != lockval.tickets.owner) { // 將當前核心掛起等待其餘核心發送信號,也就是等 SEV 指令 wfe(); // 讀取自旋鎖中的 lock->tickets.owner lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner); } // 數據同步 smp_mb(); }
最終執行的代碼是體系結構相關的自旋鎖實現:arch_spin_unlock。
code
static inline void arch_spin_unlock(arch_spinlock_t *lock) { // 數據同步 smp_mb(); // 將自旋鎖交給下一個使用者 lock->tickets.owner++; // 先進行數據同步,而後給其餘核心發信號 dsb_sev(); }
自旋鎖底層實現依賴於體系結構相關的彙編指令,在進行自旋鎖操做時,使用獨佔指令LDREX/STREX;在自旋時使用指令WFE將當前核心掛起,等待被喚醒;當核心在釋放自旋鎖時,使用SEV指令通知其餘全部核心。blog