Fork Me on GitHub

源码开放学ARM

LASO - Learn ARM with Source Open

首页         目录索引         资料下载         代码下载         联系作者        
下载PDF打印版本

原子操作

原子操作指的是在执行操作的过程中不会被别的代码路径所中断。
原子操作分类: 整形原子操作、位原子操作。

特点:
1、任何情况下操作都是原子的。
2、都依赖底层CPU的原子操作来实现,所以和CPU架构密切相关。

整形原子操作

定义和实现都在 asm/atomic.h 中。

设置原子变量的值

void atomic_set(atomic_t *v,int i);
设置原子变量的值为i。
atomic_t v=ATOMIC_INIT(0);
定义原子变量v,并初始化为0。

获取原子变量的值

atomic_read(atomic_t *v);
返回原子变量的值

原子变量加减

void atomic_add(int i,atomic_t *v);
原子变量加i
void atomic_sub(int i,atomic_t *v);
原子变量减i

原子变量自增自减

void atomic_inc(atomic_t *v);
void atomic_dec(atomic_t *v);

操作并测试

int atomic_inc_and_test(atomic_t *v);
int atomic_dec_and_test(atomic_t *v);
int atomic_sub_and_test(atomic_t *v);
操作后测试是否为0,为0返回ture,否则返回false

操作并返回

int atomic_add_return(int I,atomic_t *v);
int atomic_sub_return(int I,atomic_t *v);
int atomic_inc_return(atomic_t *v);
int atomic_dec_return(atomic_t *v);
操作后返回新的值。

位原子操作

定义和实现都在 asm/bitops.h 中。

设置位

void set_bit(nr,void *addr)
设置addr指针指向的值的nr位为1。

清除位

void clear_bit(nr,void *addr)
清除addr地址的值nr位为0。

改变位

void change_bit(nr,void *addr)
对addr地址的值第nr位取反。

测试位

test_bit(nr,void *addr)
返回addr地址的值第nr位的值。

测试并操作位

int test_and_set_bit(nr,void *addr)
int test_and_clear_bit(nr,void *addr)
int test_and_change_bit(nr,void *addr)

上述操作等同于先执行test_bit(nr,voidaddr)然后在执行xxx_bit(nr,voidaddr)

原子操作案例

设想在不同CPU运行的两个进程都获取了某个共享资源,并对该共享资源计数都加了一, 现在不 想使用该共享资源了,就需要递减该计数值(共 享资源),可能发生的情况是:

1. CPU A(上的进程,以下同)从内存单元把 当前计数值(2)装载进它的寄存器中; 
2. CPU B从内存单元把当前计数值(2)装载进它的寄存器中。 
3. CPU A在它的寄存器中将计数值递减为1; 
4. CPU B在它的寄存器中将计数值递减为1; 
5. CPU A把修改后的计数值(1)写回内存单元。 
6. CPU B把修改后的计数值(1)写回内存单元。

我们期望内存里的计数值应该是0,然而它却是1。如果该计数值是一个共享资源的引用计数,每个进程都在递减后把该值与0进行比较,从而确定是否需要释放该共享资源。 这时,两个进程都去掉了对该共享资源的引用,但没有一个进程能够释放它–两个进程都推断出:计数值是1,共享资源仍然在被使用。

上一节 | 目录索引 | 下一节

blog comments powered by Disqus