原子操作

centos7中的原子变量-一般使用来作为计数器

定义:include/linux/types.h

typedef struct {
        int counter;
} atomic_t;

#ifdef CONFIG_64BIT
typedef struct {
        long counter;
} atomic64_t;
#endif

是否使用SMP(对称多处理器)

#ifdef CONFIG_SMP

/* we can build all atomic primitives from cmpxchg */

#define ATOMIC_OP(op, c_op)                                             \
static inline void atomic_##op(int i, atomic_t *v)                      \
{                                                                       \
        int c, old;                                                     \
                                                                        \
        c = v->counter;                                                 \
        while ((old = cmpxchg(&v->counter, c, c c_op i)) != c)          \
                c = old;                                                \
}

#define ATOMIC_OP_RETURN(op, c_op)                                      \
static inline int atomic_##op##_return(int i, atomic_t *v)              \
{                                                                       \
        int c, old;                                                     \
                                                                        \
        c = v->counter;                                                 \
        while ((old = cmpxchg(&v->counter, c, c c_op i)) != c)          \
                c = old;                                                \
                                                                        \
        return c c_op i;                                                \
}
#else

#include <linux/irqflags.h>

#define ATOMIC_OP(op, c_op)                                             \
static inline void atomic_##op(int i, atomic_t *v)                      \
{                                                                       \
        unsigned long flags;                                            \
                                                                        \
        raw_local_irq_save(flags);                                      \
        v->counter = v->counter c_op i;                                 \
        raw_local_irq_restore(flags);                                   \
}

#define ATOMIC_OP_RETURN(op, c_op)                                      \
static inline int atomic_##op##_return(int i, atomic_t *v)              \
{                                                                       \
        unsigned long flags;                                            \
        int ret;                                                        \
                                                                        \
        raw_local_irq_save(flags);                                      \
        ret = (v->counter = v->counter c_op i);                         \
        raw_local_irq_restore(flags);                                   \
                                                                        \
        return ret;                                                     \
}

#endif /* CONFIG_SMP */

定义函数:
atomic_add_return
atomic_sub_return
atomic_and
atomic_xor

#ifndef atomic_add_return
ATOMIC_OP_RETURN(add, +)
#endif

#ifndef atomic_sub_return
ATOMIC_OP_RETURN(sub, -)
#endif

#ifndef atomic_and
ATOMIC_OP(and, &)
#endif

#ifndef atomic_or
ATOMIC_OP(or, |)
#endif

#ifndef atomic_xor
ATOMIC_OP(xor, ^)
#endif

依托于上面的基本函数:

#define ATOMIC_INIT(i)  { (i) }  <===初始化

#ifndef atomic_read
#define atomic_read(v)  ACCESS_ONCE((v)->counter)
#endif

#define atomic_set(v, i) (((v)->counter) = (i))

#include <linux/irqflags.h>

static inline int atomic_add_negative(int i, atomic_t *v)
{
        return atomic_add_return(i, v) < 0;
}

static inline void atomic_add(int i, atomic_t *v)
{
        atomic_add_return(i, v);
}

static inline void atomic_sub(int i, atomic_t *v)
{
        atomic_sub_return(i, v);
}

static inline void atomic_inc(atomic_t *v)
{
        atomic_add_return(1, v);
}

static inline void atomic_dec(atomic_t *v)
{
        atomic_sub_return(1, v);
}

#define atomic_dec_return(v)            atomic_sub_return(1, (v))
#define atomic_inc_return(v)            atomic_add_return(1, (v))

#define atomic_sub_and_test(i, v)       (atomic_sub_return((i), (v)) == 0)
#define atomic_dec_and_test(v)          (atomic_dec_return(v) == 0)
#define atomic_inc_and_test(v)          (atomic_inc_return(v) == 0)

#define atomic_xchg(ptr, v)             (xchg(&(ptr)->counter, (v)))
#define atomic_cmpxchg(v, old, new)     (cmpxchg(&((v)->counter), (old), (new)))



针对多处理器(SMP:CONFIG_SMP)

#include <asm-generic/cmpxchg-local.h>

#ifndef cmpxchg_local
#define cmpxchg_local(ptr, o, n)                                               \
        ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
                        (unsigned long)(n), sizeof(*(ptr))))
#endif

#ifndef cmpxchg64_local
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
#endif

#define cmpxchg(ptr, o, n)      cmpxchg_local((ptr), (o), (n))
#define cmpxchg64(ptr, o, n)    cmpxchg64_local((ptr), (o), (n))
static inline unsigned long __cmpxchg_local_generic(volatile void *ptr,
                unsigned long old, unsigned long new, int size)
{
        unsigned long flags, prev;

        /*
         * Sanity checking, compile-time.
         */
        if (size == 8 && sizeof(unsigned long) != 8)
                wrong_size_cmpxchg(ptr);

        raw_local_irq_save(flags);
        switch (size) {
        case 1: prev = *(u8 *)ptr;
                if (prev == old)
                        *(u8 *)ptr = (u8)new;
                break;
        case 2: prev = *(u16 *)ptr;
                if (prev == old)
                        *(u16 *)ptr = (u16)new;
                break;
        case 4: prev = *(u32 *)ptr;
                if (prev == old)
                        *(u32 *)ptr = (u32)new;
                break;
        case 8: prev = *(u64 *)ptr;
                if (prev == old)
                        *(u64 *)ptr = (u64)new;
                break;
        default:
                wrong_size_cmpxchg(ptr);
        }
        raw_local_irq_restore(flags);
        return prev;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值