2013-09-21 33 views
1

我正在處理需要雙倍寬度比較和交換操作(cmpxchg16b)的項目。我通過luke h發現了以下代碼,但是當我使用「g ++ - 4.7 -g -DDEBUG = 1 -std = C++ 0x dwcas2.c -o dwcas2.o」進行編譯時,出現以下錯誤:在彙編代碼中爲cmpxchg16b編譯時出錯

錯誤:

g++-4.7 -g -DDEBUG=1 -m64 -std=c++0x dwcas2.c -o dwcas2.o 
dwcas2.c: Assembler messages: 
dwcas2.c:29: Error: junk `ptr ' after expression 

任何想法爲什麼?,我覺得它是一個小而容易修復,我只是看不到它。

計算機規格: 運行Ubuntu 12.04 LTS的64核ThinkMate RAX QS5-4410服務器。這是一個NUMA系統,配有四個AMD Opteron 6272 CPU(每芯片16個核心@ 2.1 GHz)和314 GB共享內存。

代碼:

#include <stdint.h> 

namespace types 
{ 
    struct uint128_t 
    { 
     uint64_t lo; 
     uint64_t hi; 
    } 
    __attribute__ ((__aligned__(16))); 
} 

template< class T > inline bool cas(volatile T * src, T cmp, T with); 

template<> inline bool cas(volatile types::uint128_t * src, types::uint128_t cmp, types::uint128_t with) 
{ 
    bool result; 
    __asm__ __volatile__ 
    (
     "lock cmpxchg16b oword ptr %1\n\t" 
     "setz %0" 
     : "=q" (result) 
     , "+m" (*src) 
     , "+d" (cmp.hi) 
     , "+a" (cmp.lo) 
     : "c" (with.hi) 
     , "b" (with.lo) 
     : "cc" 
    ); 
    return result; 
} 

int main() 
{ 
    using namespace types; 
    uint128_t test = { 0xdecafbad, 0xfeedbeef }; 
    uint128_t cmp = test; 
    uint128_t with = { 0x55555555, 0xaaaaaaaa }; 
    return ! cas(& test, cmp, with); 
} 
+0

它應該只是'鎖定cmpxchg16b%1'。這種情況下的大小是不需要的,因爲它被指令'cmpxchg16b'所暗示。它出現在任何你認爲這段代碼是由某人認爲內聯彙編程序等同於_MASM_的人編寫的。 –

+1

我可以使用內聯asm來製作音軌嗎?如何使用[__sync_bool_compare_and_swap](https://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Atomic-Builtins.html)?或者甚至可能是std :: atomic? –

+0

@DavidWohlferd哦,現在,內部函數太容易了,但是你又可能想要你在GCC上的wiki條目來計算某些東西;-) –

回答

2

在x86上GCC默認使用AT & T語法組裝,但你的來源是英特爾的語法。你可能在clobber列表中也需要「內存」。

+0

我對組裝的經驗非常有限,你能提供一個例子嗎? –

+0

在這種情況下,clobber列表中的「內存」將不是必需的,因爲被更改的內存被明確列爲輸出操作數「」+ m「(* src)' –

+1

@MichaelPetch我不確定我是否同意。雖然可能不需要cmpxchg16b的正確功能,但通常使用這種類型的語句來同步線程。在這種情況下,在執行asm之前,你可能會想把所有內容都刷新到內存中。 –