如何在基于Linux GCC的汇编语言中实现__sync_fetch_and_sub原子操作

时间:2013-01-10 05:11:16

标签: c linux gcc assembly inline-assembly

我需要在汇编语言中自己编写__sync_fetch_and_sub原子操作的实现,基于GCC 3.4,它没有__sync_fetch_and_sub内置函数。但我对装配知之甚少。

任何人都可以帮助我吗?任何帮助将不胜感激!!

这是__sync_fetch_and_add

的实现
inline unsigned int __sync_fetch_and_add(volatile unsigned int* p, unsigned int incr)
{

    unsigned int result;
    __asm__ _volatile_ ("lock; xadd %0, %1" :
            "=r"(result), "=m"(*p):
            "0"(incr), "m"(*p) :
            "memory");
    return result;
}

__sync_fetch_and_add(int *ptr, int a_count)是将a_count原子地添加到ptr指向的变量中。返回之前在内存中的值。

__sync_fetch_and_sub(int *ptr, int a_count)是从ptr指向的变量中原子地减去a_count。返回之前在内存中的值。

1 个答案:

答案 0 :(得分:4)

此代码段使用xadd的原子版:交换并添加:它以原子方式将右操作数添加到左侧(此处为内存),并在右操作数中返回内存中的初始值。之前的lock语句确保操作的原子性。

然而,gcc使用AT& T表示法,因此这个解释中的左右参数(取自intel手册)是相反的。

由于英特尔架构上没有xsub指令,因此最简单的方法是首先采用与您想要减去的数字相反的方法,然后以原子方式添加/交换它:

inline unsigned int __sync_fetch_and_sub(volatile unsigned int* p,
    unsigned int decr)
{
    unsigned int result;

    __asm__ __volatile__ ("lock; xadd %0, %1"
            :"=r"(result), "=m"(*p)
            :"0"(-decr), "m"(*p)
            :"memory");
    return result;
}

我也删除了unsigned属性,在这种情况下我发现它们不相关。