目录
1、原子操作:
2、64位原子操作:
3、原子位操作:
// types.h (include\linux)
#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ACCESS_ONCE((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
#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)
#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)
int atomic_cmpxchg(atomic_t *ptr, int old, int new) //atomic_cmpxchg需要传入三个参数,当old与v相同的时候才把新的取值传入,并返回之前的取值。
int atomic_add_unless(atomic_t *v, int a, int u) //atomic_add_unless的功能比较特殊。它检查v是否等于u,如果不是则把v的值加上a,返回值表示相加前v是否等于u
返回1:原来的v值和u不相等,并且现在v值+=a
返回0:原来的v值和u相等,v值不变
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) //原来的值不等于0,就加1
应用举例:
static atomic_t nl_table_users = ATOMIC_INIT(0);
atomic_t active_intf_cnt;
int active_cnt = 0;
atomic_set(&active_intf_cnt, 0);
active_cnt = atomic_read(&active_intf_cnt);
atomic_inc(&active_intf_cnt);
atomic_dec(&active_intf_cnt);
if (atomic_dec_return(&active_intf_cnt) != 0) {
atomic_set(&active_intf_cnt, 0);
}
#define ATOMIC64_INIT(i) { (i) }
#define atomic64_read(v) ACCESS_ONCE((v)->counter)
#define atomic64_set(v,i) (((v)->counter) = (i))
#define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0)
#define atomic64_inc(v) atomic64_add(1LL, (v))
#define atomic64_inc_return(v) atomic64_add_return(1LL, (v))
#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
#define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0)
#define atomic64_dec(v) atomic64_sub(1LL, (v))
#define atomic64_dec_return(v) atomic64_sub_return(1LL, (v))
#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL)
int atomic64_add_unless(atomic64_t *v, long a, long u)
原子操作中的位操作部分函数如下:
void set_bit(int nr, void *addr) 原子设置addr所指的第nr位
void clear_bit(int nr, void *addr) 原子的清空所指对象的第nr位
void change_bit(nr, void *addr) 原子的翻转addr所指的第nr位
int test_bit(nr, void *addr) 原子的返回addr位所指对象nr位
int test_and_set_bit(nr, void *addr) 原子设置addr所指对象的第nr位,并返回原先的值
int test_and_clear_bit(nr, void *addr) 原子清空addr所指对象的第nr位,并返回原先的值
int test_and_change_bit(nr, void *addr) 原子翻转addr所指对象的第nr位,并返回原先的值
#define find_first_bit(addr, size) find_next_bit((addr), (size), 0) 返回第一个被置位的位号
#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) 返回第一个未被置位的位号
第一个参数addr是一个指针
第二个参数size是要搜索的总位数
unsigned long word = 0;
set_bit(0, &word); /*第0位被设置*/
set_bit(1, &word); /*第1位被设置*/
clear_bit(1, &word); /*第1位被清空*/
change_bit(0, &word); /*翻转第0位*/
原子操作API包括:
atomic_read(atomic_t * v);
该函数对原子类型的变量进行原子读操作,它返回原子类型的变量v的值。
atomic_set(atomic_t * v, int i);
该函数设置原子类型的变量v的值为i。
void atomic_add(int i, atomic_t *v);
该函数给原子类型的变量v增加值i。
atomic_sub(int i, atomic_t *v);
该函数从原子类型的变量v中减去i。
int atomic_sub_and_test(int i, atomic_t *v);
该函数从原子类型的变量v中减去i,并判断结果是否为0,如果为0,返回真,否则返回假。
void atomic_inc(atomic_t *v);
该函数对原子类型变量v原子地增加1。
void atomic_dec(atomic_t *v);
该函数对原子类型的变量v原子地减1。
int atomic_dec_and_test(atomic_t *v);
该函数对原子类型的变量v原子地减1,并判断结果是否为0,如果为0,返回真,否则返回假。
int atomic_inc_and_test(atomic_t *v);
该函数对原子类型的变量v原子地增加1,并判断结果是否为0,如果为0,返回真,否则返回假。
int atomic_add_negative(int i, atomic_t *v);
该函数对原子类型的变量v原子地增加I,并判断结果是否为负数,如果是,返回真,否则返回假。
int atomic_add_return(int i, atomic_t *v);
该函数对原子类型的变量v原子地增加i,并且返回结果。
int atomic_sub_return(int i, atomic_t *v);
该函数从原子类型的变量v中减去i,并且返回结果。
int atomic_inc_return(atomic_t * v);
该函数对原子类型的变量v原子地增加1并且返回结果。
int atomic_dec_return(atomic_t * v);
该函数对原子类型的变量v原子地减1并且返回结果。