Linux GCC如何用汇编语言实现__sync_fetch_and_sub原子操作

Ste*_*eve 3 c linux assembly gcc 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

lbo*_*onn 5

此代码段使用原子版本的xadd:exchange 和 add:它原子地将右侧操作数添加到左侧(此处为内存),并在右侧操作数中返回内存中的初始值。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;
}
Run Code Online (Sandbox Code Playgroud)

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