atomic原子类实现机制_atomic实现原理
atomic是原子的意思,意味"不可分割"的整體。在Linux kernel中有一類atomic操作API。這些操作對用戶而言是原子執行的,在一個CPU上執行過程中,不會被其他CPU打斷。最常見的操作是原子讀改寫,簡稱RMW。例如,atomic_inc()接口。atomic硬件實現和Cache到底有什么關系呢?其實有一點關系,下面會一步步揭曉答案。
問題背景
我們先來看看不使用原子操作的時候,我們會遇到什么問題。我們知道increase一個變量,CPU微觀指令級別分成3步操作。1) 先read變量的值到CPU內存寄存器;2) 對寄存器的值遞增;3) 將寄存器的值寫回變量。例如不使用原子指令的情況下在多個CPU上執行以下increase函數。
int counter = 0;
void increase(void)
{
counter++;
}
例如2個CPU得系統,初始值counter為0。在兩個CPU上同時執行以上increase函數。可能出現如下操作序列:
+ +----------------------+----------------------+
| | CPU0 operation | CPU1 operation |
| +----------------------+----------------------+
| | read counter (== 0) | |
| +----------------------+----------------------+
| | increase | read counter (== 0) |
| +----------------------+----------------------+
| | write counter (== 1) | increase |
| +----------------------+----------------------+
| | | write counter (== 1) |
| +----------------------+----------------------+
V
timeline
我們可以清晰地看到,當CPU0讀取counter的值位0后,在執行increase操作的同時,CPU1也讀取counter變量,同樣counter的值依然是0。隨后CPU0和CPU1先后將1的值寫入內存。實際上,我們想執行兩次increase操作,我應該得到counter值為2。但是實際上得到的是1。這不是我們想要的結果。為了解決這個問題,硬件引入原子自增指令。保證CPU0遞增原子變量counter之間,不被其他CPU執行自增指令導致不想要的結果。硬件是如何實現原子操作期間不被打斷呢?
Bus Lock
當CPU發出一個原子操作時,可以先鎖住Bus(總線)。這樣就可以防止其他CPU的內存操作。等原子操作結束,釋放Bus。這樣后續的內存操作就可以進行。這個方法可以實現原子操作,但是鎖住Bus會導致后續無關內存操作都不能繼續。實際上,我們只關心我們操作的地址數據。只要我們操作的地址鎖住即可,而其他無關的地址數據訪問依然可以繼續。所以我們引入另一種解決方法。
Cacheline Lock
為了實現多核Cache一致性,現在的硬件基本采用MESI協議(或者MESI變種)維護一致性。因此我們可以借助多核Cache一致性協議MESI實現原子操作。我們知道Cache line的狀態處于Exclusive或者Modified時,可以說明該變量只有當前CPU私有Cache緩存了該數據。所以我們可以直接修改Cache line即可更新數據。并且MESI協議可以幫我們保證互斥。當然這不能不能保證RMW操作期間不被打斷,因此我們還需要做些手腳實現原子操作。
我們依然假設只有2個CPU的系統。當CPU0試圖執行原子遞增操作時。a) CPU0發出"Read Invalidate"消息,其他CPU將原子變量所在的緩存無效,并從Cache返回數據。CPU0將Cache line置成Exclusive狀態。然后將該cache line標記locked。b) 然后CPU0讀取原子變量,修改,最后寫入cache line。c) 將cache line置位unlocked。
在步驟a)和c)之間,如果其他CPU(例如CPU1)嘗試執行一個原子遞增操作,CPU1會發送一個"Read Invalidate"消息,CPU0收到消息后,檢查對應的cache line的狀態是locked,暫時不回復消息(CPU1會一直等待CPU0回復Invalidate Acknowledge消息)。直到cache line變成unlocked。這樣就可以實現原子操作。我們稱這種方式為鎖cache line。這種實現方式必須要求操作的變量位于一個cache line。
LL/SC
LL/SC(Load-Link/Store-Conditional)是另一種硬件實現方法。例如aarch64架構就采用這種方法。這種方法就不是我們關注的重點了。略過。
總結
借助多核Cache一致性協議可以很方便實現原子操作。當然遠不止上面舉例說的atomic_inc還有很多其他類似的原子操作,例如原子比較交換等。
總結
以上是生活随笔為你收集整理的atomic原子类实现机制_atomic实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MATLAB三元条件运算符,C++ ?:
- 下一篇: 条件运算符用法