From: acevest Date: Fri, 14 Aug 2026 08:53:42 +0000 (+0800) Subject: 完善优先级调度入队策略;task_set_wait 仅改当前任务状态;唤醒抢占统一由 task_set_ready 处理 X-Git-Url: http://repos.zhaoyanbai.com/?a=commitdiff_plain;h=b7ad1823a4a91d7cf9d5f6a6a1d9b33cb2b26f09;p=kernel.git 完善优先级调度入队策略;task_set_wait 仅改当前任务状态;唤醒抢占统一由 task_set_ready 处理 --- diff --git a/include/sched.h b/include/sched.h index 559223f..e1d0166 100644 --- a/include/sched.h +++ b/include/sched.h @@ -38,6 +38,14 @@ typedef struct priority_readyq { uint32_t bitmap[READYQ_BITMAP_WORD_CNT]; } priority_readyq_t; +// 需要关中断执行 +void priority_readyq_enqueue_head(task_t* task); +void priority_readyq_enqueue_tail(task_t* task); +// 需要关中断执行 +void priority_readyq_unlink(task_t* task); + +bool priority_readyq_has_higher_priority_task(int priority); + void task_reset_priority(int priority); void schedule(); diff --git a/include/task.h b/include/task.h index a5887a1..e143b60 100644 --- a/include/task.h +++ b/include/task.h @@ -119,9 +119,8 @@ static inline pid_t sysc_getpid() { #define get_tsk_from_list(p) list_entry((p), Task, list) #define del_tsk_from_list(tsk) list_del((&tsk->list)) -// void task_set_run(task_t* t); void task_set_ready(task_t* t); -void task_set_wait(task_t* t); +void task_set_wait(); // 只有当前进程可以调用 void task_init_lists(task_t* t); diff --git a/kernel/sched.c b/kernel/sched.c index 1c50dea..ddbb8aa 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -125,17 +125,81 @@ void task_reset_priority(int priority) { // 而它在调度器调度运行时已经从队列上取下了 // 运行时不在任何队列上,所以只需要直接调整 + int old_priority = current->priority; + current->priority = priority; // irq_restore(eflags); // 降低优先级应该触发调度 - // 这里简单实现,更复杂的实现,应该是看有没有比priority更高的任务在就绪队列上再决定要不要重新调度 - if (current->priority < priority) { + if ((old_priority < priority) && priority_readyq_has_higher_priority_task(priority)) { set_need_schedule(); } } +static void _priority_readyq_enqueue(task_t* task, bool at_head) { + assert(task != NULL); + + int priority = task->priority; + + assert(priority >= TASK_PRIORITY_MIN); + assert(priority <= TASK_PRIORITY_MAX); + + if (at_head) { + list_add(&task->ready_list, g_priority_readyq.lists + priority); + } else { + list_add_tail(&task->ready_list, g_priority_readyq.lists + priority); + } + + priority_readyq_set_bit(priority); +} + +void priority_readyq_enqueue_head(task_t* task) { + _priority_readyq_enqueue(task, true); +} + +void priority_readyq_enqueue_tail(task_t* task) { + _priority_readyq_enqueue(task, false); +} + +void priority_readyq_unlink(task_t* task) { + assert(task != NULL); + + int priority = task->priority; + + assert(priority >= TASK_PRIORITY_MIN); + assert(priority <= TASK_PRIORITY_MAX); + + assert(!list_empty(&task->ready_list)); + + list_del_init(&task->ready_list); + + if (list_empty(g_priority_readyq.lists + priority)) { + priority_readyq_clear_bit(priority); + } +} + +bool priority_readyq_has_higher_priority_task(int priority) { + assert(priority >= TASK_PRIORITY_MIN); + assert(priority <= TASK_PRIORITY_MAX); + + int end_index = priority / READYQ_BITS_PER_WORD; + int bit_index = priority % READYQ_BITS_PER_WORD; + + for (int i = 0; i < end_index; i++) { + if (g_priority_readyq.bitmap[i] != 0) { + return true; + } + } + + // 虽然bit_index为0的情况下这个if必不满足,但不影响逻辑正确性 + if (g_priority_readyq.bitmap[end_index] & ((1U << bit_index) - 1)) { + return true; + } + + return false; +} + void setup_tasks() { INIT_LIST_HEAD(&all_tasks); // INIT_LIST_HEAD(&ready_tasks); @@ -221,9 +285,19 @@ void schedule() { unsigned long eflags; irq_save(eflags); - // 把自己挂到就绪队列尾部 + // prev->state == TASK_WAIT 的进程也可能走到这里来,因为这还是切换前 if (prev->state == TASK_READY || prev->state == TASK_RUN) { - task_set_ready(prev); + prev->state = TASK_READY; + assert(list_empty(&prev->ready_list)); + if (prev != &root_task) { + // 如果时间片没有耗尽(例如:被高优先级的进程抢占了,或者主动让出CPU),还是把自己挂队列头部,下次还是该优先级第一个被调度,以消耗完全余下的时间片 + // 如果时间片耗尽了,就把自己挂到就绪队列尾部,下次调度时会重新分配时间片 + if (prev->ticks_left > 0) { + priority_readyq_enqueue_head(prev); + } else { + priority_readyq_enqueue_tail(prev); + } + } } next = pick_next_task(); @@ -232,32 +306,13 @@ void schedule() { next = &root_task; next->ticks_left = 1; } else { - list_del_init(&next->ready_list); + priority_readyq_unlink(next); next->state = TASK_RUN; if (next->ticks_left <= 0) { next->ticks_left = TASK_TICKS_PER_QUANTUM; } - if (list_empty(g_priority_readyq.lists + next->priority)) { - priority_readyq_clear_bit(next->priority); - } } -#if 0 - if (list_empty(&ready_tasks)) { - next = &root_task; - goto end; - } - - // 从ready_tasks中选择第一个 - next = list_entry(ready_tasks.next, task_t, ready_list); - - assert(next->state == TASK_READY); - assert(next != &root_task); - -end: - task_set_run(next); -#endif - clear_need_schedule(); if (prev != next) { @@ -277,25 +332,6 @@ void add_task_for_monitor(task_t* tsk) { monitor_tasks[id] = tsk; } -// void task_set_run(task_t* t) { -// assert(t != NULL); - -// // if (t == &root_task) { -// // t->state = TASK_RUN; -// // return; -// // } - -// assert(t->state == TASK_READY); - -// unsigned long eflags; -// irq_save(eflags); - -// list_del_init(&t->ready_list); -// t->state = TASK_RUN; - -// irq_restore(eflags); -// } - void task_set_ready(task_t* t) { assert(t != NULL); if (t == &root_task) { @@ -306,34 +342,27 @@ void task_set_ready(task_t* t) { unsigned long eflags; irq_save(eflags); - // - if (!list_empty(&t->ready_list)) { - list_del_init(&t->ready_list); - } + // 不应该出现重复设置ready的情况 + assert(list_empty(&t->ready_list)); // - assert(t->priority >= TASK_PRIORITY_MIN); - assert(t->priority <= TASK_PRIORITY_MAX); - list_head_t* list = g_priority_readyq.lists + t->priority; - list_add_tail(&t->ready_list, list); - priority_readyq_set_bit(t->priority); + priority_readyq_enqueue_tail(t); t->state = TASK_READY; + if (t->priority < current->priority || current == &root_task) { + set_need_schedule(); + } + irq_restore(eflags); } -void task_set_wait(task_t* t) { - assert(t != NULL); - // printk("task_set_wait %s %d\n", t->name, t->state); - assert(t != &root_task); - - unsigned long eflags; - irq_save(eflags); - - list_del_init(&t->ready_list); - t->state = TASK_WAIT; +void task_set_wait() { + task_t* task = current; + assert(task != NULL); + assert(task != &root_task); + assert(task->state == TASK_RUN); - irq_restore(eflags); + task->state = TASK_WAIT; } void task_init_lists(task_t* t) { diff --git a/kernel/waitq.c b/kernel/waitq.c index a985e61..e1e3b17 100644 --- a/kernel/waitq.c +++ b/kernel/waitq.c @@ -23,7 +23,7 @@ void waitq_sleep(waitq_t* waitq) { assert(task->state != TASK_WAIT); list_add_tail(&task->waitq_list, &waitq->list); - task_set_wait(task); + task_set_wait(); schedule(); } @@ -32,11 +32,6 @@ void waitq_wakeup(waitq_t* waitq, int cnt) { assert(waitq != NULL); assert(cnt >= 0); - // 是否唤醒了优先级更高的任务,如果唤醒就将当前任务标记为需要调度,以便新的高优先级任务更快可以被调度 - bool woken_higher_priority_task = false; - - bool woken = false; - for (int i = 0; ((i < cnt) || (cnt == 0)); i++) { if (list_empty(&waitq->list)) { break; @@ -49,17 +44,6 @@ void waitq_wakeup(waitq_t* waitq, int cnt) { list_del_init(&task->waitq_list); task_set_ready(task); - - woken = true; - - // 当前任务优先级低于唤醒的任务 - if (current->priority > task->priority) { - woken_higher_priority_task = true; - } - } - - if (woken_higher_priority_task || (woken && (current == &root_task))) { - set_need_schedule(); } }