1. 概念 自旋鎖的目的是在短期間內進行輕量級的鎖定,解決對某項共用資源的互斥使用,在等待鎖重新可用期間進行自旋,所以自旋鎖不應該被持有時間過長,如果需要長時間鎖定的話,推薦使用信號量。實際操作的數據結構如下: 2. 獲取鎖 最終執行的代碼是體繫結構相關的自旋鎖實現:arch_spin_lock。 ...
1. 概念
自旋鎖的目的是在短期間內進行輕量級的鎖定,解決對某項共用資源的互斥使用,在等待鎖重新可用期間進行自旋,所以自旋鎖不應該被持有時間過長,如果需要長時間鎖定的話,推薦使用信號量。實際操作的數據結構如下:
2. 獲取鎖
最終執行的代碼是體繫結構相關的自旋鎖實現:arch_spin_lock。
3. 代碼分析
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();
}
4. 釋放鎖
最終執行的代碼是體繫結構相關的自旋鎖實現:arch_spin_unlock。
5. 代碼分析
static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
// 數據同步
smp_mb();
// 將自旋鎖交給下一個使用者
lock->tickets.owner++;
// 先進行數據同步,然後給其他核心發信號
dsb_sev();
}
6. 總結
自旋鎖底層實現依賴於體繫結構相關的彙編指令,在進行自旋鎖操作時,使用獨占指令LDREX/STREX;在自旋時使用指令WFE將當前核心掛起,等待被喚醒;當核心在釋放自旋鎖時,使用SEV指令通知其他所有核心。