【问题标题】:Atomic compare and swap in assembler OS independent独立于汇编器操作系统的原子比较和交换
【发布时间】:2012-11-07 10:32:55
【问题描述】:

我正在编写独立于操作系统的无锁队列,队列工作正常(使用默认的 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

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

我使用 nasm-2.10.05 编译这个命令nasm.exe -f elf -o cas.o cas.asm 我得到这个错误testas\cas.asm:14: error: invalid combination of opcode and operands

【问题讨论】:

  • 这种方法将您限制在 x86 平台上。

标签: c linux windows assembly atomic


【解决方案1】:

对于 C11 或更高版本,您应该使用 &lt;stdatomic.h&gt;,目前已获得广泛支持:

#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 documentationGCC documentation。这也应该在没有修改的情况下在 Clang 上工作,因为 Clang 宣传 __GNUC__ 与其预定义宏的兼容性。

【讨论】:

  • 这可能会起作用,Mac OS 怎么样?是否需要额外的 #ifdef ?
  • @Full_Int:它适用于 OS X。确保你没有在 OS X 上使用 GCC 4.0。
  • 如果不支持,有什么方法可以做同样的事情吗?
  • @52Coder:你用的是什么平台和工具链?
  • @52coder: &lt;stdatomic.h&gt; for atomic_compare_exchange_weak 自 ISO C11 以来。如果在您的 C11 实现中支持 lock_free,它应该使用 lock cmpxchg。 (任何现实的 C 实现都应该这样做。)
【解决方案2】:
猜你喜欢
  • 2012-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-14
  • 1970-01-01
  • 2013-04-24
  • 2021-03-09
  • 2010-12-22
相关资源
最近更新 更多