多线程嵌入式软件中的原子操作

时间:2018-05-08 14:21:47

标签: c multithreading embedded rtos

我一直在用C开发基于RTOS的嵌入式软件,我遇到了一些关于来自多个线程的共享资源访问的问题。我有两个问题。第一个是在状态机中设置和获取状态变量的值。下面是StateMachine的头文件" object":

typedef enum{
  STATE_01,
  STATE_02,
  STATE_03,
  STATE_04
}state_e;

// state machine instance
typedef struct{
  state_e currState;
}StateMachine;

extern state_e GetState(StateMachine*);
extern void SetState(StateMachine*, state_e);

访问方法的实现如下:

state_e GetState(StateMachine *sm){
  return sm->currState;
}

void SetState(StateMachine *sm, state_e state){
  sm->currState = state;
}

我的问题是我不确定是否应该使用互斥锁来控制对状态变量的访问。我的意思是在32位MCU上读取和写入32位变量是原子操作。

第二个问题涉及读取包含无符号32位整数的数组的一个项的值,其中每个位存储一位变量的值。 在这里,我不确定是否有必要使用互斥锁。出于与上述相同的原因,我认为没有,但我想听听一些更有经验的程序员的意见。位数组的关联头文件" object":

typedef struct{
  uint32_t BitsArray[NO_WORDS];
}BitsArray;

extern uint32_t GetWordValue(BitsArray*, uint8_t);

访问方法实现:

uint32_t GetWordValue(BitsArray *ba, uint8_t word){
 return *(ba->BitsArray + word);
}

感谢您的任何想法。

1 个答案:

答案 0 :(得分:4)

你的两个问题都是同样的问题。

除非您反汇编代码并验证操作确实是单指令,否则32位MCU意味着什么。 C代码通常不是这种情况。

通常你有两个或更多的指令,如:“从堆栈加载值到寄存器”,“用寄存器做的东西”,在这种情况下,你的MCU有多少位无关紧要。您可以在两条指令之间进行中断或上下文切换。

即使您可以验证机器代码是原子的,也不一定是稳定状态。对代码进行更改,添加更多变量,再次链接,突然之前原子代码不再是原子的,反之亦然。反之亦然。

C根本无法保证原子性。如果您不信任反汇编,可以选择一些替代方案:

  • C11 _Atomic
  • 编写内联汇编程序。
  • 使用互斥或​​类似的同步机制。