diff options
Diffstat (limited to '')
-rw-r--r-- | kernel/procs.c | 67 |
1 files changed, 39 insertions, 28 deletions
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); |