Chinaunix首页 | 论坛 | 博客
  • 博客访问: 370489
  • 博文数量: 94
  • 博客积分: 3421
  • 博客等级: 中校
  • 技术积分: 919
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-18 16:27
文章分类

全部博文(94)

文章存档

2015年(8)

2013年(6)

2012年(26)

2011年(8)

2010年(26)

2009年(20)

我的朋友

分类: LINUX

2010-07-20 20:07:45

原子性不可能由软件单独保证--必须需要硬件的支持,因此是和架构相关的。在x86平台上,CPU提供了在指令执行期间对 总线加锁的手段。CPU芯片上有一条引线#HLOCK pin,如果汇编语言的程序中在一条指令前面加上前缀"LOCK",经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低,持续到这条指令结束时放开,从而把总线锁住,这样同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中 的原子性。

Linux内核中的原子操作
Linux 2.4.21中,原子类型的定义和原子操作API都放在内核源码树的include/asm/atomic.h文件中,大部分使用汇编语言实现,因为c语言并不能实现这样的操作。
在x86的原子操作实现代码中,定义了LOCK宏,这个宏可以放在随后的内联汇编指令之前。如果是SMP,LOCK宏被扩展为lock指令;否则被定义为空--单CPU无需防止其它CPU的干扰,锁内存总线完全是在浪费时间。
#ifdef CONFIG_SMP
#define LOCK "lock ; "
#else
#define LOCK ""
#endif

note:一看到atomic_t的定义,就应该知道这是原子操作。

static __inline__ void atomic_add(int i, atomic_t *v)
将v指向的原子变量加上i。该函数不关心原子变量的新值,返回void类型。在下面的实现中,使用了带有C/C++表达式的内联汇编代码,格式如下(参考《AT&T ASM Syntax》):
__asm__ __volatile__("Instruction List" : Output : Input : Clobber/Modify);
__asm__ __volatile__指示编译器原封不动保留表达式中的汇编指令系列,不要考虑优化处理。涉及的约束还包括:
1. 等号约束(=):只能用于输出操作表达式约束,说明括号内的左值表达式v->counter是write-only的。
2. 内存约束(m):表示使用不需要借助寄存器,直接使用内存方式进行输入或输出。
3. 立即数约束(i):表示输入表达式是一个立即数(整数),不需要借助任何寄存器。
4. 寄存器约束(r):表示使用一个通用寄存器,由GCC在%eax/%ax/%al、%ebx/%bx/%bl、%ecx/%cx/%cl和%edx/%dx/%dl中选取一个合适的。
{
__asm__ __volatile__(
    LOCK "addl %1,%0"
    :"=m" (v->counter)
    :"ir" (i), "m" (v->counter));
}
static __inline__ void atomic_sub(int i, atomic_t *v)
从v指向的原子变量减去i。
static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
从v指向的原子变量减去i,并测试是否为0。若为0,返回真,否则返回假。由于x86的subl指令会在结果为0时设置CPU的zero标志位,而且这个 标志位是CPU私有的,不会被其它CPU影响。因此,可以执行一次加锁的减操作,再根据CPU的zero标志位来设置本地变量c,并相应返回。
{
unsigned char c;
__asm__ __volatile__(
    LOCK "subl %2,%0; sete %1"
    :"=m" (v->counter), "=qm" (c)
    :"ir" (i), "m" (v->counter) : "memory");
return c;
}
static __inline__ void atomic_inc(atomic_t *v)
递增v指向的原子变量。
static __inline__ void atomic_dec(atomic_t *v)
递减v指向的原子变量。
static __inline__ int atomic_dec_and_test(atomic_t *v)
递减v指向的原子变量,并测试是否为0。若为0,返回真,否则返回假。
static __inline__ int atomic_inc_and_test(atomic_t *v)
递增v指向的原子变量,并测试是否为0。若为0,返回真,否则返回假。
static __inline__ int atomic_add_negative(int i, atomic_t *v)
将v指向的原子变量加上i,并测试结果是否为负。若为负,返回真,否则返回假。这个操作用于实现semaphore。

阅读(1414) | 评论(0) | 转发(0) |
0

上一篇:typedef的用法

下一篇:自旋锁

给主人留下些什么吧!~~