原子操作
2016-03-17 23:15
627 查看
原子操作可以保证对一个整型数据的修改是排他性的。
Linux内核提供了一系列函数来实现内核中的原子操作,这些函数分成两类
位原子操作
整型变量原子操作
不管是哪种原子操作都依赖于底层CPU的原子操作,因此所有这些函数都与CPU架构密切相关。对于ARM处理器而言,底层试用LDREX和STREX指令,比如:
ldrex指令和strex指令配对使用,可让总线监控ldrex到strex之间有无其他的实体存取该地址,如果有并发访问,执行strex指令时,第一个寄存器的值被设置为1,否则为0。ldrex和strex的排他性过程不仅适用于多核之间的并发,也适用于同一个核内部并发的情况。
原子类型的定义:
原子类型初始化:
原子操作接口:
Linux内核提供了一系列函数来实现内核中的原子操作,这些函数分成两类
位原子操作
整型变量原子操作
不管是哪种原子操作都依赖于底层CPU的原子操作,因此所有这些函数都与CPU架构密切相关。对于ARM处理器而言,底层试用LDREX和STREX指令,比如:
/* * ARMv6 UP and SMP safe atomic ops. We use load exclusive and * store exclusive to ensure that these are atomic. We may loop * to ensure that the update happens. */ #define ATOMIC_OP(op, c_op, asm_op) \ static inline void atomic_##op(int i, atomic_t *v) \ { \ unsigned long tmp; \ int result; \ \ prefetchw(&v->counter); \ __asm__ __volatile__("@ atomic_" #op "\n" \ "1: ldrex %0, [%3]\n" \ " " #asm_op " %0, %0, %4\n" \ " strex %1, %0, [%3]\n" \ " teq %1, #0\n" \ " bne 1b" \ : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) \ : "r" (&v->counter), "Ir" (i) \ : "cc"); \ } #define ATOMIC_OPS(op, c_op, asm_op) \ ATOMIC_OP(op, c_op, asm_op) \ ATOMIC_OP_RETURN(op, c_op, asm_op) ATOMIC_OPS(add, +=, add) ATOMIC_OPS(sub, -=, sub)
ldrex指令和strex指令配对使用,可让总线监控ldrex到strex之间有无其他的实体存取该地址,如果有并发访问,执行strex指令时,第一个寄存器的值被设置为1,否则为0。ldrex和strex的排他性过程不仅适用于多核之间的并发,也适用于同一个核内部并发的情况。
原子类型的定义:
typedef struct { int counter; } atomic_t;/* 操作接口试用atomic_* */ typedef struct { long counter; } atomic_long_t;/* 操作接口请使用atomic_long_* */
原子类型初始化:
#define ATOMIC_INIT(i) { (i) } #define atomic_set(v, i) ((v)->counter = (i)) static atomic_t my_counter = ATOMIC_INIT(1);
原子操作接口:
void atomic_add(int i, atomic_t *v); void atomic_sub(int i, atomic_t *v); void atomic_inc(atomic_t *v); void atomic_dec(atomic_t *v); int atomic_inc_return(atomic_t *v); int atomic_dec_return(atomic_t *v); int atomic_add_return(int i, atomic_t *v); int atomic_sub_return(int i, atomic_t *v); int atomic_inc_and_test(atomic_t *v); int atomic_dec_and_test(atomic_t *v); int atomic_sub_and_test(int i, atomic_t *v); int atomic_add_negative(int i, atomic_t *v); int atomic_xchg(atomic_t *v, int new); int atomic_cmpxchg(atomic_t *v, int old, int new); int atomic_add_unless(atomic_t *v, int a, int u);
相关文章推荐
- Linux socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- 神器SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程