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
<
stdio.h
>
#include
<
pthread.h
>
#include
<
stdlib.h
>
static
intcount =0
;void
*test_func(
void
*arg)
return
null;
}int
main(
intargc,
const
char
*argv)
for(i=0
;i<20;
++i)
printf(
"%d\n
",count);
return0;
}
參考:1. section 7.4
2.
GCC 提供的原子操作
gcc 提供的原子操作 gcc從4.1.2提供了 sync 系列的built in函式,用於提供加減和邏輯運算的原子操作。其宣告如下 type sync fetch and add type ptr,type value,type sync fetch and sub type ptr,type v...
GCC 提供的原子操作
日期 2011 06 17 gcc從4.1.2提供了 sync 系列的built in函式,用於提供加減和邏輯運算的原子操作。其宣告如下 type sync fetch and add type ptr,type value,type sync fetch and sub type ptr,type...
GCC 提供的原子操作
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 sy...