原子操作

原子操作可以保证对一个整型数据的修改是排他性的。

Linux内核提供了一系列函数来实现内核中的原子操作,这些函数分成两类

  • 位原子操作
  • 整型变量原子操作

不管是哪种原子操作都依赖于底层CPU的原子操作,因此所有这些函数都与CPU架构密切相关。对于ARM处理器而言,底层试用LDREX和STREX指令,比如:

/*
 * ARMv6 UP and SMP safe atomic ops.  We use load exclusive and
 * store exclusive to ensure that these are atomic.  We may loop
 * to ensure that the update happens.
 */

#define ATOMIC_OP(op, c_op, asm_op)                 \
static inline void atomic_##op(int i, atomic_t *v)          \
{                                   \
    unsigned long tmp;                      \
    int result;                         \
                                    \
    prefetchw(&v->counter);                     \
    __asm__ __volatile__("@ atomic_" #op "\n"           \
"1: ldrex   %0, [%3]\n"                     \
"   " #asm_op " %0, %0, %4\n"                   \
"   strex   %1, %0, [%3]\n"                     \
"   teq %1, #0\n"                       \
"   bne 1b"                         \
    : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)       \
    : "r" (&v->counter), "Ir" (i)                   \
    : "cc");                            \
}

#define ATOMIC_OPS(op, c_op, asm_op)                    \
    ATOMIC_OP(op, c_op, asm_op)                 \
    ATOMIC_OP_RETURN(op, c_op, asm_op)

ATOMIC_OPS(add, +=, add)
ATOMIC_OPS(sub, -=, sub)

ldrex指令和strex指令配对使用,可让总线监控ldrex到strex之间有无其他的实体存取该地址,如果有并发访问,执行strex指令时,第一个寄存器的值被设置为1,否则为0。ldrex和strex的排他性过程不仅适用于多核之间的并发,也适用于同一个核内部并发的情况。

原子类型的定义:

    typedef struct { int counter; } atomic_t;/* 操作接口试用atomic_* */
    typedef struct { long counter; } atomic_long_t;/* 操作接口请使用atomic_long_* */

原子类型初始化:

    #define ATOMIC_INIT(i)      { (i) }
    #define atomic_set(v, i)    ((v)->counter = (i))
    static atomic_t my_counter = ATOMIC_INIT(1);

原子操作接口:

    void atomic_add(int i, atomic_t *v);
    void atomic_sub(int i, atomic_t *v);
    void atomic_inc(atomic_t *v);
    void atomic_dec(atomic_t *v);
    int atomic_inc_return(atomic_t *v);
    int atomic_dec_return(atomic_t *v);
    int atomic_add_return(int i, atomic_t *v);
    int atomic_sub_return(int i, atomic_t *v);
    int atomic_inc_and_test(atomic_t *v);
    int atomic_dec_and_test(atomic_t *v);
    int atomic_sub_and_test(int i, atomic_t *v);
    int atomic_add_negative(int i, atomic_t *v);
    int atomic_xchg(atomic_t *v, int new);
    int atomic_cmpxchg(atomic_t *v, int old, int new);
    int atomic_add_unless(atomic_t *v, int a, int u);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值