ARM Linux下spinlock 的實現

2021-09-25 21:31:38 字數 1650 閱讀 5471

1),spin lock 結構體

typedef struct spinlock ;

#endif

};} spinlock_t;

typedef struct raw_spinlock raw_spinlock_t;

typedef struct tickets;

};} arch_spinlock_t;

暫且拋開那些config 巨集定義,其實就是arch_spinlock_t這個結構體。

這個結構體是32bits大小。用了union。slock和 next owner共用這32bits。

舊版本的核心spin lock結構體只有乙個u32 ,為0則可以獲得鎖,不為0就自旋等待。 新的自旋鎖加了next和owner讓執行緒可以按獲取鎖的順序排隊。

2),獲取鎖

static inline void spin_lock(spinlock_t *lock)

沒什麼好說,直接到raw_spin_lock,然後中間經過數次呼叫,或者巨集定義(其中有區分smp和up等)

最終到

static inline void __raw_spin_lock(raw_spinlock_t *lock)

1,關閉搶占,同一cpu上靠關閉搶占解決同步問題,up上spin lock 其實就是關閉搶占

2,這個是編譯時靜態檢查相關,保證解鎖加鎖成對出現

3,這個巨集就最終呼叫了do_raw_spin_lock,再到arch_spin_lock

3)arch_spin_lock

static inline void arch_spin_lock(arch_spinlock_t *lock)

smp_mb();

}

從第8行開始是嵌入了asm 彙編, __volatile__關鍵字確保下面**不被優化改變。

根據嵌入彙編的規則,%0 是lockval ,型別為arch_spinlock_t型別,%1 %2 依次是newval 和tmp,依次類推。

彙編第1行: 把lock->slock值儲存到lock_val

第2行:newval=lockval+1加1《第3,4行:lock->slock = newval ,判斷strex返回值,確認是否成功更新鎖,如果更新失敗,說明有其他核心路徑插入。 

ldrex 和strex 用這種方法保證原子性,所以同一時間只會有乙個執行緒能成功更新lock->slock的值。

同樣核心中原子操作也是用類似的方法實現。

第5行: 如果更新失敗回到1行。

如果更新成功,到下面c**

判斷next是否等於owner,如果相等就獲得鎖,如果不相等說明還沒輪到自己,呼叫wfe()掛起當前cpu。

釋放鎖操作

static inline void arch_spin_unlock(arch_spinlock_t *lock)

釋放鎖比較簡單,直接owner++,然後sev指令通知所有cpu,其他cpu會嘗試獲得鎖。

思考一下為什麼釋放鎖不需要用原子操作的方式操作owner,而獲取鎖需要用原子方式操作next?

另外用smp_mb()資料記憶體屏障保證亂序執行時,記憶體操作的順序。

ARM Linux下交叉編譯lzo

進入lzo 2.03目錄下 lzo 2.03 configure host arm unknown linux gnu prefix home lanpeng arm lzo 引數解釋 host host arm unknown linux gnu 是你的交叉編譯工具的名字。prefix home ...

arm linux下編譯perf工具

因查詢linux系統下 kworker占用過高的原因,用perf工具來分析。perf為 linux kernel自帶的效能檢測工具。在linux3.10核心下編譯perf工具。1.cd 到 kerne tools perf路徑下 2.export path home huanghm work dsp...

ARM Linux 下 Hello 驅動程式

今天終於在我的tq2440 arm板子上執行了乙個簡單的驅動程式,慚愧 簡單的 hello 驅動 下面是步驟 因為是字元char 的驅動程式 所以我們應該在核心原始碼目錄下的 drivers char 新建乙個名為 yikai hello.c 內容如下 name yikai hello.c incl...