自旋鎖原理分析

1. 概念

自旋鎖的目的是在短時間間內進行輕量級的鎖定,解決對某項共享資源的互斥使用,在等待鎖從新可用期間進行自旋,因此自旋鎖不該該被持有時間過長,若是須要長時間鎖定的話,推薦使用信號量。實際操做的數據結構以下:
數據結構

2. 獲取鎖

最終執行的代碼是體系結構相關的自旋鎖實現:arch_spin_lock。
fetch

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。
code

5. 代碼分析

static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
  // 數據同步
  smp_mb();
  // 將自旋鎖交給下一個使用者
  lock->tickets.owner++;
  // 先進行數據同步,而後給其餘核心發信號
  dsb_sev();
}

6. 總結

自旋鎖底層實現依賴於體系結構相關的彙編指令,在進行自旋鎖操做時,使用獨佔指令LDREX/STREX;在自旋時使用指令WFE將當前核心掛起,等待被喚醒;當核心在釋放自旋鎖時,使用SEV指令通知其餘全部核心。blog

相關文章
相關標籤/搜索