linux gcc原子操作

2021-06-10 12:10:33 字數 2813 閱讀 1355

gcc從4.1.2提供了__sync_*系列的built-in函式,用於提供加減和邏輯運算的原子操作。

其宣告如下:

type __sync_fetch_and_add (type *ptr, type value, ...)

type __sync_fetch_and_sub (type *ptr, type value, ...)

type __sync_fetch_and_or (type *ptr, type value, ...)

type __sync_fetch_and_and (type *ptr, type value, ...)

type __sync_fetch_and_xor (type *ptr, type value, ...)

type __sync_fetch_and_nand (type *ptr, type value, ...)

type __sync_add_and_fetch (type *ptr, type value, ...)

type __sync_sub_and_fetch (type *ptr, type value, ...)

type __sync_or_and_fetch (type *ptr, type value, ...)

type __sync_and_and_fetch (type *ptr, type value, ...)

type __sync_xor_and_fetch (type *ptr, type value, ...)

type __sync_nand_and_fetch (type *ptr, type value, ...)

這兩組函式的區別在於第一組返回更新前的值,第二組返回更新後的值。

type可以是1,2,4或8位元組長度的int型別,即:

int8_t / uint8_t

int16_t / uint16_t

int32_t / uint32_t

int64_t / uint64_t

後面的可擴充套件引數(...)用來指出哪些變數需要memory barrier,因為目前gcc實現的是full barrier(類似於linux kernel 中的mb(),表示這個操作之前的所有記憶體操作不會被重排序到這個操作之後),所以可以略掉這個引數。

bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)

type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)

這兩個函式提供原子的比較和交換,如果*ptr == oldval,就將newval寫入*ptr,

第乙個函式在相等並寫入的情況下返回true.

第二個函式在返回操作之前的值。

__sync_synchronize (...)

發出乙個full barrier.

關於memory barrier,cpu會對我們的指令進行排序,一般說來會提高程式的效率,但有時候可能造成我們不希望得到的結果,舉乙個例子,比如我們有乙個硬體裝置,它有4個暫存器,當你發出乙個操作指令的時候,乙個暫存器存的是你的操作指令(比如read),兩個暫存器存的是引數(比如是位址和size),最後乙個暫存器是控制暫存器,在所有的引數都設定好之後向其發出指令,裝置開始讀取引數,執行命令,程式可能如下:

write1(dev.register_size,size);

write1(dev.register_addr,addr);

write1(dev.register_cmd,read);

write1(dev.register_control,go);

如果最後一條write1被換到了前幾條語句之前,那麼肯定不是我們所期望的,這時候我們可以在最後一條語句之前加入乙個memory barrier,強制cpu執行完前面的寫入以後再執行最後一條:

write1(dev.register_size,size);

write1(dev.register_addr,addr);

write1(dev.register_cmd,read);

__sync_synchronize();

write1(dev.register_control,go);

memory barrier有幾種型別:

acquire barrier : 不允許將barrier之後的記憶體讀取指令移到barrier之前(linux kernel中的wmb())。

release barrier : 不允許將barrier之前的記憶體讀取指令移到barrier之後 (linux kernel中的rmb())。

full barrier    : 以上兩種barrier的合集(linux kernel中的mb())。

還有兩個函式:

type __sync_lock_test_and_set (type *ptr, type value, ...)

將*ptr設為value並返回*ptr操作之前的值。

void __sync_lock_release (type *ptr, ...)

將*ptr置0

示例程式:

#include

#include

#include

static int count = 0;

void *test_func(void *arg)

return null;

}int main(int argc, const char *argv)

for(i=0;i<20;++i)

printf("%d\n",count);

return 0;

}

原子性,原子操作

舉個例子 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狀態,初始化標準為是清除狀態。當你的標誌物件已初始化,那麼你只能做三件事情 銷毀,清除或設定 查詢之前的值 這些事情對應的函式分別...