我以往写调度器都会用 volatile 修饰标志位,写法非常简单:
volatile uint8_t myflag;
uint8_t ticks;
void Func(void){
++ticks;
if(!(ticks % 5)){
myflag = true;
}
}
void User(void){
if(myflag) {
myflag = false;
//执行任务
}
}
网上普遍观点认为上面这种写法并不安全 —— 缺少内存屏障。正确方案应该使用原子类型,于是我改成了原子变量实现:
atomic_bool myflag = ATOMIC_VAR_INIT(false);
uint8_t ticks;
void Func(void){
++ticks;
if(!(ticks % 5)){
atomic_store(&myflag ,true);
}
}
void User(void){
if(atomic_load(&myflag)) {
atomic_store(&myflag ,false);
//执行任务
}
}
但这套代码无法正常工作,User函数会经常性漏掉标志置位事件,不只是延迟,而是直接丢失一整轮标志。
我试过把原子变量再加 volatile 修饰,也试过atomic_flag,都会丢标志;但老式 volatile 写法却不会丢失任何一次置位。请问问题出在哪里?
|
|