__sync_xxx()
是模仿一些英特爾原語,在你的x86上,原子加載/存儲是相當微不足道的,我認爲這是爲什麼該設置看起來不完整。
對於原子商店,我覺得你被卡住__sync_val_compare_and_swap()
,雖然喜歡__sync_fetch_and_add()
負載,這顯然是矯枉過正:-(
有是「整個內存屏障」 __sync_synchronize()
,但我一直沒能發現這是什麼(除了在x86_64上的實驗)!如果你確切知道你正在編譯什麼機器,你可以玩得開心,看到...開始加載和存儲包裝在__sync_synchronize()
。
我可以告訴對於x86和x86_64,原子加載不需要任何額外的普通讀取操作。原子存儲需要一個mfence
,如果你想要memory_order_seq_cst
,但不是。但是... __sync_xxx
系列中缺少的其他東西是編譯器障礙...除非這就是__sync_synchronize()
實際上所做的!
後來添加的...
我建議C/C++11 mappings to processors對於如何原子能可/應在x86/x86_64的,ARM和PowerPC實現一個很好的說明。
要使用__sync_val_compare_and_swap()
爲int
的原子店:
void a_store(int* p_ai, int val)
{
int ai_was ;
ai_was = *p_ai ;
do { ai_was = __sync_val_compare_and_swap (p_ai, ai_was, val) ;
} ;
在您的x86/x86_64的,對於memory_order_seq_cst(SC),你需要或者LOCK XCHG
或MOV
後跟MFENCE
...等等在循環中使用LOCK CMPXCHG
會有點痛苦。對於ARM,這也是有點痛苦,但更:-(
手卷原子加載/存儲是嚴格勇敢(或愚蠢)...和,取決於什麼!__sync_synchronize()實際上沒有一個給定的機器上,可能會或可能無法正常工作
所以,瑣碎的做法是:
__sync_synchronize() ;
v = v_atomic ; // atomic load !
__sync_synchronize() ;
__sync_synchronize() ;
v_atomic = v ; // atomic store !
__sync_synchronize() ;
其中,用於x86/x86_64的編譯(對我來說,在GCC 4.8對於x86_64):
mfence
mov xxx, xxx
mfence
用於加載和存儲。這是絕對安全(和SC)...對於加載它可能會或可能不會比LOCK XADD
...更好的存儲它可能會比LOCK CMPXCHG
和周圍的迴路更好!
如果(且僅當)爲ARM編譯這給:
dmb
ldr/str
dmb
然後,爲了安全(和SC)。
現在...適用於x86/x86_64的爲處理器你不需要任何MFENCE
在所有負載,甚至不SC。但是你確實需要停止編譯器重新排序的東西。 __sync_synchronize()
這樣做,以及種植mfence
。對於GCC,你可以構建一個__sync_compiler()
與下面的Voodoo:
#define __sync_compiler() __asm__ __volatile__("":::"memory")
我天真地認爲,__sync_synchronize()
(用於x86/x86_64的)實際上是:
#define __sync_mfence() __asm__ __volatile__("mfence":::"memory")
因爲x86/x86_64的是這麼不乖你可以:
__sync_compiler() ;
v = v_atomic ; // atomic load -- memory_order_seq_cst
__sync_compiler() ;
__sync_compiler() ;
v_atomic = v ; // atomic store -- memory_order_seq_cst
__sync_synchronize() ;
AND ...如果你能memory_order_release生活,那麼你可以通過一個更換僅存!現在
,爲ARMv7的......如果(且僅當 - 我沒有手臂,所以不能對此進行測試)__sync_synchronize()
編譯爲dmb
,那麼我們可以做負載非常輕微更好:
__sync_compiler() ;
v = v_atomic ; // atomic load
__sync_synchronize() ;
對於所有內存命令:memory_order_seq_cst和_acquire(和_consume)。
而對於memory_order_release我們可以:
__sync_synchronize() ;
v_atomic = v ; // atomic store -- memory_order_release
__sync_compiler() ;
對於似乎有特殊LDA
和STL
指令ARMv8 ...但我有些在這裏我的深度。
注意:這是以下C/C++11 mappings to processors我有信心,但不能證明ARM的真相。
反正......如果你願意手工卷的原子加載/存儲,那麼你可以做的更好。
所以......如果這些東西速度真的很重要,我會忍不住用手卷,假設目標體系結構的限制數量,並指出:
您使用無論如何gcc特定的東西,所以__sync_compiler()
技巧不會引入額外可移植性問題。
的__sync_xxx
家族一直在GCC更完整__atomic_xxx
所取代,所以如果你需要添加另一個目標架構未來,那麼你可能再能升級到__atomic_xxx
。
,並在不太遠的將來distand標準C11原子公司將全面上市,所以解決可移植性問題,可以踢。
你在寫一些彙編語言可能是。根據所用的CPU架構,您的選擇根本不同。請明確說明。 – zwol 2014-09-03 15:07:57
你也可以使用像ConcurrencyKit相對輕量級庫:http://concurrencykit.org/doc/ck_pr_store.html – 2014-09-03 17:32:37
你有'__sync_lock_test_and_set'? – zch 2014-09-03 18:26:28