多线程嵌入式软件中的原子操作
Atomic operation in multithreaded embedded software
我一直在用 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位单片机上读写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);
}
感谢您的任何想法。
你的两个问题其实是同一个问题。
32 位 MCU 没有任何意义,除非您反汇编代码并验证该操作确实是 单指令。 C 代码通常不是这种情况。
通常您有 2 条或更多条指令,例如:"load value from stack into register"、"do stuff with register",在这种情况下,您的 MCU 有多少位并不重要。您可以在两条指令之间进行中断或上下文切换。
即使您可以验证机器代码是原子的,这也不一定是稳定的状态。更改代码,添加更多变量,再次 link,突然之间以前是原子的代码不再是原子的,反之亦然。
C 根本无法保证原子性。如果您不信任反汇编,则有一些替代方案:
- C11
_Atomic
。
- 编写内联汇编程序。
- 使用互斥锁或类似的同步机制。
我一直在用 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位单片机上读写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);
}
感谢您的任何想法。
你的两个问题其实是同一个问题。
32 位 MCU 没有任何意义,除非您反汇编代码并验证该操作确实是 单指令。 C 代码通常不是这种情况。
通常您有 2 条或更多条指令,例如:"load value from stack into register"、"do stuff with register",在这种情况下,您的 MCU 有多少位并不重要。您可以在两条指令之间进行中断或上下文切换。
即使您可以验证机器代码是原子的,这也不一定是稳定的状态。更改代码,添加更多变量,再次 link,突然之间以前是原子的代码不再是原子的,反之亦然。
C 根本无法保证原子性。如果您不信任反汇编,则有一些替代方案:
- C11
_Atomic
。 - 编写内联汇编程序。
- 使用互斥锁或类似的同步机制。