From 267baa1cb4193a274ffe811b7f43c676e0ae8528 Mon Sep 17 00:00:00 2001 From: acevest Date: Wed, 24 May 2023 14:11:30 +0800 Subject: [PATCH] =?utf8?q?=E5=BC=95=E5=85=A5TASK=5FRUNNING=E7=8A=B6?= =?utf8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/ide.c | 2 +- include/irq.h | 2 + include/printk.h | 2 +- include/sched.h | 2 +- include/system.h | 2 + include/task.h | 11 +++- include/wait.h | 2 +- kernel/assert.c | 7 ++- kernel/clock.c | 5 +- kernel/fork.c | 3 + kernel/interrupts.S | 7 ++- kernel/irq.c | 11 ++++ kernel/sched.c | 143 ++++++++++++++++---------------------------- kernel/syscall.c | 2 +- kernel/task_root.c | 4 +- kernel/task_user.c | 3 +- kernel/wait.c | 3 +- 17 files changed, 100 insertions(+), 111 deletions(-) diff --git a/drivers/ide.c b/drivers/ide.c index 04d0b61..da78c5c 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -558,7 +558,7 @@ volatile uint32_t disk_inter_cnt = 0; void ide_irq_handler(unsigned int irq, pt_regs_t *regs, void *devid) { // printk("ide irq handler %d \n", irq); - printk("ide irq %d handler pci status after interrupt: %x\n", irq, ata_pci_bus_status()); + printk("ide irq %d handler pci status: 0x%02x\n", irq, ata_pci_bus_status()); #if 1 disk_inter_cnt++; diff --git a/include/irq.h b/include/irq.h index f59b776..fc704c7 100644 --- a/include/irq.h +++ b/include/irq.h @@ -59,6 +59,8 @@ int close_irq(unsigned int irq); #define irq_save(x) __asm__ __volatile__("pushfl; popl %0; cli" : "=g"(x)::"memory") +bool irq_enabled(); + #define irq_restore(x) \ do { \ typecheck(unsigned long, x); \ diff --git a/include/printk.h b/include/printk.h index e60bf5b..7337ed4 100644 --- a/include/printk.h +++ b/include/printk.h @@ -36,7 +36,7 @@ enum { MPL_TEST, MPL_X, MPL_DEBUG, - MPL_ROOT, + MPL_TASK_TITLE, MPL_TASK_0, MPL_TASK_1, MPL_TASK_2, diff --git a/include/sched.h b/include/sched.h index c0197dc..73883e3 100644 --- a/include/sched.h +++ b/include/sched.h @@ -23,7 +23,7 @@ #define FORK_USER 0 #define FORK_KRNL 1 -unsigned long schedule(); +void schedule(); void wake_up(wait_queue_head_t *wqh); diff --git a/include/system.h b/include/system.h index 2721475..e54d77d 100644 --- a/include/system.h +++ b/include/system.h @@ -60,6 +60,8 @@ void kfree(void *addr); #define panic(msg, ...) \ do { \ asm("cli;"); \ + printl(MPL_DEBUG, "PANIC:" msg " file:%s function:%s line:%d\n", ##__VA_ARGS__, __FILE__, __FUNCTION__, \ + __LINE__); \ printk("PANIC:" msg " file:%s function:%s line:%d\n", ##__VA_ARGS__, __FILE__, __FUNCTION__, __LINE__); \ while (1) { \ asm("hlt"); \ diff --git a/include/task.h b/include/task.h index 2f39bb3..2e95097 100644 --- a/include/task.h +++ b/include/task.h @@ -26,6 +26,7 @@ enum { TASK_UNUSED, + TASK_RUNNING, TASK_READY, TASK_WAIT, TASK_INITING, @@ -35,6 +36,8 @@ enum { #define TASK_NAME_SIZE 32 +#define TASK_MAX_PRIORITY 200 + typedef union task_union { struct { unsigned long esp0; /* kernel stack */ @@ -44,8 +47,9 @@ typedef union task_union { unsigned long eip; uint32_t ticks; + uint32_t turn; // 时间片用完次数 uint32_t priority; - uint32_t jiffies; + uint64_t jiffies; pid_t pid; pid_t ppid; @@ -63,9 +67,10 @@ typedef union task_union { wait_queue_head_t wait; - unsigned int sched_cnt; + uint32_t sched_cnt; // 被调度换上CPU的次数 + uint32_t sched_keep_cnt; // 时间片到了,但是没有被换出,又重新执行的次数 - int delay_cnt; // debug only + uint64_t delay_jiffies; // debug only }; unsigned char stack[TASK_SIZE]; diff --git a/include/wait.h b/include/wait.h index f985f9a..c54c014 100644 --- a/include/wait.h +++ b/include/wait.h @@ -48,7 +48,7 @@ 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); -unsigned long schedule(); +void schedule(); #define __wait_event(head, condition) \ do { \ DECLARE_WAIT_QUEUE(__wait, current); \ diff --git a/kernel/assert.c b/kernel/assert.c index 0de5c40..639a202 100644 --- a/kernel/assert.c +++ b/kernel/assert.c @@ -13,8 +13,9 @@ #include void assert_fail(char *exp, char *file, unsigned int line, const char *func) { + printl(MPL_DEBUG, "%s:%d: %s: Assertion \'%s\' failed.\n", file, line, func, exp); printk("%s:%d: %s: Assertion \'%s\' failed.\n", file, line, func, exp); - - while (1) - ; + while (1) { + asm("cli;hlt;"); + } } diff --git a/kernel/clock.c b/kernel/clock.c index 432bcd8..f2ce282 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -31,14 +31,15 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { current->jiffies = jiffies; current->ticks--; + assert(current->ticks <= TASK_MAX_PRIORITY); // 防止ticks被减到0后再减溢出 task_union *p = 0; list_head_t *t = 0; list_head_t *pos = 0; list_for_each_safe(pos, t, &all_tasks) { p = list_entry(pos, task_union, list); - if (0 != p->delay_cnt && jiffies > p->delay_cnt && p->state == TASK_WAIT) { - p->delay_cnt = 0; + if (0 != p->delay_jiffies && jiffies > p->delay_jiffies && p->state == TASK_WAIT) { + p->delay_jiffies = 0; p->state = TASK_READY; } } diff --git a/kernel/fork.c b/kernel/fork.c index 3b430d1..6893710 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -87,6 +87,9 @@ int do_fork(pt_regs_t *regs, unsigned long flags) { tsk->ppid = current->pid; tsk->priority = current->priority; tsk->ticks = tsk->priority; + tsk->turn = 0; // + root_task.sched_cnt = 0; + root_task.sched_keep_cnt = 0; pt_regs_t *child_regs = ((pt_regs_t *)(TASK_SIZE + (unsigned long)tsk)) - 1; diff --git a/kernel/interrupts.S b/kernel/interrupts.S index 2c68da2..9be5a24 100644 --- a/kernel/interrupts.S +++ b/kernel/interrupts.S @@ -53,7 +53,7 @@ DEF_IRQ(0,F) .global _irq_handler .extern irq_handler .extern schedule -.extern try_to_reschedule +.extern irq_reenter _irq_handler: SAVE_REGS @@ -70,8 +70,9 @@ _irq_handler: movl %esp, %eax call irq_handler - - call try_to_reschedule + cmpl $0, (irq_reenter) + jnz restore_regs + call schedule restore_regs: RESTORE_REGS diff --git a/kernel/irq.c b/kernel/irq.c index 073ee2c..0dfb65c 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -114,3 +114,14 @@ int request_irq(unsigned int irq, void (*handler)(unsigned int, pt_regs_t *, voi int open_irq(unsigned int irq) { return irq_desc[irq].chip->enable(irq); } int close_irq(unsigned int irq) { return irq_desc[irq].chip->disable(irq); } + +bool irq_enabled() { + uint32_t flags; + __asm__ __volatile__("pushfl; popl %0;" : "=a"(flags)); + + if ((flags & (1 << 9)) != 0) { + return true; + } + + return false; +} \ No newline at end of file diff --git a/kernel/sched.c b/kernel/sched.c index 9f1fb61..4094b95 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -58,6 +58,9 @@ void init_root_task() { root_task.state = TASK_READY; root_task.priority = 7; root_task.ticks = root_task.priority; + root_task.turn = 0; + root_task.sched_cnt = 0; + root_task.sched_keep_cnt = 0; strcpy(root_task.name, "root"); list_add(&root_task.list, &all_tasks); @@ -148,7 +151,7 @@ task_union *find_task(pid_t pid) { static const char *task_state(unsigned int state) { static const char s[][16] = { - " ERROR", "READY", " WAIT", " INIT", " EXIT", + " ERROR", "RUNNING", " READY", " WAIT", " INIT", " EXIT", }; if (state >= TASK_END) { @@ -162,133 +165,91 @@ extern uint32_t disk_request_cnt; extern uint32_t disk_handled_cnt; extern uint32_t disk_inter_cnt; -unsigned long schedule() { +void schedule() { task_union *root = &root_task; task_union *sel = 0; task_union *p = 0; list_head_t *pos = 0, *t = 0; + printl(MPL_X, "disk req %u consumed %u irq %u", disk_request_cnt, disk_handled_cnt, disk_inter_cnt); + + assert(current->ticks <= TASK_MAX_PRIORITY); + assert(current->priority <= TASK_MAX_PRIORITY); + unsigned long iflags; irq_save(iflags); - // printl(MPL_ROOT, "root:%d [%08x] cnt %u", root_task.pid, &root_task, root_task.cnt); - printl(MPL_X, "disk req %u consumed %u irq %u", disk_request_cnt, disk_handled_cnt, disk_inter_cnt); + if (TASK_RUNNING == current->state) { + if (0 == current->ticks) { + current->turn++; + current->ticks = current->priority; + current->state = TASK_READY; + } else { + irq_restore(iflags); + return; + } + } -#if 1 list_for_each_safe(pos, t, &all_tasks) { p = list_entry(pos, task_union, list); + + assert(p->state != TASK_RUNNING); + if (p == &root_task) { continue; } - if (p->state != TASK_READY) { + + if (TASK_READY != p->state) { continue; } if (sel == 0) { sel = p; - } else if (sel->jiffies >= p->jiffies) { - uint32_t delta = sel->jiffies - p->jiffies; - if (delta > 3 * p->ticks) { - sel = p; - } - } - } - - sel = sel != 0 ? sel : root; - - irq_restore(iflags); - sel->sched_cnt++; - // printk("%08x %s ticks %d state: %s\n", sel, sel->name, sel->ticks, task_state(sel->state)); - task_union *prev = current; - task_union *next = sel; - - if (prev != next) { - // printk("switch to: %s:%d\n", next->name, next->pid); - list_for_each_safe(pos, t, &all_tasks) { - p = list_entry(pos, task_union, list); - printl(MPL_TASK_0 + p->pid, " "); // 清掉上一次显示的 '>' - printl(MPL_TASK_0 + p->pid, "%s%4s:%d [%08x] state %s ticks %03d %02d sched %u", next == p ? ">" : " ", - p->name, p->pid, p, task_state(p->state), p->ticks, p->priority, p->sched_cnt); - } - context_switch(prev, next); - } -#else - task_union *sel = &root_task; - task_union *p = 0; - list_head_t *pos = 0, *t = 0; - - unsigned long iflags; - irq_save(iflags); - - float min_ratio = 1.0; - bool need_reset_weight = true; - list_for_each_safe(pos, t, &all_tasks) { - p = list_entry(pos, task_union, list); - if (p->state != TASK_READY) { continue; } - if (p->weight < p->priority) { - need_reset_weight = false; - break; - } - } - - if (need_reset_weight) { - list_for_each_safe(pos, t, &all_tasks) { - p = list_entry(pos, task_union, list); - if (p->state != TASK_READY) { - continue; - } - p->weight = 0; - } - } - - list_for_each_safe(pos, t, &all_tasks) { - p = list_entry(pos, task_union, list); - if (p->state != TASK_READY) { + if (sel->jiffies < p->jiffies) { continue; } - // 貌似在Mac的M1上的qemu执行这一句会有问题 - // 所以暂时把这整个逻辑注释掉,写了个简单的替代算法 - float ratio = (float)(p->weight * 1.0) / (p->priority * 1.0); - if (ratio < min_ratio) { - sel = p; - min_ratio = ratio; + uint64_t delta = sel->jiffies - p->jiffies; + + if (sel->priority <= p->priority) { + if (delta > (1 * p->ticks)) { + sel = p; + } + } else if (sel->priority > p->priority) { + if (delta > (5 * p->ticks)) { + sel = p; + } } } - irq_restore(iflags); - sel->sched_cnt++; - sel->ticks += 13; - // printk("%08x %s ticks %d state: %s\n", sel, sel->name, sel->ticks, task_state(sel->state)); task_union *prev = current; - task_union *next = sel; + task_union *next = sel != 0 ? sel : root; + next->state = TASK_RUNNING; if (prev != next) { - // printk("switch to: %s:%d\n", next->name, next->pid); + next->sched_cnt++; + + printl(MPL_TASK_TITLE, " NAME STATE TK/PI TURN SCHED KEEP"); list_for_each_safe(pos, t, &all_tasks) { p = list_entry(pos, task_union, list); - printl(MPL_TASK_0 + p->pid, " "); // 清掉上一次显示的 '>' - printl(MPL_TASK_0 + p->pid, "%s%4s:%d [%08x] state %s ticks %03d %03d sched %u", next == p ? ">" : " ", - p->name, p->pid, p, task_state(p->state), p->ticks, p->priority, p->sched_cnt); + printl(MPL_TASK_0 + p->pid, "%08x%s%4s:%d %s %02u/%02d %-10u %-10u %-10u", p, next == p ? ">" : " ", + p->name, p->pid, task_state(p->state), p->ticks, p->priority, p->turn, p->sched_cnt, + p->sched_keep_cnt); } - context_switch(prev, next); - } -#endif -} -// 必需在关中断的情况下调用 -void try_to_reschedule() { - if (irq_reenter != 0) { - return; + context_switch(prev, next); + } else { + // 这里可能是的情况是任务把时间片ticks用完了 + // 被设置成READY + // 重新高度,还是选中了该任务 + next->sched_keep_cnt++; } - if (0 == current->ticks) { - current->ticks = current->priority; - schedule(); - } + assert(current->state == TASK_RUNNING); + irq_restore(iflags); } void debug_sched() { diff --git a/kernel/syscall.c b/kernel/syscall.c index 7749781..8292f19 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -58,7 +58,7 @@ int sysc_test() { return 0; } - current->delay_cnt = root_task.sched_cnt % 40; + current->delay_jiffies = root_task.sched_cnt % 40; unsigned long iflags; irq_save(iflags); diff --git a/kernel/task_root.c b/kernel/task_root.c index 6fb8360..7c45487 100644 --- a/kernel/task_root.c +++ b/kernel/task_root.c @@ -141,7 +141,7 @@ void taskC_entry() { while (1) { sysc_wait(2); - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 7; i++) { asm("hlt;"); } } @@ -163,7 +163,7 @@ void root_task_entry() { kernel_task("init", init_task_entry); kernel_task("disk", disk_task_entry); - // kernel_task("user", user_task_entry); + kernel_task("user", user_task_entry); // for (int i = 0; i < 100; i++) { // asm("hlt;"); diff --git a/kernel/task_user.c b/kernel/task_user.c index bcbcda1..1545db9 100644 --- a/kernel/task_user.c +++ b/kernel/task_user.c @@ -43,12 +43,13 @@ void __ring3text__ __attribute__((__aligned__(PAGE_SIZE))) ring3_entry() { // 共享代码会利用保存在栈上的地址返回到sysexit_return_address处 "pushl $0;" "pushl $0;" + "movl $2, %%ebx;" "pushl %%ebp;" "movl %%esp, %%ebp;" "sysenter;" "sysexit_return_address:" : "=a"(__sysc_ret__) - : "a"(SYSC_TEST), "c"(ring3_entry)); + : "a"(SYSC_WAIT), "c"(ring3_entry)); } } diff --git a/kernel/wait.c b/kernel/wait.c index e3d2df5..acbc179 100644 --- a/kernel/wait.c +++ b/kernel/wait.c @@ -129,7 +129,8 @@ int sysc_wait(unsigned long cnt) { unsigned long flags; irq_save(flags); current->state = TASK_WAIT; - current->delay_cnt = jiffies + cnt; + current->delay_jiffies = jiffies + cnt; + irq_restore(flags); schedule(); -- 2.44.0