From: acevest Date: Wed, 17 Nov 2021 15:59:30 +0000 (+0800) Subject: 添加wait_event用于替换sleep_on X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch02.html?a=commitdiff_plain;h=2d39cd8459c455186a0a445dc91bf86e17bd3423;p=kernel.git 添加wait_event用于替换sleep_on --- diff --git a/include/sched.h b/include/sched.h index c2abf48..6be6203 100644 --- a/include/sched.h +++ b/include/sched.h @@ -16,8 +16,9 @@ #pragma once +#include +#include #include -#include #define FORK_USER 0 #define FORK_KRNL 1 @@ -31,4 +32,10 @@ extern task_union root_task; extern void load_cr3(task_union *tsk); extern list_head_t all_tasks; -extern list_head_t delay_tasks; \ No newline at end of file +extern list_head_t delay_tasks; + +#define set_current_state(st) \ + do { \ + current->state = (st); \ + mb(); \ + } while (0) diff --git a/include/system.h b/include/system.h index a301f3b..7aa46f4 100644 --- a/include/system.h +++ b/include/system.h @@ -76,6 +76,7 @@ extern char gdtr[6], idtr[6]; #define cli() __asm__ __volatile__("cli") #define sti() __asm__ __volatile__("sti") #define nop() asm volatile("nop") +#define mb() asm volatile("" ::: "memory") #define disableIRQ() cli() #define enableIRQ() sti() diff --git a/include/wait.h b/include/wait.h index 2f79426..7fe371a 100644 --- a/include/wait.h +++ b/include/wait.h @@ -32,8 +32,30 @@ typedef struct { #define DECLARE_WAIT_QUEUE(name, tsk) wait_queue_t name = WAIT_QUEUE_INITIALIZER(name, tsk) void init_wait_queue_head(wait_queue_head_t *wqh); -void add_wait_queue(wait_queue_head_t *wqh, wait_queue_t *wq); -void del_wait_queue(wait_queue_head_t *wqh, wait_queue_t *wq); +void add_wait_queue(wait_queue_head_t *head, wait_queue_t *wq); +void del_wait_queue(wait_queue_head_t *head, wait_queue_t *wq); +void __do_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int state); +void __end_wait(wait_queue_head_t *head, wait_queue_t *wq); void sleep_on(wait_queue_head_t *head); void wake_up(wait_queue_head_t *head); + +#define __wait_event(head, condition) \ + do { \ + DECLARE_WAIT_QUEUE(__wait, current); \ + while (1) { \ + __do_wait(head, wa, TASK_WAIT); \ + if ((condition)) { \ + break; \ + } \ + schedule(); \ + } \ + __end_wait(head, &__wait); \ + } while (0) + +#define wait_event(head, condition) \ + do { \ + if (!(condition)) { \ + __wait_event(head, (condition)); \ + } \ + } while (0) diff --git a/kernel/sched.c b/kernel/sched.c index 8b445b1..798fd76 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -16,11 +16,12 @@ #include "sched.h" +#include + #include "assert.h" #include "linkage.h" #include "mm.h" #include "msr.h" -#include "system.h" task_union root_task __attribute__((__aligned__(PAGE_SIZE))); diff --git a/kernel/wait.c b/kernel/wait.c index 1c50eb2..bc59197 100644 --- a/kernel/wait.c +++ b/kernel/wait.c @@ -28,6 +28,24 @@ void del_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) { irq_restore(flags); } +void __do_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int state) { + unsigned long flags; + irq_save(flags); + if (list_empty(&wq->task_list)) { + list_add_tail(&wq->task_list, &head->task_list); + } + set_current_state(state); + irq_restore(flags); +} + +void __end_wait(wait_queue_head_t *head, wait_queue_t *wq) { + set_current_state(TASK_RUNNING); + unsigned long flags; + irq_save(flags); + list_del_init(&wq->task_list); + irq_restore(flags); +} + void sleep_on(wait_queue_head_t *head) { DECLARE_WAIT_QUEUE(wait, current);