diff options
author | Freya Murphy <freya@freyacat.org> | 2025-04-29 11:13:58 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-04-29 11:13:58 -0400 |
commit | 4e6384d8153f1476701638e2277043d59755306d (patch) | |
tree | ba0b2af256ab7a01f5dff3ea556ac2d0176bb9b8 /kernel | |
parent | ps2 (diff) | |
download | comus-4e6384d8153f1476701638e2277043d59755306d.tar.gz comus-4e6384d8153f1476701638e2277043d59755306d.tar.bz2 comus-4e6384d8153f1476701638e2277043d59755306d.zip |
change queue structures
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/include/comus/procs.h | 12 | ||||
-rw-r--r-- | kernel/procs.c | 67 | ||||
-rw-r--r-- | kernel/syscall.c | 35 |
3 files changed, 62 insertions, 52 deletions
diff --git a/kernel/include/comus/procs.h b/kernel/include/comus/procs.h index cf3f90d..7b1a70a 100644 --- a/kernel/include/comus/procs.h +++ b/kernel/include/comus/procs.h @@ -12,6 +12,7 @@ #include <comus/cpu.h> #include <comus/limits.h> #include <comus/memory.h> +#include <comus/syscalls.h> #include <lib.h> #include <elf.h> @@ -34,11 +35,8 @@ enum proc_state { PROC_STATE_READY, PROC_STATE_RUNNING, // runnable, but waiting for some event - PROC_STATE_SLEEPING, PROC_STATE_BLOCKED, - PROC_STATE_WAITING, // no longer runnalbe - PROC_STATE_KILLED, PROC_STATE_ZOMBIE, // sentinel N_PROC_STATES, @@ -70,6 +68,7 @@ struct pcb { struct pcb *next; // next PDB in queue // process state information + uint64_t syscall; uint64_t wakeup; uint8_t exit_status; }; @@ -89,10 +88,9 @@ typedef struct pcb_queue_s *pcb_queue_t; /// public facing pcb queues extern pcb_queue_t pcb_freelist; -extern pcb_queue_t ready; -extern pcb_queue_t waiting; -extern pcb_queue_t sleeping; -extern pcb_queue_t zombie; +extern pcb_queue_t ready_queue; +extern pcb_queue_t zombie_queue; +extern pcb_queue_t syscall_queue[N_SYSCALLS]; /// pointer to the currently-running process extern struct pcb *current_pcb; diff --git a/kernel/procs.c b/kernel/procs.c index 1668bef..9bf7508 100644 --- a/kernel/procs.c +++ b/kernel/procs.c @@ -1,4 +1,5 @@ #include <comus/drivers/pit.h> +#include <comus/syscalls.h> #include <comus/memory.h> #include <comus/procs.h> #include <comus/error.h> @@ -14,18 +15,16 @@ struct pcb_queue_s { }; // collection of queues -static struct pcb_queue_s pcb_freelist_queue; -static struct pcb_queue_s ready_queue; -static struct pcb_queue_s waiting_queue; -static struct pcb_queue_s sleeping_queue; -static struct pcb_queue_s zombie_queue; +static struct pcb_queue_s _pcb_freelist; +static struct pcb_queue_s _ready_queue; +static struct pcb_queue_s _zombie_queue; +static struct pcb_queue_s _syscall_queue[N_SYSCALLS]; // public facing queue handels pcb_queue_t pcb_freelist; -pcb_queue_t ready; -pcb_queue_t waiting; -pcb_queue_t sleeping; -pcb_queue_t zombie; +pcb_queue_t ready_queue; +pcb_queue_t zombie_queue; +pcb_queue_t syscall_queue[N_SYSCALLS]; /// pointer to the currently-running process struct pcb *current_pcb = NULL; @@ -86,7 +85,7 @@ static struct pcb *find_prev_pid(pcb_queue_t queue, struct pcb *pcb) // a macro to simplify queue setup #define QINIT(q, s) \ - q = &q##_queue; \ + q = &_##q; \ if (pcb_queue_reset(q, s) != SUCCESS) { \ panic("pcb_init can't reset " #q); \ } @@ -98,10 +97,11 @@ void pcb_init(void) // set up the external links to the queues QINIT(pcb_freelist, O_PCB_FIFO); - QINIT(ready, O_PCB_PRIO); - QINIT(waiting, O_PCB_PID); - QINIT(sleeping, O_PCB_WAKEUP); - QINIT(zombie, O_PCB_PID); + QINIT(ready_queue, O_PCB_PRIO); + QINIT(zombie_queue, O_PCB_PID); + for (size_t i = 0; i < N_SYSCALLS; i++) { + QINIT(syscall_queue[i], O_PCB_PID); + } // setup pcb linked list (free list) // this can be done by calling pcb_free :) @@ -122,6 +122,7 @@ int pcb_alloc(struct pcb **pcb) return E_NO_PCBS; tmp->pid = next_pid++; + tmp->state = PROC_STATE_NEW; *pcb = tmp; return SUCCESS; } @@ -180,13 +181,14 @@ void pcb_zombify(struct pcb *victim) } // schedule init if zombie child found - if (zchild != NULL && init_pcb->state == PROC_STATE_WAITING) { + if (zchild != NULL && init_pcb->syscall == SYS_waitpid) { pid_t pid; int *status; - assert(pcb_queue_remove(zombie, zchild) == SUCCESS, + assert(pcb_queue_remove(zombie_queue, zchild) == SUCCESS, "pcb_zombify: cannot remove zombie process from queue"); - assert(pcb_queue_remove(waiting, init_pcb) == SUCCESS, + assert(pcb_queue_remove(syscall_queue[SYS_waitpid], init_pcb) == + SUCCESS, "pcb_zombify: cannot remove waiting process from queue"); pid = (pid_t)PCB_ARG1(init_pcb); @@ -208,7 +210,7 @@ void pcb_zombify(struct pcb *victim) // if the parent is waiting, wake it up and clean the victim, // otherwise the victim will become a zombie - if (parent->state == PROC_STATE_WAITING) { + if (parent->syscall == SYS_waitpid) { pid_t pid; int *status; @@ -217,6 +219,11 @@ void pcb_zombify(struct pcb *victim) if (pid == 0 || pid == victim->pid) { PCB_RET(parent) = zchild->pid; + + assert( + pcb_queue_remove(syscall_queue[SYS_waitpid], parent) == SUCCESS, + "pcb_zombify: cannot remove parent process from waitpid queue"); + if (status != NULL) { mem_ctx_switch(parent->memctx); *status = victim->exit_status; @@ -229,7 +236,7 @@ void pcb_zombify(struct pcb *victim) } victim->state = PROC_STATE_ZOMBIE; - assert(pcb_queue_insert(zombie, victim) == SUCCESS, + assert(pcb_queue_insert(zombie_queue, victim) == SUCCESS, "cannot insert victim process into zombie queue"); } @@ -456,13 +463,15 @@ struct pcb *pcb_queue_peek(const pcb_queue_t queue) void schedule(struct pcb *pcb) { assert(pcb != NULL, "schedule: pcb is null"); - - if (pcb->state == PROC_STATE_KILLED) - panic("attempted to schedule killed process %d", pcb->pid); + assert(pcb->state != PROC_STATE_UNUSED, + "attempted to schedule invalid process %d", pcb->pid); + assert(pcb->state != PROC_STATE_ZOMBIE, + "attempted to schedule killed process %d", pcb->pid); pcb->state = PROC_STATE_READY; + pcb->syscall = 0; - if (pcb_queue_insert(ready, pcb) != SUCCESS) + if (pcb_queue_insert(ready_queue, pcb) != SUCCESS) panic("schedule insert fail"); } @@ -474,9 +483,10 @@ __attribute__((noreturn)) void dispatch(void) // wait for a process to schedule do { - status = pcb_queue_pop(ready, ¤t_pcb); - if (status == SUCCESS) + status = pcb_queue_pop(ready_queue, ¤t_pcb); + if (status == SUCCESS) { break; + } int_wait(); } while (1); @@ -484,6 +494,7 @@ __attribute__((noreturn)) void dispatch(void) current_pcb->regs.cr3 = (uint64_t)mem_ctx_pgdir(current_pcb->memctx); current_pcb->state = PROC_STATE_RUNNING; current_pcb->ticks = 3; // ticks per process + current_pcb->syscall = 0; syscall_return(); } @@ -498,16 +509,16 @@ void pcb_on_tick(void) do { struct pcb *pcb; - if (pcb_queue_empty(sleeping)) + if (pcb_queue_empty(syscall_queue[SYS_sleep])) break; - pcb = pcb_queue_peek(sleeping); + pcb = pcb_queue_peek(syscall_queue[SYS_sleep]); assert(pcb != NULL, "sleeping queue should not be empty"); if (pcb->wakeup >= ticks) break; - if (pcb_queue_remove(sleeping, pcb)) + if (pcb_queue_remove(syscall_queue[SYS_sleep], pcb)) panic("failed to wake sleeping process: %d", pcb->pid); schedule(pcb); diff --git a/kernel/syscall.c b/kernel/syscall.c index 403b3bd..96d2fcf 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -7,6 +7,7 @@ #include <comus/memory.h> #include <comus/procs.h> #include <comus/time.h> +#include <comus/error.h> #include <lib.h> #include <stddef.h> @@ -37,8 +38,9 @@ static int sys_waitpid(void) { // arguments are read later // by procs.c - pcb->state = PROC_STATE_WAITING; - pcb_queue_insert(waiting, pcb); + pcb->state = PROC_STATE_BLOCKED; + assert(pcb_queue_insert(syscall_queue[SYS_waitpid], pcb) == SUCCESS, + "sys_waitpid: could not add process to waitpid queue"); // call next process dispatch(); @@ -149,17 +151,22 @@ static int sys_kill(void) return 1; switch (victim->state) { - case PROC_STATE_KILLED: case PROC_STATE_ZOMBIE: // you can't kill it if it's already dead return 0; case PROC_STATE_READY: - case PROC_STATE_SLEEPING: + // remove from ready queue + victim->exit_status = 1; + pcb_queue_remove(ready_queue, victim); + pcb_zombify(victim); + return 0; + case PROC_STATE_BLOCKED: - // here, the process is on a queue somewhere; mark - // it as "killed", and let the scheduler deal with it - victim->state = PROC_STATE_KILLED; + // remove from syscall queue + victim->exit_status = 1; + pcb_queue_remove(syscall_queue[victim->syscall], victim); + pcb_zombify(victim); return 0; case PROC_STATE_RUNNING: @@ -170,14 +177,6 @@ static int sys_kill(void) dispatch(); break; - case PROC_STATE_WAITING: - // similar to the 'running' state, but we don't need - // to dispatch a new process - victim->exit_status = 1; - pcb_queue_remove(waiting, pcb); - pcb_zombify(victim); - break; - default: // cannot kill a previable process return 1; @@ -198,11 +197,11 @@ static int sys_sleep(void) } pcb->wakeup = ticks + ms; - if (pcb_queue_insert(sleeping, pcb)) { + if (pcb_queue_insert(syscall_queue[SYS_sleep], pcb)) { WARN("sleep pcb insert failed"); return 1; } - pcb->state = PROC_STATE_SLEEPING; + pcb->state = PROC_STATE_BLOCKED; // calling pcb is in sleeping queue, // we must call a new one @@ -348,6 +347,7 @@ void syscall_handler(void) pcb = current_pcb; num = pcb->regs.rax; pcb->regs.rax = 0; + pcb->syscall = num; current_pcb = NULL; // check for invalid syscall @@ -369,5 +369,6 @@ void syscall_handler(void) pcb->regs.rax = ret; // return to current pcb + pcb->syscall = 0; current_pcb = pcb; } |