原子操作 ARM架構

2021-08-01 06:03:25 字數 2465 閱讀 1521

說明:核心版本號為3.10.101

一、arm架構中的原子操作實現

在原子操作(一)中我們已經提到,各個架構組織為「復仇者」聯盟,統一了基本的原子變數操作,這裡我們就拿atomic_dec(v)來看看通天arm的實現。

首先是atomic_dec(v)原子減一操作的巨集定義。這個巨集的定義在檔案arch/arm/include/asm/atomic.h中:

#define atomic_dec(v)        atomic_sub(1, v)
對於arm架構不同的版本,stomic_sub(i,v)的實現是不一樣的。具體而言,在armv6之前的版本定義如下:

#define atomic_sub(i, v)    (void) atomic_sub_return(i, v)
而armv6以後的版本則將atomic_sub()實現為static 內聯函式,具體見第二節。

二、armv6以前的版本的實現

armv6之前的版本將atomic_sub()巨集定義為atomic_sub_return()函式,其實現也在檔案arch/arm/include/asm/atomic.h中。而這個atomic_sub_return()函式根據版本的不同也有兩個不同的實現。我們這裡只關注armv6之前版本的實現。

/*

armv6 以前的版本:不支援smp

*/static inline int atomic_sub_return(int i, atomic_t *v)

可以看到,對v->counter的減一操作是乙個臨界區,指令的執行不能被打斷,記憶體的訪問也需要保持沒有干擾。

armv6以前的版本通過關本地中斷來保護這塊臨界區,看起來相當簡單,其奧秘就在於armv6以前的版本不支援smp。

在系統不支援smp的情況下,我們關掉本地中斷可以防止下面幾種意外:

1) 關掉本地中斷後,在對v->counter實施"減一"的過程中不會被外部中斷打斷;

2) 系統不支援smp,可以保證在本地cpu訪問v->counter和val變數記憶體的過程中不會有其他cpu訪問這些記憶體。

問題:

1. 雖然在臨界區內不會有其他cpu訪問 v->counter和val,但是能夠保證不會有dma操作這些記憶體麼?

2. 雖然禁止了中斷,但是可以保證期間此cpu不會被搶占或者因為其他原因放棄排程麼?

答:

1. dma在操作記憶體前會通過dma中斷、匯流排仲裁來與cpu的記憶體訪問進行協調。這裡已經關掉本地中斷,且是up系統,所以不會干擾。

2. 在up系統中沒有核心搶占;從**上來看,臨界區這一段沒有主動放棄cpu;另外,我們禁止了本地中斷,也就是禁止了時鐘中斷,這樣在開中斷前就不會有機會進行排程檢查,保證臨界區在開中斷前一直執行。

三. armv7以後的架構

從armv6t2以後的版本中,arm和thumb指令集開始採用了新一代"獨佔訪問"指令"load-exclusive and store-exclusive "來實現原子操作。獨佔訪問的秘訣就在於系統中通過exclusive monitor來實現獨佔訪問的監控。核心中atomic_sub()的具體實現如下所示:

/*

* armv6 up and smp safe atomic ops. we use load exclusive and

* store exclusive to ensure that these are atomic. we may loop */

static inline void atomic_sub(int i, atomic_t *v)

訪存指令ldrex/strex和普通的ldr/str訪存指令不一樣,它是「獨佔」訪存指令。這對指令訪存過程由乙個稱作「exclusive monitor」的部件來監視是否可以進行獨佔訪問。

先看看這對獨佔訪存指令:

(1)ldrex r1 ,[r0] 指令是以獨佔的方式從r0所指的位址中取乙個字存放到r0中;

(2)strex r2,r1,[r0] 指令是以獨佔的方式用r1來更新記憶體,如果獨佔訪問條件允許,則更新成功並返回0到r2,否則失敗返回1到r2。

了解ldrex和strex的基本原理後,理一理上面atomic_sub()原子更新(減一)atomic_t * v的實現流程:

(1) 從記憶體中讀取v->counter值到乙個暫存器中(result),並更新exclusive monitor狀態為獨佔訪問;

(2)result減一操作;

(3)嘗試將result的值寫入v->counter位址,如果exclusive monitor允許獨佔寫存,則修改記憶體成功並將tmp設定為0 ,否則tmp設定1;

(4)檢視tmp的值是否為0 ,如果不為0表示上面的更新v->counter失敗,再次跳轉會(1)執行。

一旦strex指令執行成功,就表示這次記憶體訪問沒有受到其他干擾,保證了記憶體更新操作的原子性。

原子性,原子操作

舉個例子 a想要從自己的帳戶中轉1000塊錢到b的帳戶裡。那個從a開始轉帳,到轉帳結束的這乙個過程,稱之為乙個事務。在這個事務裡,要做如下操作 從a的帳戶中減去1000塊錢。如果a的帳戶原來有3000塊錢,現在就變成2000塊錢了。在b的帳戶裡加1000塊錢。如果b的帳戶如果原來有2000塊錢,現在...

原子變數與原子操作

1.原子操作的速度要快於臨界區,event,互斥量,如果多個執行緒同時寫乙個變數時,最方便的就是原子操作。原子操作函式,解決多執行緒安全 2.原子變數也是為了解決執行緒衝突問題,如果兩個執行緒同時訪問同乙個變數,乙個執行緒改變了這個變數,另乙個執行緒就會出現一些bug。3.release和debug...

c 原子操作 賦值 c 原子操作

這個型別可以在兩個狀態間切換 設定set flag true 和清除clear flag false 必須被atomic flag init初始化此時flag為clear狀態,初始化標準為是清除狀態。當你的標誌物件已初始化,那麼你只能做三件事情 銷毀,清除或設定 查詢之前的值 這些事情對應的函式分別...