10.6临界资源及其简单保护
在我们运行代码的过程中会出现下图现象,一个任务没有打印完任务就被CPU切换了,然后出现打印出错
串行接口输出这部分的代码(临界资源)没有被保护起来
我们保护临界资源有两种方案,PV信号量方案后面学,这次先采用关中断方案
//irq.c
/**
* @brief 进入中断保护
*/
irq_state_t irq_enter_protection (void) {
irq_state_t state = read_eflags();
irq_disable_global();
return state;
}
/**
* @brief 退出中断保护
*/
void irq_leave_protection (irq_state_t state) {
write_eflags(state);
}
//irq.h
typedef uint32_t irq_state_t; //因为eflags是32位,起个别名好标识
//cpu_instr.h
static inline uint32_t read_eflags (void) {
uint32_t eflags;
__asm__ __volatile__("pushfl\n\tpopl %%eax":"=a"(eflags)); //先压到栈里面,然后保存在一个寄存器里面
return eflags;
}
static inline void write_eflags (uint32_t eflags) {
__asm__ __volatile__("pushl %%eax\n\tpopfl"::"a"(eflags));//先将寄存器的值压到栈里面,然后从栈顶拿出来
}
为什么要记录eflags的原值?
因为在进入保护区前不知道是关中断还是开中断,所以要恢复到进入临界区前的状态,所以要记录进入临界区前的eflags值
然后给所有全局变量(GDT表之类的数据结构加上保护代码)