gcc内联实现原子CAS

gcc内联实现原子CAS,c,assembly,x86,inline-assembly,C,Assembly,X86,Inline Assembly,我一直在尝试实现一个gcc内联函数(AT&T assembly),该函数将执行原子CAS操作,但我无法让它工作——返回值总是出错 我尝试了两种不同的方法,每种方法似乎都有自己的错误行为: 一, 二, 但是这两种方法都不起作用,有人能告诉我其中一种实现的问题吗 谢谢为什么不使用C11原子类型或gcc内部函数?原子CAS不需要进行组装。问题太多,效率太低,很难知道从哪里开始pushf显然是疯了;ZF已经在标记中,您可以使用它jz或setz,而不是将其提取为整数reg,然后使用和/cmp将其返回ZF“

我一直在尝试实现一个gcc内联函数(AT&T assembly),该函数将执行原子CAS操作,但我无法让它工作——返回值总是出错

我尝试了两种不同的方法,每种方法似乎都有自己的错误行为:

一,

二,

但是这两种方法都不起作用,有人能告诉我其中一种实现的问题吗


谢谢

为什么不使用C11原子类型或gcc内部函数?原子CAS不需要进行组装。问题太多,效率太低,很难知道从哪里开始
pushf
显然是疯了;ZF已经在标记中,您可以使用它
jz
setz
,而不是将其提取为整数reg,然后使用
/
cmp
将其返回ZF
“=m”(ret)
是纯输出,因此可以优化
ret=1
初始值设定项。此外,没有理由使用内存操作数,
“+r”
也可以工作。@J.Doe
=
约束表示“程序集将始终覆盖操作数具有的任何值。”使用
=
约束,然后不给该操作数赋值,会导致操作数采用不确定的值。使用
+
约束告诉编译器操作数的上一个值很重要。@J.Doe:这与我的意思相反。我说您的约束忽略了您初始化了
ret
,因此您应该将约束修复为
“+r”(ret)
(读/写操作数)。请注意GCC手册中
+
=
之间的区别:。或者,您可以使用带有
setz%0
“=r”
8位
\u Bool
输出将ZF作为0或1整数存储到寄存器中。另请参见文档和教程。或者您可以使用GCC6标志输出约束直接告诉GCC其中一个输出是ZF,从而避免asm中的
setz
指令的开销。我在上的回答显示了
锁的完全工作的C包装器;cmpxchg在模板中没有其他asm指令,只有必要的约束。为什么不使用C11原子类型或gcc内部函数?原子CAS不需要进行组装。问题太多,效率太低,很难知道从哪里开始
pushf
显然是疯了;ZF已经在标记中,您可以使用它
jz
setz
,而不是将其提取为整数reg,然后使用
/
cmp
将其返回ZF
“=m”(ret)
是纯输出,因此可以优化
ret=1
初始值设定项。此外,没有理由使用内存操作数,
“+r”
也可以工作。@J.Doe
=
约束表示“程序集将始终覆盖操作数具有的任何值。”使用
=
约束,然后不给该操作数赋值,会导致操作数采用不确定的值。使用
+
约束告诉编译器操作数的上一个值很重要。@J.Doe:这与我的意思相反。我说您的约束忽略了您初始化了
ret
,因此您应该将约束修复为
“+r”(ret)
(读/写操作数)。请注意GCC手册中
+
=
之间的区别:。或者,您可以使用带有
setz%0
“=r”
8位
\u Bool
输出将ZF作为0或1整数存储到寄存器中。另请参见文档和教程。或者您可以使用GCC6标志输出约束直接告诉GCC其中一个输出是ZF,从而避免asm中的
setz
指令的开销。我在上的回答显示了
锁的完全工作的C包装器;cmpxchg
在模板中没有其他asm指令,只有必要的约束。
static inline int
cas(volatile void * addr, int expected, int newval) 
{
  int result = 1;
  asm volatile("lock; cmpxchgl %3, (%2)\n\t"
               "pushfl\n\t"
              "popl %%ebx\n\t"
              "andl $0x40, %%ebx\n\t"
              "cmpl $0x0, %%ebx\n\t"
              "jnz res%=\n\t"
              "movl $0, %0\n\t"
              "res%=:\n\t"
              : "=m"(result)
              : "a"(expected), "b"(addr), "r"(newval)
              : "memory");

  return result;
}
static inline int cas(volatile void * addr, int expected, int newval) {
  int ret = 1;
  asm volatile("lock; cmpxchgl %3, (%2)\n\t"
          "jz cas_success%=\n\t"
          "movl $0, %0\n\t"
          "cas_success%=:\n\t"
  : "=m"(ret)
  : "a"(expected), "b"(addr), "r"(newval)
  : "memory");
  return ret;
}