原子变量是线程和 ISR 可以不间断地读取和修改的变量。它在 32 位计算机上为 32 位,在 64 位计算机上为 64 位。

概念

可以定义任意数量的原子变量(仅受可用 RAM 的限制)。
使用内核的原子 API 操作原子变量可以保证正确执行所需的操作,即使优先级较高的上下文操作同一变量也是如此。
内核还支持原子变量数组中单个的原子操作。

定义原子变量

原子变量是使用atomic_t类型定义变量。
默认情况下,原子变量初始化为零。但是,可以使用ATOMIC_INIT为其指定不同的值:

  1. atomic_t flags = ATOMIC_INIT(0xFF);

操作原子变量

下面的代码演示如何使用原子变量来跟踪调用函数的次数。

  1. atomic_t call_count;
  2. int call_counting_routine(void)
  3. {
  4. /* increment invocation counter */
  5. atomic_inc(&call_count);
  6. /* do rest of routine's processing */
  7. ...
  8. }

操作原子变量数组

下面的代码演示如何使用原子变量数组实现一组 200 个标志位。

  1. #define NUM_FLAG_BITS 200
  2. ATOMIC_DEFINE(flag_bits, NUM_FLAG_BITS);
  3. /* set specified flag bit & return its previous value */
  4. int set_flag_bit(int bit_position)
  5. {
  6. return (int)atomic_set_bit(flag_bits, bit_position);
  7. }

原子变量的API

API 描述
atomic_test_bit 测试是否设置了目标的位。目标可以是单个原子变量或原子变量数组。
atomic_test_and_clear_bit 判定原子变量的位,并且清除该位
atomic_test_and_set_bit 判定原子变量的位,并且设置该位
atomic_clear_bit 清除原子变量的位
atomic_set_bit 设置原子变量的位
atomic_set_bit_to 以原子方式将位设置为给定值
atomic_cas 在目标上执行原子比较和设置。如果目标的当前值等于old_value,则目标设置为new_value。如果目标的当前值不等于old_value,则目标保持不变。
atomic_ptr_cas 在目标上执行原子指针的比较和设置。如果目标的当前值等于old_value,则目标设置为new_value。如果目标的当前值不等于old_value,则目标保持不变。
atomic_add 原子相加
atomic_sub 原子相减
atomic_inc 原子自增
atomic_dec 原子自减
atomic_get 获取原子值
atomic_ptr_get 获取原子指针值
atomic_set 原子设置值
atomic_ptr_set 原子指针设置值
atomic_clear 清空原子值
atomic_ptr_clear 清空原子指针值
atomic_or 原子按位或
atomic_xor 原子按位异或
atomic_and 原子按位与
atomic_nand 原子按位与取反