生活随笔
收集整理的這篇文章主要介紹了
c++ 原子操作 赋值_原子操作原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 概念 原子操作是指不被打斷的操作,即它是最小的執行單位。最簡單的原子操作就是一條條的匯編指令(不包括一些偽指令,偽指令會被匯編器解釋成多條匯編指令)。在 linux 中原子操作對應的數據結構為 atomic_t,定義如下:
typedef struct { int counter;} atomic_t;
本質上就是一個整型變量,之所以定義這么一個數據類型,是為了讓原子操作函數只接受 atomic_t 類型的操作數,如果傳入的不是 atomic_t 類型數據,在程序編譯階段就不會通過;另一個原因就是確保編譯器不會對相應的值進行訪問優化,確保對它的訪問都是對內存的訪問,而不是對寄存器的訪問。2. 賦值操作 ARM 處理器有直接對內存地址進行賦值的指令(STR)。
#define atomic_set(v,i) (((v)->counter) = (i))
3. 讀操作 用 volatile 來防止編譯器對變量訪問的優化,確保是對內存的訪問,而不是對寄存器的訪問。
#define atomic_read(v) (*(volatile int *)&(v)->counter)
4. 加操作 使用獨占指令完成累加操作。
static inline void atomic_add(int i, atomic_t *v){ unsigned long tmp; int result; // 使用獨占指令讀取,然后執行加操作,獨占寫失敗時就重新執行 __asm__ __volatile__("@ atomic_add\n""1: ldrex %0, [%3]\n"" add %0, %0, %4\n"" strex %1, %0, [%3]\n"" teq %1, #0\n"" bne 1b" : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) : "r" (&v->counter), "Ir" (i) : "cc");}
5. 減操作 對比加操作 和減操作 的代碼可以看出,它們非常的相似,其實不同的地方就一句,所以現在最新的內核源碼中已經使用宏定義 ATOMIC_OP(op, c_op, asm_op) 來重寫了這部分代碼。
static inline void atomic_sub(int i, atomic_t *v){ unsigned long tmp; int result; // 使用獨占指令讀取,然后執行減操作,獨占寫失敗時就重新執行 __asm__ __volatile__("@ atomic_sub\n""1: ldrex %0, [%3]\n"" sub %0, %0, %4\n"" strex %1, %0, [%3]\n"" teq %1, #0\n"" bne 1b" : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) : "r" (&v->counter), "Ir" (i) : "cc");}
6. 其他操作 類似的原子操作函數還有一些,比如 atomic_XXX_return、atomic_cmpxchg、atomic_clear_mask,以及在此基礎上實現的 atomic_inc、atomic_dec、atomic_XXX_and_test、atomic_XXX_return等。以上代碼都是針對 SMP 處理器的實現方式,針對非 SMP 處理器,由于不存在其他核心的搶占,所以只需要防止其他進程搶占即可實現原子操作,例如加操作 :
static inline int atomic_sub_return(int i, atomic_t *v){ unsigned long flags; int val; // 通過關閉中斷防止其他進程打斷代碼的執行 raw_local_irq_save(flags); val = v->counter; v->counter = val -= i; // 恢復中斷原始的狀態 raw_local_irq_restore(flags); return val;}
7. 總結 原子性操作的實現需要具體體系結構相關的指令集的支持。
總結
以上是生活随笔 為你收集整理的c++ 原子操作 赋值_原子操作原理 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。