]> Zhao Yanbai Git Server - kernel.git/commitdiff
完善优先级调度入队策略;task_set_wait 仅改当前任务状态;唤醒抢占统一由 task_set_ready 处理 master
authoracevest <zhaoyanbai@126.com>
Fri, 14 Aug 2026 08:53:42 +0000 (16:53 +0800)
committeracevest <zhaoyanbai@126.com>
Fri, 14 Aug 2026 08:53:42 +0000 (16:53 +0800)
include/sched.h
include/task.h
kernel/sched.c
kernel/waitq.c

index 559223f0c0c88f918f84d12ecb2c81543465fef8..e1d016614cd700c713ab5cbd1e5ba2fbdd4b5a79 100644 (file)
@@ -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();
index a5887a1d0e41c14abc7c3e0b40c6aa9e19e0bca5..e143b6004c9d23a04cb5252e3e8517747eb3adca 100644 (file)
@@ -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);
 
index 1c50deaa33239f89bf4d2351add778cc9be698f6..ddbb8aaa4609f81eea134e46469096df0b086353 100644 (file)
@@ -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) {
index a985e6174eecea7ae40a2b1f8ceda4822432f1f7..e1e3b177d833fd5e3e9192c631e7eb8159f8f3aa 100644 (file)
@@ -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();
     }
 }