该坚持的时候坚持,该妥协的时候妥协,该放弃的时候放弃
分类: LINUX
2015-01-10 23:38:10
所谓原子操作,是指不能被cpu和其他cpu所中断的执行指令或指令流
原子操作需要硬件的支持,因此是架构相关的,其API和原子类型的定义都定义在内核源码树的include/asm/atomic.h文件中,它们都使用汇编语言实现,因为C语言并不能实现这样的操作。
原子操作的实现
CPU基本的原子操作
LOCK前缀
自动带LOCK的指令
CPU平台本身可以保证的原子操作
-读或者写一个字节
-读或者写一个对齐的16-bit数据
-读或者写一个对齐的32-bit数据
-读或者写一个对齐的64-bit数据(64位CPU)
另外:
在32-bit的数据总线上访问一块cache禁止的16位数据(>=Petiunm)
在一个cache line中访问不对其的 16,32,64位数据(>=P6 pamily)
LOCK前缀
-指令前带LOCK前缀迫使CPU做独占的内存访问
-XCHG自动带有LOCK前缀
LOCK在不同CPU版本的实现
-在较老的CPU上,产生LOCK信号以用来锁总线
-在>=P6 family,锁cache line
代码示例:
cmpxchg(ptr.old, new):比较*ptr和old的值,如果相等则*ptr = new.在任何时候该函数返回ptr的初始值.因此,如果想要知道ptr的值是否被New替换,只需要检查其返回值是否与old相等。
自动带LOCK前缀的指令
-xchg
-事物内存(TSX on intel)
可以自定义一块transaction region,然后可以在区域结束的时候原子提交,如果成功提交,则其他CPU可以看到该区域的所有更改,如果提交失败则撤销该区域的所有更改操作,进而转入到程序提供的abort代码。
两种主要的类型
-atomic_t的数据
-bit操作
-其他指令
定义:
atomic_t的操作
-所有的操作都定义在include/linux/atomic.h中以及include/asm/atomic.h中
-常用的atomic操作:
ATOMIC_INIT(i)
atomic_set(v,i)
automic_read(v)
automic_add(i,v)
atomic_sub(i,v)
atomic_inc(v)
atomic_dec(v)
atomic_inc_add_test(v) /*测试新值是否为0*/
atomic_dec_add_test(v)
atomic_xchg(v,new)
atomic_cmpxchg(v,old,new)
atomic_add_negative(i,v) /*测试新值是否为负*/
atomic_add_unless(v,a,u) /*如果v不为u,则v加上a,返回非0,否则直接返回0*/
bit操作
-原子性的位操作
-常用的原子位操作
set_bit(nr, *addr)
clear_bit(nr, *addr)
test_bit(nr, *addr)
change_bit(nr, *addr)
test_and_set_bit(nr, addr) /*测试旧位是否已经设置*/
test_and_clear_bit(nr, *addr)
test_and_change_bit(nr, *addr)
-另外,非原子的位操作
__set_bit(nr, *addr)
__clear_bit(nr, *addr)
test_bit(nr, *addr)
__change_bit(nr, *addr)
__test_and_set_bit(nr, addr) /*测试旧位是否已经设置*/
其他指令(包含原子)
- xchg()
- cmpxchg()
- cmpxchg_double()