原子操作

目录

1、原子操作:

2、64位原子操作:

3、原子位操作:


// types.h (include\linux)

  1. typedef struct {
  2. int counter;
  3. } atomic_t;
  4.  
  5. #if defined(CONFIG_64BIT) && !defined(CONFIG_GENERIC_ATOMIC64)
  6. typedef struct {
  7. long counter;
  8. } atomic64_t;
  9. #endif

1、原子操作:

#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相同的时候才把新的取值传入,并返回之前的取值。

  1. static inline int atomic_cmpxchg(atomic_t *v, int old, int new)  
  2. {  
  3.     int ret;  
  4.     unsigned long flags;  
  5.   
  6.     raw_local_irq_save(flags);  
  7.     ret = v->counter;  
  8.     if (likely(ret == old))  
  9.         v->counter = new;  
  10.     raw_local_irq_restore(flags);  
  11.   
  12.     return ret;  
  13. }  

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值不变

  1. static inline int atomic_add_unless(atomic_t *v, int a, int u)  
  2. {  
  3.     int c, old;  
  4.   
  5.     c = atomic_read(v);  
  6.     while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)  
  7.         c = old;  
  8.     return c != u;  
  9. }  

#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);

}

 

2、64位原子操作:

#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)

3、原子位操作:

原子操作中的位操作部分函数如下:

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并且返回结果。

 

 

你可能感兴趣的:(linux,kernel)