From 6df4c1b667e29397f235fb1dba79bad4c1d26389 Mon Sep 17 00:00:00 2001 From: acevest Date: Tue, 30 Apr 2024 22:33:41 +0800 Subject: [PATCH 01/16] =?utf8?q?=E7=94=A8semaphore=5Fwaiter=5Ft=E5=AE=9E?= =?utf8?q?=E7=8E=B0down=E5=92=8Cup?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- include/sched.h | 4 +- include/task.h | 12 ++--- include/wait.h | 3 +- kernel/clock.c | 4 +- kernel/exit.c | 2 +- kernel/fork.c | 6 +-- kernel/sched.c | 42 +++++++-------- kernel/semaphore.c | 130 +++++++++------------------------------------ 8 files changed, 62 insertions(+), 141 deletions(-) diff --git a/include/sched.h b/include/sched.h index 7bc55cc..1c6da97 100644 --- a/include/sched.h +++ b/include/sched.h @@ -25,9 +25,9 @@ void schedule(); -extern task_union root_task; +extern task_t root_task; -extern void load_cr3(task_union *tsk); +extern void load_cr3(task_t *tsk); extern list_head_t all_tasks; extern list_head_t delay_tasks; diff --git a/include/task.h b/include/task.h index 795b28e..d47538e 100644 --- a/include/task.h +++ b/include/task.h @@ -72,7 +72,7 @@ typedef union task_union { list_head_t pend; // 某些条件串成一个链表 - list_head_t wait; + // list_head_t wait; uint32_t sched_cnt; // 被调度换上CPU的次数 uint32_t sched_keep_cnt; // 时间片到了,但是没有被换出,又重新执行的次数 @@ -83,12 +83,12 @@ typedef union task_union { }; unsigned char stack[TASK_SIZE]; -} task_union; +} task_t; -task_union *alloc_task_union(); +task_t *alloc_task_t(); -static inline task_union *get_current() { - task_union *tsk; +static inline task_t *get_current() { + task_t *tsk; asm("andl %%esp, %0;" : "=r"(tsk) : "0"(~(TASK_SIZE - 1))); return tsk; } @@ -97,7 +97,7 @@ static inline task_union *get_current() { static inline pid_t sysc_getpid() { return current->pid; } -task_union *find_task(pid_t pid); +task_t *find_task(pid_t pid); #define ROOT_TSK_PID (0) diff --git a/include/wait.h b/include/wait.h index b591ea3..a3fd1c3 100644 --- a/include/wait.h +++ b/include/wait.h @@ -15,14 +15,13 @@ #include #include #include -union task_union; typedef struct wait_queue_head { list_head_t task_list; } wait_queue_head_t; typedef struct { - union task_union *task; + task_t *task; list_head_t task_list; } wait_queue_t; diff --git a/kernel/clock.c b/kernel/clock.c index b104efe..0bcd146 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -53,11 +53,11 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { // 后续放到一个内核任务中去做,需要先把禁止内核抢占做了 const char *task_state(unsigned int state); void clk_bh_handler(void *arg) { - task_union *p = 0; + task_t *p = 0; list_head_t *t = 0; list_head_t *pos = 0; list_for_each_safe(pos, t, &delay_tasks) { - p = list_entry(pos, task_union, pend); + p = list_entry(pos, task_t, pend); // printk("%s state: %s\n", p->name, task_state(p->state)); assert(p->state == TASK_WAIT); assert(p->delay_jiffies != 0); diff --git a/kernel/exit.c b/kernel/exit.c index 44c136f..d57dc41 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -19,7 +19,7 @@ int sysc_exit(int status) { irq_save(flags); current->state = TASK_EXITING; - task_union *t = current; + task_t *t = current; irq_restore(flags); diff --git a/kernel/fork.c b/kernel/fork.c index 27b7037..ab6d887 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -19,15 +19,15 @@ extern pid_t get_next_pid(); extern list_head_t all_tasks; int do_fork(pt_regs_t *regs, unsigned long flags) { - task_union *tsk; - tsk = alloc_task_union(); + task_t *tsk; + tsk = alloc_task_t(); printd("fork task %08x flags %08x\n", tsk, flags); if (tsk == NULL) { panic("can not malloc PCB"); } - memcpy(tsk, current, sizeof(task_union)); + memcpy(tsk, current, sizeof(task_t)); assert(tsk->magic == TASK_MAGIC); diff --git a/kernel/sched.c b/kernel/sched.c index 2f832ab..b2af86e 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -23,7 +23,7 @@ #include "mm.h" #include "msr.h" -task_union root_task __attribute__((__aligned__(PAGE_SIZE))); +task_t root_task __attribute__((__aligned__(PAGE_SIZE))); // 暂时不考虑pid回绕问题 pid_t get_next_pid() { @@ -40,7 +40,7 @@ pid_t get_next_pid() { return pid; } -void load_cr3(task_union *tsk) { LoadCR3(tsk->cr3); } +void load_cr3(task_t *tsk) { LoadCR3(tsk->cr3); } extern pde_t __initdata init_pgd[PDECNT_PER_PAGE] __attribute__((__aligned__(PAGE_SIZE))); @@ -86,7 +86,7 @@ void init_root_task() { printk("init_root_task tss.esp0 %08x\n", tss.esp0); } -kmem_cache_t *task_union_cache; +kmem_cache_t *task_t_cache; void setup_tasks() { INIT_LIST_HEAD(&all_tasks); @@ -94,15 +94,15 @@ void setup_tasks() { init_root_task(); - task_union_cache = kmem_cache_create("task_union", sizeof(task_union), PAGE_SIZE); - if (0 == task_union_cache) { + task_t_cache = kmem_cache_create("task_t", sizeof(task_t), PAGE_SIZE); + if (0 == task_t_cache) { panic("setup tasks failed. out of memory"); } } -task_union *alloc_task_union() { - task_union *task; - task = (task_union *)kmem_cache_alloc(task_union_cache, 0); +task_t *alloc_task_t() { + task_t *task; + task = (task_t *)kmem_cache_alloc(task_t_cache, 0); return task; } @@ -116,7 +116,7 @@ void switch_to() { #endif } -void context_switch(task_union *prev, task_union *next) { +void context_switch(task_t *prev, task_t *next) { unsigned long eax, ebx, ecx, edx, esi, edi; asm volatile( "pushfl;" @@ -135,14 +135,14 @@ void context_switch(task_union *prev, task_union *next) { : "memory"); } -task_union *find_task(pid_t pid) { - task_union *p = 0; +task_t *find_task(pid_t pid) { + task_t *p = 0; list_head_t *pos = 0, *tmp = 0; unsigned long iflags; irq_save(iflags); list_for_each_safe(pos, tmp, &all_tasks) { - p = list_entry(pos, task_union, list); + p = list_entry(pos, task_t, list); if (p->pid == pid) { break; } @@ -165,11 +165,11 @@ const char *task_state(unsigned int state) { } void debug_print_all_tasks() { - task_union *p = 0; + task_t *p = 0; list_head_t *pos = 0, *t = 0; printl(MPL_TASK_TITLE, " NAME STATE TK/PI REASON SCHED KEEP"); list_for_each_safe(pos, t, &all_tasks) { - p = list_entry(pos, task_union, list); + p = list_entry(pos, task_t, list); printl(MPL_TASK_0 + p->pid, "%08x%s%-6s:%u %s %02u/%02u %-10s %-10u %-10u", p, p->state == TASK_RUNNING ? ">" : " ", p->name, p->pid, task_state(p->state), p->ticks, p->priority, p->reason, p->sched_cnt, p->sched_keep_cnt); @@ -177,9 +177,9 @@ void debug_print_all_tasks() { } void schedule() { - task_union *root = &root_task; - task_union *sel = 0; - task_union *p = 0; + task_t *root = &root_task; + task_t *sel = 0; + task_t *p = 0; list_head_t *pos = 0, *t = 0; assert(current->ticks <= TASK_MAX_PRIORITY); @@ -198,7 +198,7 @@ void schedule() { } list_for_each_safe(pos, t, &all_tasks) { - p = list_entry(pos, task_union, list); + p = list_entry(pos, task_t, list); if (p == &root_task) { continue; @@ -230,8 +230,8 @@ void schedule() { } } - task_union *prev = current; - task_union *next = sel != 0 ? sel : root; + task_t *prev = current; + task_t *next = sel != 0 ? sel : root; next->state = TASK_RUNNING; next->reason = ""; @@ -252,6 +252,6 @@ void schedule() { } void debug_sched() { - task_union *p = list_entry(current->list.next, task_union, list); + task_t *p = list_entry(current->list.next, task_t, list); p->state = (p->state == TASK_READY) ? TASK_WAIT : TASK_READY; } diff --git a/kernel/semaphore.c b/kernel/semaphore.c index c7ff128..6000451 100644 --- a/kernel/semaphore.c +++ b/kernel/semaphore.c @@ -10,40 +10,46 @@ #include #include +typedef struct semaphore_waiter { + list_head_t list; + task_t *task; + + // 在Linux内核中这个结构体有一个up字段,这个字段的作用是防止进程被错误地唤醒 + // 例如 + // 如果一个进程在等待信号量时收到了一个信号(signal),它可能会被内核唤醒以处理这个信号。 + // 但是,如果这个进程没有真正获得信号量(即up字段为false)它应该继续等待信号量而不是继续执行 + // 本内核暂时还用不到这个字段 + +} semaphore_waiter_t; + void semaphore_init(semaphore_t *s, unsigned int v) { s->cnt = v; INIT_LIST_HEAD(&(s->wait_list)); } -#if 1 volatile void down(semaphore_t *s) { unsigned long iflags; irq_save(iflags); if (likely(s->cnt > 0)) { s->cnt--; + irq_restore(iflags); } else { - task_union *task = current; - list_add_tail(&task->wait, &s->wait_list); + task_t *task = current; + semaphore_waiter_t waiter; + waiter.task = task; + INIT_LIST_HEAD(&waiter.list); + list_add(&waiter.list, &s->wait_list); + + irq_restore(iflags); task->state = TASK_WAIT; task->reason = "down"; schedule(); } - - irq_restore(iflags); } -// volatile bool try_down(semaphore_t *s) { -// unsigned long iflags; -// irq_save(iflags); - -// // if(s->cnt ) - -// irq_restore(iflags); -// } - volatile void up(semaphore_t *s) { unsigned long iflags; irq_save(iflags); @@ -51,105 +57,21 @@ volatile void up(semaphore_t *s) { if (list_empty(&s->wait_list)) { s->cnt++; } else { - task_union *task = list_first_entry(&s->wait_list, task_union, wait); - list_del(&task->wait); + semaphore_waiter_t *waiter = list_first_entry(&s->wait_list, semaphore_waiter_t, list); + list_del(&waiter->list); + task_t *task = waiter->task; + task->state = TASK_READY; task->reason = "up"; - // 按理这里应该调用schedule再重新调度一次 - // 原因是有可能多个任务都在一个循环里争抢一个锁 - // 如果这里不让当前任务尝试放弃CPU重新调度,则在下一轮循环中它又可能抢到锁 - // 这种情况如果一直发生,就可能导致其它任务一直抢不到 - // - // 但这里为什么又没调用schedule呢? - // 这是因为在目前在ide_irq_bh_handler里调用了up来唤醒磁盘任务 + // 这里不应该调用schedule()再重新调度一次 + // 例如,目前在ide_irq_bh_handler里调用了up来唤醒磁盘任务 // 而ide_irq_bh_handler又是中断的底半处理,不应该切换任务 // 否则会引起irq里的reenter问题,导致不能再进底半处理,也无法切换任务 - // 这里暂时先保持这样,后续再来解决这里 - // schedule(); - } - - irq_restore(iflags); -} - -#else - -typedef struct semaphore_waiter { - list_head_t list; - task_union *task; - int up; -} semaphore_waiter_t; - -#define SEMAPHORE_WAITER_INITIALIZER(name, task) \ - { .list = LIST_HEAD_INIT((name).list), .task = task, .up = 0 } - -#define DECLARE_SEMAPHORE_WAITER(name, task) semaphore_waiter_t name = SEMAPHORE_WAITER_INITIALIZER(name, task) - -volatile void __down(semaphore_t *s) { - task_union *task = current; - DECLARE_SEMAPHORE_WAITER(waiter, task); - list_add_tail(&waiter.list, &s->wait_list); - - while (true) { - task->state = TASK_WAIT; - task->reason = "down"; - schedule(); - - assert(waiter.up == 1); - if (waiter.up) { - break; - } - } -} - -volatile void down(semaphore_t *s) { - unsigned long iflags; - irq_save(iflags); - - if (likely(s->cnt > 0)) { - s->cnt--; - } else { - __down(s); - } - - irq_restore(iflags); -} - -volatile void __up(semaphore_t *s) { - semaphore_waiter_t *waiter = list_first_entry(&s->wait_list, semaphore_waiter_t, list); - list_del(&waiter->list); - waiter->up = 1; - - waiter->task->state = TASK_READY; - waiter->task->reason = "up"; - - // 按理这里应该调用schedule再重新调度一次 - // 原因是有可能多个任务都在一个循环里争抢一个锁 - // 如果这里不让当前任务尝试放弃CPU重新调度,则在下一轮循环中它又可能抢到锁 - // 这种情况如果一直发生,就可能导致其它任务一直抢不到 - // - // 但这里为什么又没调用schedule呢? - // 这是因为在目前在ide_irq_bh_handler里调用了up来唤醒磁盘任务 - // 而ide_irq_bh_handler又是中断的底半处理,不应该切换任务 - // 否则会引起irq里的reenter问题,导致不能再进底半处理,也无法切换任务 - // 这里暂时先保持这样,后续再来解决这里 - // schedule(); -} - -volatile void up(semaphore_t *s) { - unsigned long iflags; - irq_save(iflags); - - // if (likely(list_empty(&s->wait_list))) { - if (list_empty(&s->wait_list)) { - s->cnt++; - } else { - __up(s); } irq_restore(iflags); } -#endif void mutex_lock(semaphore_t *s) { down(s); } void mutex_unlock(semaphore_t *s) { up(s); } -- 2.44.0 From 6df9a0e571cd66abf7ed738ec21dda0f941ca238 Mon Sep 17 00:00:00 2001 From: acevest Date: Fri, 10 May 2024 13:54:23 +0800 Subject: [PATCH 02/16] =?utf8?q?IDE=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/ide.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/ide.c b/drivers/ide.c index f7dab9e..091ae31 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -40,7 +40,13 @@ void ide_pci_init(pci_device_t *pci) { printd("PCI %03d:%02d.%d %02X #%02d %04X:%04X\n", pci->bus, pci->dev, pci->devfn, pci->progif, pci->intr_line, pci->vendor, pci->classcode); - uint32_t iobase = pci_read_config_long(pci_cmd(pci, PCI_BAR4)); + for (int i = 0; i < 6; i++) { + printd("ide pci BAR%u value 0x%08X\n", i, pci->bars[i]); + } + + // BAR4开始有16个端口,有2组,每组8个,分别控制Primary和Secondary通道的DMA + // BAR5: SATA AHCI Base Address + uint32_t iobase = pci->bars[4]; for (int i = 0; i < NR_IDE_CONTROLLER; i++) { INIT_MUTEX(&ide_pci_controller[i].request_mutex); @@ -55,6 +61,9 @@ void ide_pci_init(pci_device_t *pci) { iobase += i * 8; // secondary channel 需要加8 printd("ide pci Base IO Address Register %08x\n", iobase); + // 虽然iobase是uint32_t,但在PC机上最多有65536个端口,也就是有效位数为16bit + // 所以这里用0xFFFC或0xFFFFFFFC其实都可以 + iobase &= 0xFFFC; // 最低为0是内存地址为1是端口地址 ide_pci_controller[i].bus_iobase = iobase; ide_pci_controller[i].bus_cmd = iobase + PCI_IDE_CMD; @@ -62,13 +71,6 @@ void ide_pci_init(pci_device_t *pci) { ide_pci_controller[i].bus_prdt = iobase + PCI_IDE_PRDT; ide_pci_controller[i].prdt = (prdte_t *)alloc_one_page(0); - printd("BARS: "); - for (int j = 0; j < BARS_CNT; ++j) { - printd("%08x ", pci->bars[j]); - pci->bars[j] &= (~1UL); - } - printd("\n"); - ide_pci_controller[i].pci = pci; } -- 2.44.0 From 0141e8ea6e56888f9cc986e131a3de2c8508fb31 Mon Sep 17 00:00:00 2001 From: acevest Date: Fri, 10 May 2024 19:39:20 +0800 Subject: [PATCH 03/16] =?utf8?q?=E4=BC=98=E5=8C=96=E7=AD=89=E5=BE=85?= =?utf8?q?=E9=98=9F=E5=88=97=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- include/wait.h | 24 ++++++++++++++---------- kernel/wait.c | 28 ++++++++++++++-------------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/include/wait.h b/include/wait.h index a3fd1c3..f94a0a7 100644 --- a/include/wait.h +++ b/include/wait.h @@ -22,40 +22,44 @@ typedef struct wait_queue_head { typedef struct { task_t *task; - list_head_t task_list; -} wait_queue_t; + list_head_t entry; +} wait_queue_entry_t; #define WAIT_QUEUE_HEAD_INITIALIZER(name) \ { .task_list = LIST_HEAD_INIT((name).task_list) } #define DECLARE_WAIT_QUEUE_HEAD(name) wait_queue_head_t name = WAIT_QUEUE_HEAD_INITIALIZER(name) -#define WAIT_QUEUE_INITIALIZER(name, tsk) \ - { .task = tsk, .task_list = LIST_HEAD_INIT((name).task_list) } +#define WAIT_QUEUE_ENTRY_INITIALIZER(name, tsk) \ + { .task = tsk, .entry = LIST_HEAD_INIT((name).entry) } -#define DECLARE_WAIT_QUEUE(name, tsk) wait_queue_t name = WAIT_QUEUE_INITIALIZER(name, tsk) +#define DECLARE_WAIT_QUEUE_ENTRY(name, tsk) wait_queue_entry_t name = WAIT_QUEUE_ENTRY_INITIALIZER(name, tsk) void init_wait_queue_head(wait_queue_head_t *wqh); -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 add_wait_queue(wait_queue_head_t *head, wait_queue_entry_t *wq); +void del_wait_queue(wait_queue_head_t *head, wait_queue_entry_t *wq); // prepare_to_wait 不会调用schedule -void prepare_to_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int state); +void prepare_to_wait(wait_queue_head_t *head, wait_queue_entry_t *wq, unsigned int state); -void __end_wait(wait_queue_t *wq); +void __end_wait(wait_queue_entry_t *wq); // 使用这个函数的时候需要注意 // 设置condition为真的语句和wake_up原子地执行 void wake_up(wait_queue_head_t *head); void __wake_up(wait_queue_head_t *head, int nr); +// 以下wait_event被定义成宏,而不是函数是因为condition +// condition可能是一个表达式,如果定义成函数,往下传递就直接变成了一个值 +// 如果在某一步这个值变了,并不会反应在这些逻辑判断上 + // 只要保证condition设置为真时,它是和wake_up一起原子执行的 // 那就能保证condition为真是如下__wait_event和wait_event里的if不出问题 // 也就是不会出现if-break后进程又再次因为其它原因阻塞后,又被wake_up的逻辑 // 设置为READY状态 #define __wait_event(head, condition) \ do { \ - DECLARE_WAIT_QUEUE(__wait, current); \ + DECLARE_WAIT_QUEUE_ENTRY(__wait, current); \ while (1) { \ prepare_to_wait(head, &__wait, TASK_WAIT); \ if ((condition)) { \ diff --git a/kernel/wait.c b/kernel/wait.c index 0ee1d13..6ddb303 100644 --- a/kernel/wait.c +++ b/kernel/wait.c @@ -14,43 +14,43 @@ volatile void init_wait_queue_head(wait_queue_head_t *wqh) { INIT_LIST_HEAD(&wqh->task_list); } -volatile void prepare_to_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int state) { +volatile void prepare_to_wait(wait_queue_head_t *head, wait_queue_entry_t *wqe, unsigned int state) { unsigned long flags; irq_save(flags); - if (list_empty(&wq->task_list)) { - list_add_tail(&wq->task_list, &head->task_list); + if (list_empty(&wqe->entry)) { + list_add_tail(&wqe->entry, &head->task_list); } set_current_state(state); irq_restore(flags); } -volatile void __end_wait(wait_queue_t *wq) { +volatile void __end_wait(wait_queue_entry_t *wqe) { set_current_state(TASK_READY); unsigned long flags; irq_save(flags); - list_del_init(&wq->task_list); + list_del_init(&wqe->entry); irq_restore(flags); } -volatile void add_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) { +volatile void add_wait_queue(wait_queue_head_t *head, wait_queue_entry_t *wqe) { unsigned long flags; irq_save(flags); - list_add_tail(&wq->task_list, &head->task_list); + list_add_tail(&wqe->entry, &head->task_list); irq_restore(flags); } -volatile void del_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) { +volatile void del_wait_queue(wait_queue_head_t *head, wait_queue_entry_t *wqe) { unsigned long flags; irq_save(flags); - list_del(&wq->task_list); + list_del(&wqe->entry); irq_restore(flags); } volatile void __wake_up(wait_queue_head_t *head, int nr) { unsigned long flags; - wait_queue_t *p, *tmp; + wait_queue_entry_t *p, *tmp; irq_save(flags); - list_for_each_entry_safe(p, tmp, &head->task_list, task_list) { + list_for_each_entry_safe(p, tmp, &head->task_list, entry) { p->task->state = TASK_READY; current->reason = "wake_up"; @@ -66,11 +66,11 @@ volatile void __wake_up(wait_queue_head_t *head, int nr) { volatile void wake_up(wait_queue_head_t *head) { // - __wake_up(head, 1); + __wake_up(head, 0); // wake up all } volatile void wait_on(wait_queue_head_t *head) { - DECLARE_WAIT_QUEUE(wait, current); + DECLARE_WAIT_QUEUE_ENTRY(wait, current); unsigned long flags; irq_save(flags); @@ -78,7 +78,7 @@ volatile void wait_on(wait_queue_head_t *head) { current->state = TASK_WAIT; current->reason = "sleep_on"; - list_add_tail(&wait.task_list, &head->task_list); + list_add_tail(&wait.entry, &head->task_list); irq_restore(flags); -- 2.44.0 From 52eb50383a52f76f0d70d5df5bea27a528aceeb2 Mon Sep 17 00:00:00 2001 From: acevest Date: Fri, 10 May 2024 22:01:50 +0800 Subject: [PATCH 04/16] =?utf8?q?=E4=BF=AE=E5=A4=8D=E6=9C=AA=E6=AD=A3?= =?utf8?q?=E7=A1=AE=E5=88=9D=E5=A7=8B=E5=8C=968253=E7=9A=84=E9=97=AE?= =?utf8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- kernel/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/clock.c b/kernel/clock.c index 0bcd146..6c7ac63 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -81,7 +81,7 @@ void setup_i8253(uint16_t hz) { const uint8_t read_write_latch = 3; // 0 锁存数据供CPU读;1只读写低字节;2只读写高字节;3先读写低字节,后读写高字节 const uint8_t mode = 2; // - const uint8_t cmd = (counter_no << 6) | (read_write_latch << 4) || (mode << 1); // 第0位为0表示二进制,为1表示BCD + const uint8_t cmd = (counter_no << 6) | (read_write_latch << 4) | (mode << 1); // 第0位为0表示二进制,为1表示BCD const uint8_t i8253_cmd_port = 0x43; const uint8_t i8253_data_port = 0x40 + counter_no; -- 2.44.0 From 92624ca65653e45e28b27ed05a506d7c24063094 Mon Sep 17 00:00:00 2001 From: acevest Date: Sat, 11 May 2024 09:40:36 +0800 Subject: [PATCH 05/16] =?utf8?q?=E8=A7=A3=E5=86=B3task=5Ft.ticks=E5=8F=AF?= =?utf8?q?=E8=83=BD=E8=A2=AB=E6=97=B6=E9=92=9F=E4=B8=AD=E6=96=AD=E5=87=8F?= =?utf8?q?=E4=B8=BA=E8=B4=9F=E6=95=B0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- boot/boot.c | 4 +-- include/task.h | 2 +- kernel/clock.c | 72 ++++++++++++++++++++++++++++++++++++---------- kernel/irq.c | 2 +- kernel/sched.c | 15 ++++------ kernel/setup.c | 4 +-- kernel/syscall.c | 24 +++++++++------- kernel/task_init.c | 2 +- kernel/task_root.c | 2 +- 9 files changed, 85 insertions(+), 42 deletions(-) diff --git a/boot/boot.c b/boot/boot.c index f7ad9f0..7498796 100644 --- a/boot/boot.c +++ b/boot/boot.c @@ -53,7 +53,7 @@ void setup_gdt(); void setup_idt(); void setup_gates(); void set_tss(); -void setup_i8253(uint16_t); +void setup_i8254(uint16_t); void setup_boot_irqs(); void check_kernel(unsigned long addr, unsigned long magic) { @@ -78,7 +78,7 @@ void check_kernel(unsigned long addr, unsigned long magic) { setup_boot_irqs(); - setup_i8253(100); + setup_i8254(100); boot_delay(DEFAULT_BOOT_DELAY_TICKS); diff --git a/include/task.h b/include/task.h index d47538e..30f96de 100644 --- a/include/task.h +++ b/include/task.h @@ -48,7 +48,7 @@ typedef union task_union { uint32_t esp; uint32_t eip; - uint32_t ticks; + int ticks; uint32_t turn; // 时间片用完次数 uint32_t priority; uint64_t jiffies; diff --git a/kernel/clock.c b/kernel/clock.c index 6c7ac63..e78622f 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -36,15 +36,24 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { current->jiffies = jiffies; // 中断目前虽然不能嵌套,但依然可以打断前一个中断的下半部分处理 - // 若前一个时钟中断将这个值减到0 - // 同时其下半部分处理时间过长,直到这个时钟中断还没处理完 - // 那么这个时钟中断是完全可以打断它,且在这里把这个ticks从0减到负数 - // 而这个是uint32_t型,因此会溢出成0xFFFFFFFF - if (current->ticks > 0) { - current->ticks--; + // 若前一个时钟中断将这个值减到0,会将该进程设置为need_resched,同时分配新的时间片值,以在下半部处理完后再重新调度就绪进程运行 + // 而如果其下半部分需要处理的事情很多,处理时间过长,两个时钟中断之间的时间还不足以处理完 + // 那么下一个时钟中断是完全可以打断还没处理完的下半部逻辑 + // 打断后该时钟中断不应该继续减少该进程的时间片,因为这会造成该进程在后续的调底中少了实际的运行时间 + if (1 == current->need_resched) { + // 这种情况必然已经发生了该时钟中断打断了下半部处理程序 + return; } - assert(current->ticks <= TASK_MAX_PRIORITY); // 防止ticks被减到0后再减溢出 + current->ticks--; + + if (0 == current->ticks) { + current->need_resched = 1; + current->ticks = current->priority; + current->turn++; + } + + assert(current->ticks >= 0); // 防止ticks被减到0后再减溢出 add_irq_bh_handler(clk_bh_handler, NULL); } @@ -73,23 +82,56 @@ void clk_bh_handler(void *arg) { debug_print_all_tasks(); } -void setup_i8253(uint16_t hz) { - // 最低频率为18.2Hz(1193180/65536,最大计数值是65536是因为往计数器里写0就从65536开始计数) +uint16_t read_i8254_counter(uint8_t counter_no) { + const uint8_t i8254_cmd_port = 0x43; + const uint8_t i8254_data_port = 0x40 + counter_no; + + assert(counter_no < 3); + + uint8_t cmd = 0x00; + cmd |= 0x03 << 6; // read back command + cmd |= 0x01 << 4; // don't latch status + cmd |= 0x01 << (counter_no + 1); // read back timer channel n + + uint16_t value = 0; + + outb_p(cmd, i8254_cmd_port); + + value |= inb(i8254_data_port) << 0; + value |= inb(i8254_data_port) << 8; + + return value; +} + +void setup_i8254(uint16_t hz) { + // PC/AT 8254的连接方法 + // 第0个计数器连连到了8259A的IRQ0 + // 第1个计数器连连到了DRAM刷新电路,通常情况下,该通道的频率设置为15.2kHz + // 第2个计数器连连到了音频驱动单元,可以通过频率控制发声 + + // 8254的最低频率为18.2Hz(1193180/65536,最大计数值是65536是因为往计数器里写0就从65536开始计数) assert(hz >= 19); const uint8_t counter_no = 0; // 第0个计数器 const uint8_t read_write_latch = 3; // 0 锁存数据供CPU读;1只读写低字节;2只读写高字节;3先读写低字节,后读写高字节 const uint8_t mode = 2; // + const uint8_t BCD = 0; // 0 二进制;1 BCD码 - const uint8_t cmd = (counter_no << 6) | (read_write_latch << 4) | (mode << 1); // 第0位为0表示二进制,为1表示BCD + const uint8_t cmd = + ((counter_no & 0x03) << 6) | ((read_write_latch & 0x03) << 4) | ((mode & 0x07) << 1) | ((BCD & 0x01) << 0); - const uint8_t i8253_cmd_port = 0x43; - const uint8_t i8253_data_port = 0x40 + counter_no; + const uint8_t i8254_cmd_port = 0x43; + const uint8_t i8254_data_port = 0x40 + counter_no; const uint32_t clock_rate = 1193180; uint16_t latch = (clock_rate + hz / 2) / hz; - outb_p(cmd, i8253_cmd_port); - outb_p(latch & 0xFF, i8253_data_port); - outb(latch >> 8, i8253_data_port); + // 必须先写控制命令,再写入初始计数值 + outb_p(cmd, i8254_cmd_port); + outb_p((latch >> 0) & 0xFF, i8254_data_port); + outb_p((latch >> 8) & 0xFF, i8254_data_port); + + // for (uint8_t i = 0; i < 3; i++) { + // printk("i8254 counter%u value %u\n", i, read_i8254_counter(i)); + // } } diff --git a/kernel/irq.c b/kernel/irq.c index b6f6a5b..b25f382 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -136,7 +136,7 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { reenter--; // 考察如果不需要调度程序,直接退出 - if (current->ticks != 0) { + if (current->need_resched == 0) { return; } diff --git a/kernel/sched.c b/kernel/sched.c index b2af86e..86d9105 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -167,12 +167,12 @@ const char *task_state(unsigned int state) { void debug_print_all_tasks() { task_t *p = 0; list_head_t *pos = 0, *t = 0; - printl(MPL_TASK_TITLE, " NAME STATE TK/PI REASON SCHED KEEP"); + printl(MPL_TASK_TITLE, " NAME STATE TK/PI REASON SCHED KEEP TURN"); list_for_each_safe(pos, t, &all_tasks) { p = list_entry(pos, task_t, list); - printl(MPL_TASK_0 + p->pid, "%08x%s%-6s:%u %s %02u/%02u %-10s %-10u %-10u", p, + printl(MPL_TASK_0 + p->pid, "%08x%s%-6s:%u %s %02u/%02u %-10s %-10u %-10u %-10u", p, p->state == TASK_RUNNING ? ">" : " ", p->name, p->pid, task_state(p->state), p->ticks, p->priority, - p->reason, p->sched_cnt, p->sched_keep_cnt); + p->reason, p->sched_cnt, p->sched_keep_cnt, p->turn); } } @@ -182,17 +182,12 @@ void schedule() { task_t *p = 0; list_head_t *pos = 0, *t = 0; - assert(current->ticks <= TASK_MAX_PRIORITY); + assert(current->ticks >= 0); assert(current->priority <= TASK_MAX_PRIORITY); unsigned long iflags; irq_save(iflags); - if (0 == current->ticks) { - current->turn++; - current->ticks = current->priority; - } - if (current->state == TASK_RUNNING) { current->state = TASK_READY; } @@ -233,6 +228,8 @@ void schedule() { task_t *prev = current; task_t *next = sel != 0 ? sel : root; + prev->need_resched = 0; + next->state = TASK_RUNNING; next->reason = ""; diff --git a/kernel/setup.c b/kernel/setup.c index 12e2314..a44c169 100644 --- a/kernel/setup.c +++ b/kernel/setup.c @@ -24,7 +24,7 @@ extern void init_buffer(); extern void setup_gdt(); extern void setup_idt(); extern void setup_gate(); -void setup_i8253(uint16_t hz); +void setup_i8254(uint16_t hz); extern void detect_cpu(); extern void setup_sysc(); extern void setup_pci(); @@ -87,7 +87,7 @@ void setup_kernel() { boot_delay(DEFAULT_BOOT_DELAY_TICKS); - setup_i8253(100); + setup_i8254(100); setup_irqs(); void ide_init(); diff --git a/kernel/syscall.c b/kernel/syscall.c index 9979ce1..c1f5c01 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -43,20 +43,24 @@ int sysc_none() { extern uint64_t jiffies; -// 特别说明:如果想把这个函数的参数ticks改为uint64_t +// 特别说明:如果想把这个函数的参数ticks改为int64_t // 那么就需要在编写用户级的系统调用库函数的时候注意 // 不仅需要填写 ebx,还要填写 ecx // 不然就可能出现诡异的一直WAIT,不会调度到该任务的问题 -int sysc_wait(uint32_t ticks) { - unsigned long flags; - irq_save(flags); - current->state = TASK_WAIT; - current->reason = "sysc_wait"; - current->delay_jiffies = jiffies + ticks; - list_add(¤t->pend, &delay_tasks); - irq_restore(flags); - +int sysc_wait(int ticks) { + if (ticks < 0) { + return -EINVAL; + } else { + unsigned long flags; + irq_save(flags); + current->state = TASK_WAIT; + current->reason = "sysc_wait"; + current->delay_jiffies = jiffies + ticks; + list_add(¤t->pend, &delay_tasks); + irq_restore(flags); + } schedule(); + return 0; } int sysc_test() {} diff --git a/kernel/task_init.c b/kernel/task_init.c index 30753e7..7064470 100644 --- a/kernel/task_init.c +++ b/kernel/task_init.c @@ -9,7 +9,7 @@ #include #include #include -int sysc_wait(uint32_t ticks); +int sysc_wait(int ticks); void init_task_entry() { current->priority = 10; diff --git a/kernel/task_root.c b/kernel/task_root.c index 9ea4224..528f3a9 100644 --- a/kernel/task_root.c +++ b/kernel/task_root.c @@ -22,7 +22,7 @@ #include int do_fork(pt_regs_t *regs, unsigned long flags); -int sysc_wait(uint32_t ticks); +int sysc_wait(int ticks); #define get_eflags(x) __asm__ __volatile__("pushfl; popl %0;" : "=g"(x)::"memory") -- 2.44.0 From 205a80455296cb90dea06c23bebedeedd63bb3a2 Mon Sep 17 00:00:00 2001 From: acevest Date: Sat, 11 May 2024 19:05:29 +0800 Subject: [PATCH 06/16] =?utf8?q?=E6=97=B6=E9=92=9F=E4=B8=AD=E6=96=AD?= =?utf8?q?=E6=89=93=E6=96=AD=E4=BA=86=E4=B8=8B=E5=8D=8A=E9=83=A8=E9=80=BB?= =?utf8?q?=E8=BE=91=E7=9A=84=E6=83=85=E5=86=B5=E4=B8=8B=E4=B8=8D=E5=86=8D?= =?utf8?q?=E6=B7=BB=E5=8A=A0=E4=B8=8B=E5=8D=8A=E9=83=A8=E5=A4=84=E7=90=86?= =?utf8?q?=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- kernel/clock.c | 5 ++++- kernel/irq.c | 11 ++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/kernel/clock.c b/kernel/clock.c index e78622f..66b6764 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -42,6 +42,7 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { // 打断后该时钟中断不应该继续减少该进程的时间片,因为这会造成该进程在后续的调底中少了实际的运行时间 if (1 == current->need_resched) { // 这种情况必然已经发生了该时钟中断打断了下半部处理程序 + // 反之时钟中断打断了下半部处理程序不一定need_resched就为1 return; } @@ -55,7 +56,9 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { assert(current->ticks >= 0); // 防止ticks被减到0后再减溢出 - add_irq_bh_handler(clk_bh_handler, NULL); + if (reenter == 0) { + add_irq_bh_handler(clk_bh_handler, NULL); + } } // 开中断执行这个函数 diff --git a/kernel/irq.c b/kernel/irq.c index b25f382..2b03adb 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -77,6 +77,8 @@ void dump_irq_nr_stack() { void irq_bh_handler(); void schedule(); +volatile int reenter_count = 0; + __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { unsigned int irq = regs->irq; if (irq >= NR_IRQS) { @@ -86,8 +88,11 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { irq_desc_t *p = irq_desc + irq; irq_action_t *action = p->action; - assert(irq_disabled()); reenter++; + reenter_count += reenter == 0 ? 0 : 1; + assert(irq_disabled()); + assert(reenter >= 0); + assert(reenter <= 1); // 屏蔽当前中断 p->chip->disable(irq); @@ -100,8 +105,8 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { #if 1 unsigned long esp; asm("movl %%esp, %%eax" : "=a"(esp)); - printl(MPL_CURRENT, "current %08x %-6s cr3 %08x reenter %d esp %08x ticks %u", current, current->name, current->cr3, - reenter, esp, current->ticks); + printl(MPL_CURRENT, "current %08x %-6s cr3 %08x reenter %d:%u esp %08x ticks %u", current, current->name, + current->cr3, reenter, reenter_count, esp, current->ticks); #endif while (action && action->handler) { -- 2.44.0 From 9a038ef28319536cbfd5c83b7528799b03c701b1 Mon Sep 17 00:00:00 2001 From: acevest Date: Sat, 11 May 2024 19:06:06 +0800 Subject: [PATCH 07/16] =?utf8?q?=E4=BF=AE=E5=A4=8Dwake=5Fup=E9=97=AE?= =?utf8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- kernel/wait.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/wait.c b/kernel/wait.c index 6ddb303..bb4fd0f 100644 --- a/kernel/wait.c +++ b/kernel/wait.c @@ -12,7 +12,7 @@ #include #include -volatile void init_wait_queue_head(wait_queue_head_t *wqh) { INIT_LIST_HEAD(&wqh->task_list); } +volatile void init_wait_queue_head(wait_queue_head_t *wqh) { INIT_LIST_HEAD(&(wqh->task_list)); } volatile void prepare_to_wait(wait_queue_head_t *head, wait_queue_entry_t *wqe, unsigned int state) { unsigned long flags; @@ -51,8 +51,12 @@ volatile void __wake_up(wait_queue_head_t *head, int nr) { wait_queue_entry_t *p, *tmp; irq_save(flags); list_for_each_entry_safe(p, tmp, &head->task_list, entry) { + assert(p->task != NULL); + printk("wakeup %s\n", p->task->name); p->task->state = TASK_READY; - current->reason = "wake_up"; + p->task->reason = "wake_up"; + + list_del(&p->entry); --nr; if (nr == 0) { -- 2.44.0 From fceec7b5bbbf745b9e9559d2b8dcc571cbe5db7a Mon Sep 17 00:00:00 2001 From: acevest Date: Sat, 11 May 2024 19:07:24 +0800 Subject: [PATCH 08/16] =?utf8?q?=E4=BF=AE=E5=A4=8Ddisk=5Frequest=5Ft.bb?= =?utf8?q?=E5=AD=97=E6=AE=B5=E6=9C=AA=E5=88=9D=E5=A7=8B=E5=8C=96=E7=9A=84?= =?utf8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/ata.c | 2 +- kernel/semaphore.c | 1 + kernel/task_root.c | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/ata.c b/drivers/ata.c index 8feb182..a751cd9 100644 --- a/drivers/ata.c +++ b/drivers/ata.c @@ -226,7 +226,7 @@ void tmp_ide_disk_read(dev_t dev, uint32_t sect_nr, uint32_t count, char *buf) { // mbr_ext_offset: 在MBR中的扩展分区记录里的偏移地址 // lba_partition_table: 扩展分区的真实偏移地址 void read_partition_table(ide_drive_t *drv, uint32_t mbr_ext_offset, uint32_t lba_partition_table, int depth) { - disk_request_t r; + // disk_request_t r; char *sect = kmalloc(SECT_SIZE, 0); #if 1 diff --git a/kernel/semaphore.c b/kernel/semaphore.c index 6000451..19b08b5 100644 --- a/kernel/semaphore.c +++ b/kernel/semaphore.c @@ -58,6 +58,7 @@ volatile void up(semaphore_t *s) { s->cnt++; } else { semaphore_waiter_t *waiter = list_first_entry(&s->wait_list, semaphore_waiter_t, list); + assert(waiter != 0); list_del(&waiter->list); task_t *task = waiter->task; diff --git a/kernel/task_root.c b/kernel/task_root.c index 528f3a9..c7eeead 100644 --- a/kernel/task_root.c +++ b/kernel/task_root.c @@ -112,6 +112,8 @@ void taskA_entry() { r.pos = sect_nr; r.count = 1; r.buf = disk_buf1; + r.bb = 0; + send_disk_request(&r); // verify_hd_data(sect_nr, disk_buf1, current->name); @@ -135,8 +137,10 @@ void taskB_entry() { r.pos = sect_nr; r.count = 1; r.buf = disk_buf2; + r.bb = 0; + send_disk_request(&r); - // verify_hd_data(sect_nr, disk_buf2, current->name); + // verify_hd_data(sect_nr, disk_buf2, current->name); for (int i = 0; i < 1; i++) { asm("hlt;"); -- 2.44.0 From 90c0d73ac87873c0ceab96deffde8c19ee089133 Mon Sep 17 00:00:00 2001 From: acevest Date: Sat, 11 May 2024 21:05:52 +0800 Subject: [PATCH 09/16] =?utf8?q?RUNNING=E6=94=B9=E4=B8=BARUN?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- include/task.h | 2 +- kernel/sched.c | 19 +++++++++---------- kernel/task_disk.c | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/include/task.h b/include/task.h index 30f96de..eebbf8d 100644 --- a/include/task.h +++ b/include/task.h @@ -26,7 +26,7 @@ enum { TASK_UNUSED, - TASK_RUNNING, + TASK_RUN, TASK_READY, TASK_WAIT, TASK_INITING, diff --git a/kernel/sched.c b/kernel/sched.c index 86d9105..b74cbe6 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -153,8 +153,8 @@ task_t *find_task(pid_t pid) { } const char *task_state(unsigned int state) { - static const char s[][16] = { - " ERROR", "RUNNING", " READY", " WAIT", " INIT", " EXIT", + static const char s[][8] = { + " ERROR", "\x10RUN\x07\x07", " READY", " WAIT ", " INIT ", " EXIT ", }; if (state >= TASK_END) { @@ -167,12 +167,11 @@ const char *task_state(unsigned int state) { void debug_print_all_tasks() { task_t *p = 0; list_head_t *pos = 0, *t = 0; - printl(MPL_TASK_TITLE, " NAME STATE TK/PI REASON SCHED KEEP TURN"); + printl(MPL_TASK_TITLE, " NAME STATE TK/PI REASON SCHED KEEP TURN"); list_for_each_safe(pos, t, &all_tasks) { p = list_entry(pos, task_t, list); - printl(MPL_TASK_0 + p->pid, "%08x%s%-6s:%u %s %02u/%02u %-10s %-10u %-10u %-10u", p, - p->state == TASK_RUNNING ? ">" : " ", p->name, p->pid, task_state(p->state), p->ticks, p->priority, - p->reason, p->sched_cnt, p->sched_keep_cnt, p->turn); + printl(MPL_TASK_0 + p->pid, "%08x %-6s:%u %s %02u/%02u %-10s %-10u %-10u %-10u", p, p->name, p->pid, + task_state(p->state), p->ticks, p->priority, p->reason, p->sched_cnt, p->sched_keep_cnt, p->turn); } } @@ -188,7 +187,7 @@ void schedule() { unsigned long iflags; irq_save(iflags); - if (current->state == TASK_RUNNING) { + if (current->state == TASK_RUN) { current->state = TASK_READY; } @@ -199,7 +198,7 @@ void schedule() { continue; } - assert(p->state != TASK_RUNNING); + assert(p->state != TASK_RUN); if (TASK_READY != p->state) { continue; @@ -230,7 +229,7 @@ void schedule() { prev->need_resched = 0; - next->state = TASK_RUNNING; + next->state = TASK_RUN; next->reason = ""; if (prev != next) { @@ -243,7 +242,7 @@ void schedule() { next->sched_keep_cnt++; } - assert(current->state == TASK_RUNNING); + assert(current->state == TASK_RUN); irq_restore(iflags); } diff --git a/kernel/task_disk.c b/kernel/task_disk.c index ae22190..43697e5 100644 --- a/kernel/task_disk.c +++ b/kernel/task_disk.c @@ -59,7 +59,7 @@ void disk_task_entry(void *arg) { int channel = (int)arg; ide_pci_controller_t *ide_ctrl = ide_pci_controller + channel; - // 为了在DEBUG时看到RUNNING + // 为了在DEBUG时看到RUN int cnt = 2; for (int i = 0; i < cnt; i++) { asm("hlt;"); -- 2.44.0 From 40a46ae2c7fa62a5e7d1315b8f46010fc0807fbc Mon Sep 17 00:00:00 2001 From: acevest Date: Sat, 11 May 2024 22:37:44 +0800 Subject: [PATCH 10/16] =?utf8?q?=E6=B7=BB=E5=8A=A0rdmsr?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- include/msr.h | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/include/msr.h b/include/msr.h index 41ee5cd..7348d77 100644 --- a/include/msr.h +++ b/include/msr.h @@ -17,13 +17,39 @@ #ifndef _MSR_H #define _MSR_H +#include + #define MSR_SYSENTER_CS 0x174 #define MSR_SYSENTER_ESP 0x175 #define MSR_SYSENTER_EIP 0x176 +#define MSR_IA32_PERF_STATUS 0x198 +#define MSR_IA32_PERF_CRTL 0x199 + +#define rdmsr(msr, lowval, highval) \ + do { \ + asm("rdmsr;" : "=a"(lowval), "=d"(highval) : "c"(msr)); \ + } while (0) + #define wrmsr(msr, lowval, highval) \ do { \ asm("wrmsr;" ::"c"(msr), "a"(lowval), "d"(highval)); \ - } while (0); + } while (0) + +static inline uint64_t read_msr(uint32_t msr) { + uint32_t lowval = 0; + uint32_t highval = 0; + + rdmsr(msr, lowval, highval); + + return ((uint64_t)highval << 32) | lowval; +} + +static inline void write_msr(uint32_t msr, uint64_t value) { + uint32_t lowval = value & 0xFFFFFFFF; + uint32_t highval = value >> 32; + + wrmsr(msr, lowval, highval); +} #endif //_MSR_H -- 2.44.0 From 6d85d68496639b97e8f9c1d88655633bf66986cf Mon Sep 17 00:00:00 2001 From: acevest Date: Sat, 11 May 2024 22:40:01 +0800 Subject: [PATCH 11/16] =?utf8?q?=E4=BB=A5=E6=9B=B4=E7=BB=86=E7=9A=84?= =?utf8?q?=E7=B2=92=E5=BA=A6=E5=88=A4=E6=96=AD=E6=AF=8F=E8=BD=AE=E4=B8=8B?= =?utf8?q?=E5=8D=8A=E9=83=A8=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91=E6=98=AF?= =?utf8?q?=E5=90=A6=E8=B6=85=E6=97=B6=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- kernel/irq.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/kernel/irq.c b/kernel/irq.c index 2b03adb..74d6f47 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -151,10 +151,27 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { extern uint32_t jiffies; void irq_bh_handler() { - uint32_t end = jiffies + 2; + uint32_t end = jiffies + 1; while (true) { irq_bh_action_t *action = NULL; +#if 1 + disable_irq(); + action = irq_bh_actions; + if (action == NULL) { + enable_irq(); + break; + } + + irq_bh_actions = action->next; + if (irq_bh_actions == NULL) { + irq_bh_actions_end = NULL; + } + enable_irq(); + + action->handler(action->arg); + kfree(action); +#else disable_irq(); action = irq_bh_actions; @@ -173,7 +190,7 @@ void irq_bh_handler() { action = action->next; kfree(p); } - +#endif if (jiffies >= end) { break; } @@ -227,6 +244,9 @@ int request_irq(unsigned int irq, void (*handler)(unsigned int, pt_regs_t *, voi void add_irq_bh_handler(void (*handler)(), void *arg) { // 只能在中断处理函数中调用 assert(irq_disabled()); + assert(reenter >= 0); + + // 本函数不用考虑临界问题 irq_bh_action_t *p; p = (irq_bh_action_t *)kmalloc(sizeof(irq_bh_action_t), 0); -- 2.44.0 From 4b5e498185470c1fd6d1778ce0128174eb55dad7 Mon Sep 17 00:00:00 2001 From: acevest Date: Wed, 15 May 2024 19:59:48 +0800 Subject: [PATCH 12/16] =?utf8?q?=E6=B7=BB=E5=8A=A0=E5=87=8F=E7=BC=93?= =?utf8?q?=E7=B3=BB=E7=BB=9F=E8=BF=90=E8=A1=8C=E7=9A=84=E8=B0=83=E8=AF=95?= =?utf8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- Makefile | 1 + kernel/clock.c | 13 ++++-- kernel/irq.c | 106 ++++++++++++++++++++++++++++++++++--------------- kernel/sched.c | 24 +++++++++-- 4 files changed, 106 insertions(+), 38 deletions(-) diff --git a/Makefile b/Makefile index 533d351..b2c8ab4 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ CFLAGS += -fcf-protection=none CFLAGS += -DNR_TTYS=3 CFLAGS += -DFIXED_SYSENTER_ESP_MODE=1 CFLAGS += -DENABLE_BOOT_WAIT=0 +CFLAGS += -DENABLE_CLOCK_IRQ_WAIT=0 SYSTEMMAP = System.map KERNELBIN = KERNEL.ELF diff --git a/kernel/clock.c b/kernel/clock.c index 66b6764..97a16a5 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -25,10 +25,13 @@ void debug_print_all_tasks(); void dump_irq_nr_stack(); void clk_bh_handler(void *arg); +extern volatile bool enable_clock_irq_delay; + void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { // if (jiffies % 100 == 0) { // printl(MPL_CLOCK, "clock irq: %d", jiffies); printlxy(MPL_IRQ, MPO_CLOCK, "CLK irq: %d", jiffies); + // printk("CLK irq %d\n", jiffies); // } jiffies++; @@ -46,6 +49,13 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { return; } +#if ENABLE_CLOCK_IRQ_WAIT + if (enable_clock_irq_delay) { + return; + } + enable_clock_irq_delay = true; +#endif + current->ticks--; if (0 == current->ticks) { @@ -80,9 +90,6 @@ void clk_bh_handler(void *arg) { p->reason = "clk_bh"; } } - - // 此处调用这个还是有问题的 - debug_print_all_tasks(); } uint16_t read_i8254_counter(uint8_t counter_no) { diff --git a/kernel/irq.c b/kernel/irq.c index 74d6f47..d688d15 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -79,6 +79,8 @@ void schedule(); volatile int reenter_count = 0; +volatile uint32_t clk_irq_cnt = 0; + __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { unsigned int irq = regs->irq; if (irq >= NR_IRQS) { @@ -100,6 +102,16 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { // 发送EOI p->chip->ack(irq); +#if 0 + if (0x00 == irq) { + if ((clk_irq_cnt++ & 0xFU) != 0) { + reenter--; + p->chip->enable(irq); + return; + } + } +#endif + assert(current->magic == TASK_MAGIC); #if 1 @@ -150,54 +162,86 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { } extern uint32_t jiffies; + +volatile bool enable_clock_irq_delay = false; + void irq_bh_handler() { uint32_t end = jiffies + 1; - while (true) { - irq_bh_action_t *action = NULL; + +// ENABLE_CLOCK_IRQ_WAIT是用来调试的 +// 是为了让时钟减缓进程的时间片更慢一点,以便于调试 +// 采用这种方式,而不是经过一定时钟数再减一次进程时间片的方法 +// 是因为这种方法只能让时间片减得慢,但会拉长进程的实际运行时间,效果不真实 +// 这种方法不会改变进程的运行时间 +#if ENABLE_CLOCK_IRQ_WAIT + uint32_t debug_end = jiffies + 20; + while (jiffies < debug_end) +#endif + { + while (true) { + irq_bh_action_t *action = NULL; #if 1 - disable_irq(); - action = irq_bh_actions; - if (action == NULL) { + disable_irq(); + action = irq_bh_actions; + if (action == NULL) { + enable_irq(); + break; + } + + irq_bh_actions = action->next; + if (irq_bh_actions == NULL) { + irq_bh_actions_end = NULL; + } enable_irq(); - break; - } - irq_bh_actions = action->next; - if (irq_bh_actions == NULL) { + action->handler(action->arg); + kfree(action); +#else + disable_irq(); + + action = irq_bh_actions; + irq_bh_actions = NULL; irq_bh_actions_end = NULL; - } - enable_irq(); - action->handler(action->arg); - kfree(action); -#else - disable_irq(); + enable_irq(); - action = irq_bh_actions; - irq_bh_actions = NULL; - irq_bh_actions_end = NULL; + if (action == NULL) { + break; + } - enable_irq(); + while (action != NULL) { + action->handler(action->arg); + irq_bh_action_t *p = action; + action = action->next; + kfree(p); + } +#endif + + if (jiffies >= end) { + break; + } - if (action == NULL) { - break; + // 这里可能存在有部分没处理完 } - while (action != NULL) { - action->handler(action->arg); - irq_bh_action_t *p = action; - action = action->next; - kfree(p); + void debug_print_all_tasks(); +#if ENABLE_CLOCK_IRQ_WAIT + debug_print_all_tasks(); + if (irq_bh_actions == NULL) { + asm("hlt;"); } -#endif - if (jiffies >= end) { - break; +#else + if (jiffies < end) { + debug_print_all_tasks(); } - - // 这里可能存在有部分没处理完 +#endif } +#if ENABLE_CLOCK_IRQ_WAIT + enable_clock_irq_delay = false; +#endif + // 这之后也可能存在再次被中断加入下半部处理请求 // 但这些都不会丢失 // 而是会延迟到这次中断返回后下一次的中断的下半部分处理逻辑 diff --git a/kernel/sched.c b/kernel/sched.c index b74cbe6..cace86f 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -154,7 +154,7 @@ task_t *find_task(pid_t pid) { const char *task_state(unsigned int state) { static const char s[][8] = { - " ERROR", "\x10RUN\x07\x07", " READY", " WAIT ", " INIT ", " EXIT ", + " ERROR", "\x10\x07RUN\x07", " READY", " WAIT ", " INIT ", " EXIT ", }; if (state >= TASK_END) { @@ -209,19 +209,35 @@ void schedule() { continue; } +#if 1 + if (p->priority > sel->priority) { + sel = p; + } else if (p->priority == sel->priority) { + int64_t a = p->jiffies + (p->priority - p->ticks); + int64_t b = sel->jiffies + (sel->priority - sel->ticks); + if (a < b) { + sel = p; + } + } +#endif +#if 0 // 考察三个量 // priority 越大越优先 // jiffies 越小越优先 // (priority - ticks) 表示已经使用的量,越小越优先 - int64_t a = sel->jiffies - sel->priority + (sel->priority - sel->ticks); - int64_t b = p->jiffies - p->priority + (p->priority - p->ticks); - if (a > b) { + // 实际简化表达式为 ticks - jiffies(选择最大的) + // 先这样写,后续可以在各项添加系数 + // 这个方法的缺点是对后面新加入的进程非常不友好 + int64_t a = sel->priority - sel->jiffies - (sel->priority - sel->ticks); + int64_t b = p->priority - p->jiffies - (p->priority - p->ticks); + if (a < b) { sel = p; } else if (a == b) { if (sel->priority < p->priority) { sel = p; } } +#endif } task_t *prev = current; -- 2.44.0 From 51e4c85ca53a84381d3d92180d636d4ab47cabb5 Mon Sep 17 00:00:00 2001 From: acevest Date: Mon, 15 Jul 2024 20:11:08 +0800 Subject: [PATCH 13/16] =?utf8?q?=E4=BF=AE=E5=A4=8D=E4=BF=A1=E5=8F=B7?= =?utf8?q?=E9=87=8F=E7=9A=84down=E9=80=BB=E8=BE=91=E5=8F=AF=E8=83=BD?= =?utf8?q?=E5=BC=95=E8=B5=B7=E8=B0=83=E5=BA=A6=E5=BC=82=E5=B8=B8=E7=9A=84?= =?utf8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- kernel/semaphore.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/semaphore.c b/kernel/semaphore.c index 19b08b5..a38696c 100644 --- a/kernel/semaphore.c +++ b/kernel/semaphore.c @@ -41,11 +41,11 @@ volatile void down(semaphore_t *s) { INIT_LIST_HEAD(&waiter.list); list_add(&waiter.list, &s->wait_list); - irq_restore(iflags); - task->state = TASK_WAIT; task->reason = "down"; + irq_restore(iflags); + schedule(); } } -- 2.44.0 From bf778f66604a78636b26cf70bea414aea1003aa9 Mon Sep 17 00:00:00 2001 From: acevest Date: Tue, 23 Jul 2024 19:57:59 +0800 Subject: [PATCH 14/16] =?utf8?q?=E4=BF=AE=E5=A4=8D=5F=5Fwait=5Fevent?= =?utf8?q?=E7=9A=84bug;=E7=A1=AC=E7=9B=98=E4=B8=AD=E6=96=AD=E9=80=9A?= =?utf8?q?=E7=9F=A5disk=E8=BF=9B=E7=A8=8B=E6=94=B9=E7=94=A8=E5=AE=8C?= =?utf8?q?=E6=88=90=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/ide.c | 7 +++--- drivers/ide.h | 8 ++----- fs/buffer.c | 8 +++++-- include/completion.h | 9 ++++++-- include/wait.h | 54 +++++++++++++++++++++++++++++++++----------- kernel/completion.c | 12 ++++++---- kernel/irq.c | 1 + kernel/task_disk.c | 5 ++-- kernel/wait.c | 24 +++++--------------- 9 files changed, 77 insertions(+), 51 deletions(-) diff --git a/drivers/ide.c b/drivers/ide.c index 091ae31..2761631 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -53,7 +53,8 @@ void ide_pci_init(pci_device_t *pci) { ide_pci_controller[i].request_queue.count = 0; INIT_LIST_HEAD(&ide_pci_controller[i].request_queue.list); semaphore_init(&ide_pci_controller[i].request_queue.sem, 0); - semaphore_init(&ide_pci_controller[i].disk_intr_sem, 0); + init_completion(&ide_pci_controller[i].intr_complete); + ide_pci_controller[i].intr_complete.name = i == 0 ? "ide0_intr_complete" : "ide1_intr_complete"; atomic_set(&ide_pci_controller[i].request_cnt, 0); atomic_set(&ide_pci_controller[i].irq_cnt, 0); @@ -142,8 +143,8 @@ void ide_irq_bh_handler(void *arg) { printlxy(MPL_IDE0 + channel, MPO_IDE, "IDE%d req %u irq %u consumed %u", channel, atomic_read(&(ide_ctrl->request_cnt)), ide_ctrl->irq_cnt, ide_ctrl->consumed_cnt); - // up里不会立即重新调度进程 - up(&ide_ctrl->disk_intr_sem); + // complete会唤醒进程,但不会立即重新调度进程 + complete(&ide_ctrl->intr_complete); } void ide_irq_handler(unsigned int irq, pt_regs_t *regs, void *devid) { diff --git a/drivers/ide.h b/drivers/ide.h index 91a7c5d..ea90706 100644 --- a/drivers/ide.h +++ b/drivers/ide.h @@ -184,9 +184,8 @@ typedef struct _ide_pci_controller { // 请求队列 disk_request_queue_t request_queue; - // task disk与中断函数之间的信号量 - // 初始化成0 - semaphore_t disk_intr_sem; + // 中断处理函数通知task disk任务完成 + completion_t intr_complete; atomic_t request_cnt; atomic_t irq_cnt; @@ -212,6 +211,3 @@ typedef struct _ide_drive { extern ide_drive_t ide_drives[MAX_IDE_DRIVE_CNT]; ide_drive_t *ide_get_drive(dev_t dev); - -void sleep_on_ide(); -void wait_on_ide(); diff --git a/fs/buffer.c b/fs/buffer.c index a754b5a..823d38f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -124,7 +124,9 @@ again: irq_restore(iflags); retry++; // wait on free list - wait_on(&s->waitq); + // TODO + assert(0); + // wait_on(&s->waitq); goto again; } @@ -156,7 +158,9 @@ void brelse(bbuffer_t *b) { assert(s != NULL); assert(s - store < 3); - wake_up(&s->waitq); + // TODO + assert(0); + // wake_up(&s->waitq); } bbuffer_t *bread(dev_t dev, uint64_t block, uint32_t size) { diff --git a/include/completion.h b/include/completion.h index 93afe91..a367a86 100644 --- a/include/completion.h +++ b/include/completion.h @@ -12,14 +12,19 @@ #include typedef struct completion { - int done; + volatile int done; wait_queue_head_t wait; + + // 仅用于调试 + char *name; } completion_t; #define COMPLETION_INITIALIZER(x) \ { 0, WAIT_QUEUE_HEAD_INITIALIZER(x).wait } -void wait_completion(completion_t *x); void init_completion(completion_t *x); +void wait_completion(completion_t *x); + +// 一次只唤醒一个进程 void complete(completion_t *x); diff --git a/include/wait.h b/include/wait.h index f94a0a7..2f726d4 100644 --- a/include/wait.h +++ b/include/wait.h @@ -46,17 +46,46 @@ void __end_wait(wait_queue_entry_t *wq); // 使用这个函数的时候需要注意 // 设置condition为真的语句和wake_up原子地执行 +// wake_up只唤醒不立即重新调度 void wake_up(wait_queue_head_t *head); + +// nr == 0 代表唤醒所有 void __wake_up(wait_queue_head_t *head, int nr); // 以下wait_event被定义成宏,而不是函数是因为condition // condition可能是一个表达式,如果定义成函数,往下传递就直接变成了一个值 // 如果在某一步这个值变了,并不会反应在这些逻辑判断上 +#define __wait_event(head, condition) \ + do { \ + DECLARE_WAIT_QUEUE_ENTRY(__wait, current); \ + unsigned long flags; \ + while (1) { \ + irq_save(flags); \ + prepare_to_wait(head, &__wait, TASK_WAIT); \ + if ((condition)) { \ + __end_wait(&__wait); \ + irq_restore(flags); \ + break; \ + } else { \ + irq_restore(flags); \ + void schedule(); \ + schedule(); \ + __end_wait(&__wait); \ + } \ + } \ + } while (0) -// 只要保证condition设置为真时,它是和wake_up一起原子执行的 -// 那就能保证condition为真是如下__wait_event和wait_event里的if不出问题 -// 也就是不会出现if-break后进程又再次因为其它原因阻塞后,又被wake_up的逻辑 -// 设置为READY状态 +#if 0 +// __wait_event这个逻辑参考自Linux内核,但是发现它有BUG +// 第一个问题 +// 1. 在进入到__wait_event后,prepare_to_wait前其它进程通过wake_up唤醒当前进程 +// 2. prepare_to_wait把当前进程设置为TASK_WAIT +// 3. prepare_to_wait最后一句irq_restore(flags);执行完后 其实 condition 已经为true了 +// 4. 从if((conditon))到break再到__end_wait前都有可能被中断打断并重新schedule() +// 只要在__end_wait的irq_save(flags);完全关闭中断前被中断打断并schedule把当前进程换下CPU,那么这次唤醒就会丢失 +// 如果只有一次唤醒,那么这个唤醒丢失后,当前进程就会一直处于WAIT状态并且永远不会再被调度到 +// +// 但按理Linux内核不应该会出现这种BUG,还没研究明白,先把这段代码放在这里 #define __wait_event(head, condition) \ do { \ DECLARE_WAIT_QUEUE_ENTRY(__wait, current); \ @@ -70,13 +99,12 @@ void __wake_up(wait_queue_head_t *head, int nr); } \ __end_wait(&__wait); \ } while (0) - -#define wait_event(head, condition) \ - do { \ - if (!(condition)) { \ - __wait_event(head, (condition)); \ - } \ +#endif + +#define wait_event(head, condition) \ + do { \ + if ((condition)) { \ + break; \ + } \ + __wait_event(head, (condition)); \ } while (0) - -// 无条件wait -void wait_on(wait_queue_head_t *head); diff --git a/kernel/completion.c b/kernel/completion.c index 8d2ab8b..ea7d7b4 100644 --- a/kernel/completion.c +++ b/kernel/completion.c @@ -11,20 +11,22 @@ #include void wait_completion(completion_t *x) { - // - wait_event(&x->wait, (x->done == 1)); + wait_event(&x->wait, (x->done != 0)); + x->done--; } void complete(completion_t *x) { uint32_t iflags; irq_save(iflags); - x->done = 1; - // wake_up(&x->wait); - __wake_up(&x->wait, 0); + x->done++; + __wake_up(&x->wait, 1); irq_restore(iflags); } void init_completion(completion_t *x) { x->done = 0; init_wait_queue_head(&x->wait); + + // 测试字段 + x->name = 0; } diff --git a/kernel/irq.c b/kernel/irq.c index d688d15..36f1b61 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -142,6 +142,7 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) { { enable_irq(); + // 这里面不能执行任务切换操作,比如信号量相关操作 irq_bh_handler(); disable_irq(); diff --git a/kernel/task_disk.c b/kernel/task_disk.c index 43697e5..40a2427 100644 --- a/kernel/task_disk.c +++ b/kernel/task_disk.c @@ -94,6 +94,8 @@ void disk_task_entry(void *arg) { uint64_t pos = r->pos + drv->partions[part_id].lba_start; assert(pos < drv->partions[part_id].lba_end); + // init_completion(&ide_ctrl->intr_complete); + switch (r->command) { case DISK_REQ_IDENTIFY: printk("try to read disk drive %u identify", drv_no); @@ -116,8 +118,7 @@ void disk_task_entry(void *arg) { } // 等待硬盘中断 - // printk("down ide req\n"); - down(&ide_ctrl->disk_intr_sem); + wait_completion(&ide_ctrl->intr_complete); // 读数据 if (DISK_REQ_IDENTIFY == r->command) { diff --git a/kernel/wait.c b/kernel/wait.c index bb4fd0f..601feac 100644 --- a/kernel/wait.c +++ b/kernel/wait.c @@ -17,15 +17,21 @@ volatile void init_wait_queue_head(wait_queue_head_t *wqh) { INIT_LIST_HEAD(&(wq volatile void prepare_to_wait(wait_queue_head_t *head, wait_queue_entry_t *wqe, unsigned int state) { unsigned long flags; irq_save(flags); + // 进程可能等待一个condition满足后被唤醒 + // 然后又发现这个conditon又不满足了,需要继续wait + // 这时候又会把自己加到等待队列里 + // 所以这里需要加一个判断,如果已经加过了,就不需要再加了,不然会出问题 if (list_empty(&wqe->entry)) { list_add_tail(&wqe->entry, &head->task_list); } set_current_state(state); + current->reason = "p_wait"; irq_restore(flags); } volatile void __end_wait(wait_queue_entry_t *wqe) { set_current_state(TASK_READY); + current->reason = "e_wait"; unsigned long flags; irq_save(flags); list_del_init(&wqe->entry); @@ -72,21 +78,3 @@ volatile void wake_up(wait_queue_head_t *head) { // __wake_up(head, 0); // wake up all } - -volatile void wait_on(wait_queue_head_t *head) { - DECLARE_WAIT_QUEUE_ENTRY(wait, current); - - unsigned long flags; - irq_save(flags); - - current->state = TASK_WAIT; - current->reason = "sleep_on"; - - list_add_tail(&wait.entry, &head->task_list); - - irq_restore(flags); - - schedule(); - - __end_wait(&wait); -} -- 2.44.0 From af6f9ccffdc4304a5db9360fbb1285978c431aee Mon Sep 17 00:00:00 2001 From: acevest Date: Tue, 23 Jul 2024 20:44:33 +0800 Subject: [PATCH 15/16] =?utf8?q?=E6=81=A2=E5=A4=8D=E4=BF=A1=E5=8F=B7?= =?utf8?q?=E9=87=8F=E6=93=8D=E4=BD=9Cup()=E9=87=8C=E8=B0=83=E7=94=A8schedu?= =?utf8?q?le()?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/ide.c | 5 +++++ kernel/semaphore.c | 15 +++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/ide.c b/drivers/ide.c index 2761631..fa65c10 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -143,6 +143,11 @@ void ide_irq_bh_handler(void *arg) { printlxy(MPL_IDE0 + channel, MPO_IDE, "IDE%d req %u irq %u consumed %u", channel, atomic_read(&(ide_ctrl->request_cnt)), ide_ctrl->irq_cnt, ide_ctrl->consumed_cnt); + // 之前这里是用up()来唤醒磁盘任务 + // 但在中断的底半处理,不应该切换任务,因为会引起irq里的reenter问题,导致不能再进底半处理,也无法切换任务 + // 所以就移除了up()里的 schedule() + // 后来就改用完成量来通知磁盘任务,就不存在这个问题了 + // complete会唤醒进程,但不会立即重新调度进程 complete(&ide_ctrl->intr_complete); } diff --git a/kernel/semaphore.c b/kernel/semaphore.c index a38696c..23763a5 100644 --- a/kernel/semaphore.c +++ b/kernel/semaphore.c @@ -56,6 +56,7 @@ volatile void up(semaphore_t *s) { if (list_empty(&s->wait_list)) { s->cnt++; + irq_restore(iflags); } else { semaphore_waiter_t *waiter = list_first_entry(&s->wait_list, semaphore_waiter_t, list); assert(waiter != 0); @@ -65,13 +66,15 @@ volatile void up(semaphore_t *s) { task->state = TASK_READY; task->reason = "up"; - // 这里不应该调用schedule()再重新调度一次 - // 例如,目前在ide_irq_bh_handler里调用了up来唤醒磁盘任务 - // 而ide_irq_bh_handler又是中断的底半处理,不应该切换任务 - // 否则会引起irq里的reenter问题,导致不能再进底半处理,也无法切换任务 - } + irq_restore(iflags); - irq_restore(iflags); + // 之前把这里的schedule()删除了,是因为up()被用到了 ide_irq_bh_handler 里去唤醒磁盘任务 + // 但在中断的底半处理,不应该切换任务,因为会引起irq里的reenter问题,导致不能再进底半处理,也无法切换任务 + // 但这种方法是不对的 + // 后来就改用完成量来通知磁盘任务 + // 因此信号量这里就可以加回schedule()了 + schedule(); + } } void mutex_lock(semaphore_t *s) { down(s); } -- 2.44.0 From 7b01bd07632c4f2264440dc3d93fff3cdcac82eb Mon Sep 17 00:00:00 2001 From: acevest Date: Wed, 21 Aug 2024 15:47:56 +0800 Subject: [PATCH 16/16] =?utf8?q?=E6=9B=B4=E6=94=B9alloc=5Fpages=E6=8E=A5?= =?utf8?q?=E5=8F=A3=E8=BF=94=E5=9B=9E=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/ide.c | 2 +- fs/buffer.c | 2 +- include/page.h | 7 ++++--- kernel/exec.c | 8 ++++---- kernel/fork.c | 6 +++--- kernel/task_user.c | 6 +++--- mm/buddy.c | 31 ++++++++++++++++++------------- mm/mm.c | 2 +- mm/page.c | 10 +++++----- mm/slub.c | 22 +++------------------- 10 files changed, 43 insertions(+), 53 deletions(-) diff --git a/drivers/ide.c b/drivers/ide.c index fa65c10..7985baa 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -70,7 +70,7 @@ void ide_pci_init(pci_device_t *pci) { ide_pci_controller[i].bus_cmd = iobase + PCI_IDE_CMD; ide_pci_controller[i].bus_status = iobase + PCI_IDE_STATUS; ide_pci_controller[i].bus_prdt = iobase + PCI_IDE_PRDT; - ide_pci_controller[i].prdt = (prdte_t *)alloc_one_page(0); + ide_pci_controller[i].prdt = (prdte_t *)page2va(alloc_one_page(0)); ide_pci_controller[i].pci = pci; } diff --git a/fs/buffer.c b/fs/buffer.c index 823d38f..597eae6 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -213,7 +213,7 @@ void init_buffer() { page_t *page = NULL; for (int j = 0; j < MAX_BBUFFER_CNT; j++) { if (page_left_space < blocksize) { - data = (void *)(alloc_one_page(0)); + data = (void *)page2va(alloc_one_page(0)); page = va2page(data); } diff --git a/include/page.h b/include/page.h index 30e2238..bbe407d 100644 --- a/include/page.h +++ b/include/page.h @@ -103,14 +103,14 @@ typedef unsigned long pte_t; #define PAGE_UP(page) (((unsigned long)page + PAGE_SIZE - 1) & PAGE_MASK) #define PAGE_DOWN PAGE_ALIGN -#define PAGE_FLAGS(addr) ((addr)-PAGE_ALIGN(addr)) +#define PAGE_FLAGS(addr) ((addr) - PAGE_ALIGN(addr)) #define va2pa(x) (((unsigned long)(x)) - PAGE_OFFSET) #define pa2va(x) ((void *)(((unsigned long)(x)) + PAGE_OFFSET)) // pfn: page frame number #define pa2pfn(addr) ((addr) >> PAGE_SHIFT) -#define pfn2pa(pfn) ((pfn) << PAGE_SHIFT) +#define pfn2pa(pfn) ((void *)((pfn) << PAGE_SHIFT)) #define va2pfn(addr) pa2pfn(va2pa(addr)) #define pfn2va(pfn) pa2va(pfn2pa(pfn)) @@ -155,6 +155,7 @@ typedef struct page { } page_t; void *page2va(page_t *page); +void *page2pa(page_t *page); page_t *_va2page(unsigned long addr); page_t *_pa2page(unsigned long addr); @@ -181,7 +182,7 @@ typedef struct free_area { list_head_t free_list; } free_area_t; -unsigned long alloc_pages(unsigned int gfp_mask, unsigned int order); +page_t *alloc_pages(unsigned int gfp_mask, unsigned int order); void free_pages(unsigned long addr); #define alloc_one_page(gfp_mask) alloc_pages(gfp_mask, 0) diff --git a/kernel/exec.c b/kernel/exec.c index cac3df4..0a328c3 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -35,7 +35,7 @@ void put_paging(unsigned long vaddr, unsigned long paddr, unsigned long flags) { pte_t *page_table = (pte_t *)PAGE_ALIGN(page_dir[npde]); if (page_table == 0) { - page_table = (pte_t *)alloc_one_page(0); + page_table = (pte_t *)page2va(alloc_one_page(0)); memset(page_table, 0, PAGE_SIZE); page_table = (pte_t *)va2pa(page_table); assert(page_table != 0); @@ -56,7 +56,7 @@ int sysc_exec(const char *path, char *const argv[]) { ext2_read_inode(ino, &inode); - Elf32_Ehdr *ehdr = (Elf32_Ehdr *)alloc_one_page(0); + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(page2va(alloc_one_page(0))); assert(ehdr != 0); ext2_read_data(&inode, 0, PAGE_SIZE, (char *)ehdr); printk("%08x\n", *((unsigned long *)ehdr->e_ident)); @@ -68,8 +68,8 @@ int sysc_exec(const char *path, char *const argv[]) { Elf32_Phdr *phdr; phdr = (Elf32_Phdr *)(((unsigned long)ehdr) + ehdr->e_phoff + (i * ehdr->e_phentsize)); - printk("Type %08x Off %08x Va %08x Pa %08x Fsz %08x Mmsz %08x\n", phdr->p_type, phdr->p_offset, phdr->p_vaddr, phdr->p_paddr, phdr->p_filesz, - phdr->p_memsz); + printk("Type %08x Off %08x Va %08x Pa %08x Fsz %08x Mmsz %08x\n", phdr->p_type, phdr->p_offset, phdr->p_vaddr, + phdr->p_paddr, phdr->p_filesz, phdr->p_memsz); unsigned long vaddr = phdr->p_vaddr; unsigned long offset = phdr->p_offset; diff --git a/kernel/fork.c b/kernel/fork.c index ab6d887..c4e1b46 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -39,7 +39,7 @@ int do_fork(pt_regs_t *regs, unsigned long flags) { list_add(&tsk->list, &all_tasks); irq_restore(iflags); - tsk->cr3 = va2pa((unsigned long)alloc_one_page(0)); + tsk->cr3 = (uint32_t)page2pa(alloc_one_page(0)); assert(tsk->cr3 != 0); unsigned int i, j; @@ -67,7 +67,7 @@ int do_fork(pt_regs_t *regs, unsigned long flags) { // 这里不用再为每个PDE拷贝一次PageTable,只需要拷贝PageDirectory并将其低于768的写权限去掉 // 同时需要修改缺页异常doPageFault的逻辑 if (PAGE_ALIGN(spde) != 0) { - dpde = alloc_one_page(0); + dpde = page2va(alloc_one_page(0)); assert(dpde != 0); memset((void *)dpde, 0, PAGE_SIZE); dpde = PAGE_FLAGS(spde) | (unsigned long)va2pa(dpde); @@ -102,7 +102,7 @@ int do_fork(pt_regs_t *regs, unsigned long flags) { strcpy(tsk->name, (char *)(child_regs->eax)); child_regs->eax = 0; } else { - child_regs->eip = *((unsigned long *)&&fork_child); + child_regs->eip = *((unsigned long *) && fork_child); } // 这一句已经不需要了,通过fork_child已经能给子进程返回0了 diff --git a/kernel/task_user.c b/kernel/task_user.c index cb8b880..8356609 100644 --- a/kernel/task_user.c +++ b/kernel/task_user.c @@ -63,10 +63,10 @@ void user_task_entry() { current->priority = 7; unsigned long ring3_text_page = va2pa(ring3_entry); - unsigned long ring3_bss_page = va2pa(alloc_one_page(0)); + unsigned long ring3_bss_page = (unsigned long)page2pa(alloc_one_page(0)); - unsigned long *pt_text_page = (unsigned long *)(alloc_one_page(0)); - unsigned long *pt_bss_page = (unsigned long *)(alloc_one_page(0)); + unsigned long *pt_text_page = (unsigned long *)page2va(alloc_one_page(0)); + unsigned long *pt_bss_page = (unsigned long *)page2va(alloc_one_page(0)); unsigned long *p = (unsigned long *)(pa2va(current->cr3)); diff --git a/mm/buddy.c b/mm/buddy.c index 15dd0ee..7463ebd 100644 --- a/mm/buddy.c +++ b/mm/buddy.c @@ -46,15 +46,16 @@ page_t *_pa2page(unsigned long paddr) { } void *page2va(page_t *page) { return pfn2va((page)-buddy_system.page_map); } +void *page2pa(page_t *page) { return pfn2pa((page)-buddy_system.page_map); } page_t *__alloc_pages(unsigned int order) { // page_t *page = 0; - page_t *buddy = 0; free_area_t *area; - unsigned long size; unsigned int select_order; unsigned int i; + + // 找到首个满足 >= order的page块 for (select_order = order; select_order < MAX_ORDER; ++select_order) { area = buddy_system.free_area + select_order; if (!list_empty(&(area->free_list))) { @@ -65,25 +66,28 @@ page_t *__alloc_pages(unsigned int order) { return 0; found: + // 从链表取下这个连续的page块 page = list_entry(area->free_list.next, page_t, lru); list_del(&(page->lru)); ClearPagePrivate(page); page->private = 0; area->free_count--; + // 二分这个page块,把空闲的挂到对应的order队列上 + // 直到得到order大小的page块 while (select_order > order) { area--; select_order--; - size = 1UL << select_order; + unsigned long buddy_offset = 1UL << select_order; - buddy = page + size; - list_add(&(buddy->lru), &(area->free_list)); + page_t *buddy_page = page + buddy_offset; + list_add(&(buddy_page->lru), &(area->free_list)); area->free_count++; - buddy->private = select_order; - SetPagePrivate(buddy); + buddy_page->private = select_order; + SetPagePrivate(buddy_page); } - // + // 初始化这一连续的page块 for (i = 0; i < (1UL << order); ++i) { page_t *p = page + i; p->head_page = page; @@ -95,7 +99,7 @@ found: return page; } -unsigned long alloc_pages(unsigned int gfp_mask, unsigned int order) { +page_t *alloc_pages(unsigned int gfp_mask, unsigned int order) { // gfp_mask // ... @@ -104,8 +108,10 @@ unsigned long alloc_pages(unsigned int gfp_mask, unsigned int order) { page_t *page = __alloc_pages(order); irq_restore(flags); - unsigned long addr = (unsigned long)page2va(page); - return addr; + // unsigned long addr = (unsigned long)page2va(page); + // return addr; + + return page; } void __free_pages(page_t *page, unsigned int order) { @@ -190,8 +196,7 @@ void init_buddy_system() { buddy_system.page_map = alloc_from_bootmem(page_map_size, "buddy"); if (0 == buddy_system.page_map) { printk("can not go on playing...\n"); - while (1) - ; + while (1); } buddy_system.page_map_end = buddy_system.page_map + pfn_cnt + 1; diff --git a/mm/mm.c b/mm/mm.c index 71deb05..8fa0dce 100644 --- a/mm/mm.c +++ b/mm/mm.c @@ -50,7 +50,7 @@ void init_paging() { // 最大限制内存1G for (pfn = pa2pfn(BOOT_INIT_PAGETBL_CNT << 22); pfn < bootmem_data.max_pfn; ++pfn) { unsigned long ti = pfn % PAGE_PTE_CNT; - unsigned long page_addr = pfn2pa(pfn); + unsigned long page_addr = (unsigned long)pfn2pa(pfn); if (ti == 0) { pgtb_addr = (unsigned long *)alloc_from_bootmem(PAGE_SIZE, "paging"); if (0 == pgtb_addr) { diff --git a/mm/page.c b/mm/page.c index 925580b..3b27a8d 100644 --- a/mm/page.c +++ b/mm/page.c @@ -21,14 +21,14 @@ void do_no_page(void *addr) { pde_t *page_dir = (pde_t *)pa2va(current->cr3); pte_t *page_tbl = 0; - unsigned long page = alloc_one_page(0); + unsigned long page = (unsigned long)page2va(alloc_one_page(0)); assert(page != 0); int npde = get_npde(addr); int npte = get_npte(addr); if (page_dir[npde] == 0) { - page_tbl = (pte_t *)alloc_one_page(0); + page_tbl = (pte_t *)page2va(alloc_one_page(0)); assert(page_tbl != 0); memset((void *)page_tbl, 0, PAGE_SIZE); @@ -57,7 +57,7 @@ void do_wp_page(void *addr) { // 如果是因为PDE被写保护 if (*pde & PDE_RW == 0) { // 1. 分配一个页表 - unsigned long newtbl = alloc_one_page(0); + unsigned long newtbl = (unsigned long)page2va(alloc_one_page(0)); assert(newtbl != 0); // 2. 拷贝页表 @@ -88,7 +88,7 @@ void do_wp_page(void *addr) { // 如果PTE的位置被写保护 if (*pte & PTE_RW == 0) { // 1. 分配一个页表 - unsigned long newaddr = alloc_one_page(0); + unsigned long newaddr = (unsigned long)page2va(alloc_one_page(0)); assert(newaddr != 0); // 2. 拷贝页表 @@ -113,7 +113,7 @@ void do_wp_page(void *addr) { page->count--; unsigned long flags = PAGE_FLAGS(page_tbl[npte]); unsigned long wp_va_addr = (unsigned long)pa2va(wp_pa_addr); - unsigned long newtbl = alloc_one_page(0); + unsigned long newtbl = (unsigned long) page2va(alloc_one_page(0)); assert(newtbl != 0); memcpy((void *)newtbl, (void *)wp_va_addr, PAGE_SIZE); diff --git a/mm/slub.c b/mm/slub.c index d700130..92e48e8 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -28,21 +28,14 @@ page_t *get_partial(kmem_cache_t *cache, gfp_t gfpflags) { // 从伙伴系统批发页,并将之初始化成一个链表 page_t *new_slub(kmem_cache_t *cache, gfp_t gfpflags) { - // alloc pages from buddy system - unsigned long bgn = alloc_pages(gfpflags, cache->order); - unsigned long end = 0; - - // 找到该页的管理结构 - page_t *page = va2page(bgn); - - // + page_t *page = alloc_pages(gfpflags, cache->order); if (0 == page) { return 0; } - end = bgn + cache->objects * cache->size; + unsigned long bgn = (unsigned long)page2va(page); + unsigned long end = bgn + cache->objects * cache->size; -#if 1 unsigned long last = bgn; unsigned long addr; @@ -55,15 +48,6 @@ page_t *new_slub(kmem_cache_t *cache, gfp_t gfpflags) { // 最后一个赋值为0 *((void **)last) = 0; -#else - unsigned long addr; - for (addr = bgn; addr < end; addr += cache->size) { - *(unsigned long *)addr = addr + cache->size; - } - - addr = end - cache->size; - *(unsigned long *)addr = 0; -#endif page->freelist = (void **)bgn; page->inuse = 0; -- 2.44.0