summaryrefslogtreecommitdiff
path: root/kernel/procs.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--kernel/procs.c67
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, &current_pcb);
- if (status == SUCCESS)
+ status = pcb_queue_pop(ready_queue, &current_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);