gcc内联实现原子CAS
我一直在尝试实现一个gcc内联函数(AT&T assembly),该函数将执行原子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“
谢谢为什么不使用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;
}