x86使用内敛汇编实现简单的临界段保护

临界资源保护

实现方法

  • 禁用中断
__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屏蔽中断
x86使用内敛汇编实现简单的临界段保护_第1张图片

//临界区管理
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);//退出临界区
}

你可能感兴趣的:(汇编,linux,运维,笔记,服务器)