【问题标题】:atomic_inc and atomic_xchg in gcc assemblygcc 程序集中的 atomic_inc 和 atomic_xchg
【发布时间】:2013-01-13 07:50:44
【问题描述】:

我写了下面的用户级代码sn-p来测试两个子函数,原子incxchg(参考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;
}

我的两个问题是:

  1. 这两个子函数写对了吗?
  2. 当我在 32 位或 64位平台?例如,指针地址是否可以有不同的 长度。还是inclxchgl 会与操作数冲突?

【问题讨论】:

  • 在内存操作数约束中使用 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));

标签: gcc assembly x86 x86-64


【解决方案1】:

我对这个问题的理解如下,如果我错了,请纠正我。

所有读-修改-写指令(例如:incl、add、xchg)都需要一个锁定前缀。 lock指令是通过在内存总线上断言LOCK#信号来锁定其他CPU访问的内存。

Linux 内核中的 __xchg 函数意味着没有“锁定”前缀,因为 xchg 始终意味着锁定。 http://lxr.linux.no/linux+v2.6.38/arch/x86/include/asm/cmpxchg_64.h#L15

但是,atomic_inc 中使用的 incl 没有这个假设,因此需要 lock_prefix。 http://lxr.linux.no/linux+v2.6.38/arch/x86/include/asm/atomic.h#L105

顺便说一句,我认为您需要将 *ptr 复制到 volatile 变量以避免 gcc 优化。

威廉

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-07
    • 2017-04-29
    • 2011-01-30
    • 2012-04-27
    • 2013-07-05
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多