其atomic_t原型如下:
typedef struct {
它是一个只含有一个volatile类型的成员变量的结构体;因此编译器不对相应的值进行访问优化(因为是volatile类型的)。
原子整数操作的使用:
常见的用途是计数器,因为计数器是一个很简单的操作,所以无需复杂的锁机制;能使用原子操作的地方,尽量不使用复杂的锁机制;
1.整型原子操作
1.1 设置源自变量的值
void atomic_set(atomic_t *v,int i); //设置原子变量的的值为i
atomic_t v = ATOMIC_INIT(0); //定义原子变量,并将其初始化为0
1.2 获取元原子变量的值
atomic_read(atomic_t *v); //返回原子变量的值
这是一个宏定义:#define atomic_read(v) (*(volatile int)&(v)->counter)
代码实现:
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
1.3 原子变量加减
void atomic_add(int i,atomic_t *v); //原子变量增加i
void atomic_sub(int i,atomic_t *v); //原子变量减少i
各CPU通过原子操作指令实现。如果CPU不支持,用锁中断方式实现:
//atomic_add_return
raw_local_irq_save(flags);
val = v->counter;
v->counter = val += i;
raw_local_irq_restore(flags);
1.4 原子变量自增、自减
void atomic_inc(atomic_t *v);
void atomic_dec(atomic_t *v);
1.5 操作并测试
int atomic_int_and_test(atomic_t *v);
int atomic_dec_and_test(atomic_t *v);
int atomic_sub_and_test(int i,atomic_t *v);
以上操作后测试其是否为0,为0则返回true,否则返回false。
1.6 操作并返回
int atomic_add_and_return(int i,atomic_t *v);
int atomic_sub_and_return(int i,atomic_t *v);
int atomic_dec_and_return(atomic_t *v);
int atomic_inc_and_return(atomic_t *v);
以上操作后返回新的值。
代码实现:
#define atomic_inc(v) atomic_add(1, v)
#define atomic_dec(v) atomic_sub(1, v)
#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)
#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
#define atomic_inc_return(v) (atomic_add_return(1, v))
#define atomic_dec_return(v) (atomic_sub_return(1, v))
#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
2. 位原子操作
2.1 设置位
void set_bit(nr,void *addr); //设置addr地址的第nr位为1
2.2 清除位
void clear_bit(nr, void *addr); //设置addr地址的第nr位为0
2.3 改变位
void change_bit(nr, void *addr); //反置addr的第nr位
2.4 测试位
void test_bit(nr,void *addr); //返回addr的nr位
2.5 测试并操作位
void test_and_set_bit(nr, void *addr); //设置addr所指对象的第nr位,并返回原先的值
void test_and_clear_bit(nr,void *addr); //清空addr所指对象的第nr位,并返回原先的值
void test_and_change_bit(nr,void *addr); //翻转addr所指对象的第nr位,并返回原先的值
#define set_bit(nr,p) ATOMIC_BITOP_LE(set_bit,nr,p)
#define clear_bit(nr,p) ATOMIC_BITOP_LE(clear_bit,nr,p)
#define change_bit(nr,p) ATOMIC_BITOP_LE(change_bit,nr,p)
#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
#define ATOMIC_BITOP_LE(name,nr,p) \
(__builtin_constant_p(nr) ? \
____atomic_##name(nr, p) : \
_##name##_le(nr,p))
锁实现的版本:
static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
{
unsigned long flags;
unsigned long mask = 1UL << (bit & 31);
p += bit >> 5;
raw_local_irq_save(flags);
*p |= mask;
raw_local_irq_restore(flags);
}
汇编版本: