【发布时间】:2013-01-13 07:50:44
【问题描述】:
我写了下面的用户级代码sn-p来测试两个子函数,原子inc和xchg(参考Linux代码)。
我需要的只是尝试对 32 位整数执行操作,这就是我明确使用int32_t 的原因。
我假设global_counter 将被不同的线程竞争,而tmp_counter 很好。
#include <stdio.h>
#include <stdint.h>
int32_t global_counter = 10;
/* Increment the value pointed by ptr */
void atomic_inc(int32_t *ptr)
{
__asm__("incl %0;\n"
: "+m"(*ptr));
}
/*
* Atomically exchange the val with *ptr.
* Return the value previously stored in *ptr before the exchange
*/
int32_t atomic_xchg(uint32_t *ptr, uint32_t val)
{
uint32_t tmp = val;
__asm__(
"xchgl %0, %1;\n"
: "=r"(tmp), "+m"(*ptr)
: "0"(tmp)
:"memory");
return tmp;
}
int main()
{
int32_t tmp_counter = 0;
printf("Init global=%d, tmp=%d\n", global_counter, tmp_counter);
atomic_inc(&tmp_counter);
atomic_inc(&global_counter);
printf("After inc, global=%d, tmp=%d\n", global_counter, tmp_counter);
tmp_counter = atomic_xchg(&global_counter, tmp_counter);
printf("After xchg, global=%d, tmp=%d\n", global_counter, tmp_counter);
return 0;
}
我的两个问题是:
- 这两个子函数写对了吗?
- 当我在 32 位或
64位平台?例如,指针地址是否可以有不同的
长度。还是
incl和xchgl会与操作数冲突?
【问题讨论】:
-
在内存操作数约束中使用
ptr时不要取消引用。 -
与
xchg不同,inc默认不是原子的。你需要一个lock前缀。 -
由于内联 asm 已经是 gcc 特定的,您不妨使用 gcc atomic 内置函数。至少这些也可以在 x86-64 甚至其他架构下工作。
-
嗨,Michael,但为什么 Linux 可以尊重 lxr.linux.no/linux+v2.6.38/arch/x86/include/asm/… 中的 ptr?这样做有什么风险?
-
正如哈罗德所说,公司应该是 __asm__("lock;\n" "incl %0;\n" : "+m"(*ptr));