3

我正在编写与操作系统无关的无锁队列,队列工作正常(使用默认的 windows\linux atomic CAS),但我想让队列在不改变 linux 和 windows 的情况下工作。所以我想我应该在汇编程序中编写自己的 CAS,还是有其他方法可以实现它?

到目前为止,我有这个代码:

global _CAS

_CAS:

    mov eax, [esp+4]    
    mov edx, [esp+8]    
    mov ecx, [esp+12]   

    ;XCHG eax, edx  <- this function works fine
     CMPXCHG  ecx, eax, ebx 

    ret

我知道我lock之前仍然需要添加CMPXCHG它,它应该适用于结构,但现在我更感兴趣的是让它工作。

我使用 nasm-2.10.05 使用此命令进行编译,但nasm.exe -f elf -o cas.o cas.asm 出现此错误testas\cas.asm:14: error: invalid combination of opcode and operands

4

2 回答 2

14

使用 C11 或更高版本,您应该使用如今<stdatomic.h>已获得广泛支持的 .

#include <stdatomic.h>

请参阅atomic_compare_exchange。我不会在这里尝试总结确切的语义。

如果没有 C11,您可以在两个平台上使用内在函数,无需组装:

#ifdef _MSC_VER
# include <intrin.h>
# define CAS(ptr, oldval, newval) \
    _InterlockedCompareExchange(ptr, newval, oldval)
#elif __GNUC__
# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
#  error "requires GCC 4.1 or greater"
# endif
# define CAS(ptr, oldval, newval) \
    __sync_val_compare_and_swap(ptr, oldval, newval)
#else
# error "CAS not supported on this platform"
#endif

这两个都支持以下接口:

/* If the current value of *ptr is oldval, then write newval
   into *ptr.  Returns the initial value of *ptr.  */
long CAS(long *ptr, long oldval, long newval);

请参阅MSDN 文档GCC 文档。这也应该适用于 Clang,无需修改,因为 Clang 宣传__GNUC__与其预定义宏的兼容性。

于 2012-11-07T11:04:31.953 回答
5

根据http://web.itu.edu.tr/kesgin/mul06/intel/instr/cmpxchg.htmlcmpxchg需要两个,而不是三个参数。

也许,http ://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=arch/x86/include/asm/cmpxchg.h也很有趣。

于 2012-11-07T10:41:42.080 回答