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 |