当前位置: 首页 > 工具软件 > OpenSBI > 使用案例 >

OpenSBI atomic_xchg函数分析

司寇苗宣
2023-12-01

atomic_xchg函数原型

long atomic_xchg(atomic_t *atom, long newval)
{
    /* Atomically set new value and return old value. */
#ifdef __riscv_atomic
    return axchg(&atom->counter, newval);
#else
    return xchg(&atom->counter, newval);
#endif
}

axchg宏定义

#define axchg(ptr, x)                               \
    ({                                  \
        __typeof__(*(ptr)) _x_ = (x);                   \
        (__typeof__(*(ptr))) __axchg((ptr), _x_, sizeof(*(ptr)));   \
    })

__axchg宏定义

这里是linux内核中惯用套路,使用typeof来获取参数的类型,并使用sizeof来获取参数的size,根据size区分使用汇编指令

#define __axchg(ptr, new, size)                         \
    ({                                  \
        __typeof__(ptr) __ptr = (ptr);                  \
        __typeof__(new) __new = (new);                  \
        __typeof__(*(ptr)) __ret;                   \
        switch (size) {                         \
        case 4:                             \
            __asm__ __volatile__ (                  \
                "   amoswap.w.aqrl %0, %2, %1\n"        \
                : "=r" (__ret), "+A" (*__ptr)           \
                : "r" (__new)                   \
                : "memory");                    \
            break;                          \
        case 8:                             \
            __asm__ __volatile__ (                  \
                "   amoswap.d.aqrl %0, %2, %1\n"        \
                : "=r" (__ret), "+A" (*__ptr)           \
                : "r" (__new)                   \
                : "memory");                    \
            break;                          \
        default:                            \
            break;                          \
        }                               \
        __ret;                              \
    })

atomic_t定义

typedef struct {
    volatile long counter;
} atomic_t;

amoswap.d 含义:原子双字交换指令

amoswap.d  rd, rs2, (rs1)

将内存中地址为 x[rs1]中的双字记为 t,把这个双字变为 x[rs2]的值,把 x[rd]设为 t。

aqrl 含义:aq表示acquire,rl表示release

表示在此指令加上了内存屏障,前后的加载存储指令不能越过屏障

amoswap.d.aqrl %0, %2, %1 汇编

%0 :ret

%1 : *__ptr

%2 :_new 

即等同于amoswap.d.aqrl  ret, _new ,*__ptr  <==> amoswap.d.aqrl  ret, new, atom->counter

就是将new赋值给atom->counter,然后将旧值赋值给ret

long atomic_xchg(atomic_t *atom, long newval)

含义: 将newval值赋值给atom->counter, 返回atom->counter的旧值,并且还带有加载获取、存储释放的特性。

 类似资料: