临界资源保护
实现方法
- 禁用中断
__attribute__((used)) static inline uint32_t read_eflags (void){uint32_t eflags;ASM_V("pushf\n\tpop %%eax":"=a"(eflags));return eflags;
}
__attribute__((used)) static inline void write_eflags (uint32_t eflags){ASM_V("push %%eax\n\tpopf"::"a"(eflags));
}
EFLAGS的位9是IF位, 为1的时候开启中断, 0屏蔽中断
//临界区管理
irq_state_t irq_enter_protection (void){//记录一下之前的中断是开启的还是关闭的irq_state_t state = read_eflags();state |= EFLAGS_IF;irq_disable_global();return state;
}
void irq_leave_protection (irq_state_t state){//恢复之前的IF状态state |= read_eflags();write_eflags(state);
}
实际使用
//打印的时候串口是一个临界资源
void log_printf(const char * fmt, ...){char str_buf[128];va_list args;//格式化处理kernel_memset(str_buf, '\0', sizeof(str_buf));va_start(args, fmt);kernel_vsprintf(str_buf, fmt, args);va_end(args);const char *p = str_buf;irq_state_t state = irq_enter_protection(); //进入临界while(*p != '\0'){//等待串口忙标志while((inb(COM1_PORT+ 5) & (1<<6))== 0);outb(COM1_PORT, *p++);}//自动换行outb(COM1_PORT, '\r');outb(COM1_PORT, '\n');irq_leave_protection(state);//退出临界区
}