linux-kernel 3.5.3Tcp系统调用,源码分析5-原子操作

linux的原子操作实现,首先是基本数据结构的定义

typedef struct {
int counter;
} atomic_t;

操作集

#define atomic_dec_return(v) atomic_sub_return(1, (v))
#define atomic_inc_return(v) atomic_add_return(1, (v))
#define atomic64_dec_return(v) atomic64_sub_return(1, (v))
#define atomic64_inc_return(v) atomic64_add_return(1, (v))
#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
#define atomic64_sub_and_test(i,v) (atomic64_sub_return((i), (v)) == 0)
#define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0)
#define atomic64_inc_and_test(v) (atomic64_add_return(1, (v)) == 0)
#define atomic_add(i,v) atomic_add_return((i), (v))
#define atomic_sub(i,v) atomic_sub_return((i), (v))
#define atomic_inc(v) atomic_add(1, (v))
#define atomic_dec(v) atomic_sub(1, (v))
#define atomic64_add(i,v) atomic64_add_return((i), (v))
#define atomic64_sub(i,v) atomic64_sub_return((i), (v))
#define atomic64_inc(v) atomic64_add(1, (v))
#define atomic64_dec(v) atomic64_sub(1, (v))

下面来看看,其中几个操作的实现

#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)

#ifdef CONFIG_SMP
#error SMP not supported on pre-ARMv6 CPUs
#endif

static inline int atomic_add_return(int i, atomic_t *v)
{
unsigned long flags;
int val;
raw_local_irq_save(flags);
val = v->counter;
v->counter = val += i;
raw_local_irq_restore(flags);
return val;
}
#define atomic_add(i, v) (void) atomic_add_return(i, v)

在pre-ARMv6(不支持smp)的硬件上,原子性通过关中断来保证的

还有通过CMPXCHG系列的指令来实现原子操作(IA64)

#define atomic_add(i,v) atomic_add_return((i), (v))

#define atomic_add_return(i,v)
({
int __ia64_aar_i = (i);
(__builtin_constant_p(i)
&& (   (__ia64_aar_i ==  1) || (__ia64_aar_i ==   4)
    || (__ia64_aar_i ==  8) || (__ia64_aar_i ==  16)
    || (__ia64_aar_i == -1) || (__ia64_aar_i ==  -4)
    || (__ia64_aar_i == -8) || (__ia64_aar_i == -16)))
? ia64_fetch_and_add(__ia64_aar_i, &(v)->counter)
: ia64_atomic_add(__ia64_aar_i, v);
})

最终调用的是:

#define ia64_cmpxchg1_acq(ptr, new, old)
({
__u64 ia64_intri_res;
asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));
asm volatile ("cmpxchg1.acq %0=[%1],%2,ar.ccv":
     "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");
ia64_intri_res;
})

对于支持smp的硬件,实现有所不一样,看一看x86的实现:

/**
 * atomic_add_negative - add and test if negative
 * @i: integer value to add
 * @v: pointer of type atomic_t
 *
 * Atomically adds @i to @v and returns true
 * if the result is negative, or false when
 * result is greater than or equal to zero.
 */
static inline int atomic_add_negative(int i, atomic_t *v)
{
unsigned char c;
asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
    : "+m" (v->counter), "=qm" (c)
    : "ir" (i) : "memory");
return c;
}

关于宏LOCK_PREFIX以及具体实现原理,可以参见http://blog.csdn.net/vividonly/article/details/6599502,写的很详细,另外这篇博客还有介绍原子位操作,赞一个



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值