Race conditions#
例子#
struct list{ |
假設現在有兩個 process 同時在不同的 CPU 上執行上述程式碼,當兩個 process 都執行到 14 行,則兩條鏈結的 next
都設置為 list
;接著,先執行的 process A 將 list 設定為自己的鏈結,後執行的 process B 也將 list 設為自己的鏈結。
問題:此時 list 上將會遺失原本 process A insert
的節點。
圖解#
- 一開始的 list
- 假設 pocess A 及 B 同時將自己的資料插在 list 的第一顆
- 接著 process A 以些微的差距先將 list 設為 l(自己的鏈結),此時 list 的第一顆為 A 的資料
- 最後 process B 也將 list 設為 l,此時 list 上的第一顆為 B 的資料,且 A 的資料遺失了。
使用鎖#
struct list *list = 0; |
Code: 鎖#
- XV6 使用
struct spinlock
,其中以 locked 作為標記。- 為 0 時,此鎖無人使用,可以被取用
- 非 0 時,此鎖有人在使用,無法被取用
File: spinlock.h#
1 | // Mutual exclusion lock. |
- 邏輯上,
acquire
應該長這樣:
void |
- 但是我們發現,可能會有多個 CPU 執行至第五行,發現
lk->locked
為0
,接著都拿到了鎖,即違反了互斥 - XV6 使用 x86 的特殊指令
xchg
來完成動作。
File: spinlock.c
功能 | 回傳值 | *lk |
---|---|---|
要求鎖 | void | 欲要求的鎖 |
20 | // Acquire the lock. |
功能 | 回傳值 | *lk |
---|---|---|
還鎖 | void | 欲還的鎖 |
42 | // Release the lock. |
File: x86.h
功能 | 回傳值 |
---|---|
交換值(x86特殊指令) | 結果 |
*addr |
newval |
---|---|
欲交換值得目標 | 欲填的值 |
120 | static inline uint |