summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/proc.c143
-rw-r--r--src/kernel/proc.h3
-rw-r--r--src/kernel/syscalls.c6
3 files changed, 58 insertions, 94 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index ee26f44..2a35acc 100644
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -91,15 +91,8 @@ void process_forget(struct process *p) {
}
void process_free(struct process *p) {
- bool valid = false;
- if (p->state == PS_DEADER) valid = true;
- if (p->state == PS_DEAD && (!p->parent
- || p->parent->state == PS_DEAD
- || p->parent->state == PS_DEADER)) valid = true;
- assert(valid);
-
- while (p->child)
- process_free(p->child);
+ assert(p->state == PS_DEAD);
+ assert(!p->child);
// also could be done on kill
vfs_mount_remref(p->mount);
@@ -130,8 +123,8 @@ _Noreturn void process_switch_any(void) {
struct process *found = process_find(PS_RUNNING);
if (found) process_switch(found);
- if (process_first->state == PS_DEAD || process_first->state == PS_DEADER)
- shutdown();
+ if (process_first->state == PS_DEAD)
+ shutdown(); // TODO not the place for this
cpu_pause();
process_switch_any();
@@ -199,15 +192,11 @@ void process_transition(struct process *p, enum process_state state) {
p->state = state;
switch (state) {
case PS_RUNNING:
- assert(last != PS_DEAD && last != PS_DEADER);
+ assert(last != PS_DEAD);
break;
case PS_DEAD:
// see process_kill
break;
- case PS_DEADER:
- assert(last == PS_DEAD);
- process_free(p);
- break;
case PS_WAITS4CHILDDEATH:
case PS_WAITS4FS:
case PS_WAITS4REQUEST:
@@ -220,96 +209,70 @@ void process_transition(struct process *p, enum process_state state) {
}
void process_kill(struct process *p, int ret) {
- if (p->state == PS_DEAD || p->state == PS_DEADER) return;
+ if (p->state != PS_DEAD) {
+ if (p->handled_req) {
+ vfsreq_finish(p->handled_req, -1);
+ p->handled_req = NULL;
+ }
- if (p->handled_req) {
- vfsreq_finish(p->handled_req, -1);
- p->handled_req = NULL;
- }
- if (p->controlled) {
- assert(p->controlled->potential_handlers > 0);
- p->controlled->potential_handlers--;
- if (p->controlled->potential_handlers == 0) {
- // orphaned
- struct vfs_request *q = p->controlled->queue;
- while (q) {
- struct vfs_request *q2 = q->queue_next;
- vfsreq_finish(q, -1);
- q = q2;
+ if (p->controlled) {
+ // TODO vfs_backend_user_handlerdown
+ assert(p->controlled->potential_handlers > 0);
+ p->controlled->potential_handlers--;
+ if (p->controlled->potential_handlers == 0) {
+ // orphaned
+ struct vfs_request *q = p->controlled->queue;
+ while (q) {
+ struct vfs_request *q2 = q->queue_next;
+ vfsreq_finish(q, -1);
+ q = q2;
+ }
+ p->controlled->queue = NULL;
}
- p->controlled->queue = NULL;
- }
- if (p->controlled->user.handler == p) {
- assert(p->state == PS_WAITS4REQUEST);
- p->controlled->user.handler = NULL;
+ if (p->controlled->user.handler == p) {
+ assert(p->state == PS_WAITS4REQUEST);
+ p->controlled->user.handler = NULL;
+ }
+
+ vfs_backend_refdown(p->controlled);
+ p->controlled = NULL;
}
- vfs_backend_refdown(p->controlled);
- p->controlled = NULL;
- }
+ if (p->state == PS_WAITS4FS)
+ p->waits4fs.req->caller = NULL;
- // TODO VULN unbounded recursion
- struct process *c2;
- for (struct process *c = p->child; c; c = c2) {
- c2 = c->sibling;
- process_kill(c, -1);
- }
+ for (handle_t h = 0; h < HANDLE_MAX; h++)
+ handle_close(p->handles[h]);
- struct vfs_request *req;
- switch (p->state) {
- case PS_RUNNING:
- case PS_WAITS4CHILDDEATH:
- case PS_WAITS4REQUEST:
- break;
-
- case PS_WAITS4FS:
- // if the request wasn't accepted we could just remove this process from the queue
- // eh
- req = p->waits4fs.req;
- req->caller = NULL;
- // TODO test this
- break;
+ process_transition(p, PS_DEAD);
+ p->death_msg = ret;
- case PS_DEAD:
- case PS_DEADER:
- case PS_LAST:
- kprintf("process_kill unexpected state 0x%x\n", p->state);
- panic_invalid_state();
+ // TODO VULN unbounded recursion
+ struct process *c2;
+ for (struct process *c = p->child; c; c = c2) {
+ c2 = c->sibling;
+ process_kill(c, -1);
+ }
}
- for (handle_t h = 0; h < HANDLE_MAX; h++)
- handle_close(p->handles[h]);
- process_transition(p, PS_DEAD);
- p->death_msg = ret;
+ assert(!p->child);
process_try2collect(p);
}
int process_try2collect(struct process *dead) {
struct process *parent = dead->parent;
- int ret;
-
- assert(dead->state == PS_DEAD);
+ int ret = -1;
- if (!parent || dead->noreap) {
- process_transition(dead, PS_DEADER);
- return -1;
- }
- switch (parent->state) {
- case PS_WAITS4CHILDDEATH:
- ret = dead->death_msg;
- regs_savereturn(&parent->regs, ret);
- process_transition(parent, PS_RUNNING);
- process_transition(dead, PS_DEADER);
+ assert(dead && dead->state == PS_DEAD);
- return ret;
+ if (!dead->noreap && parent && parent->state != PS_DEAD) { // might be reaped
+ if (parent->state != PS_WAITS4CHILDDEATH) return -1;
- case PS_DEAD:
- case PS_DEADER:
- process_transition(dead, PS_DEADER);
- return -1;
-
- default:
- return -1; // this return value isn't used anywhere
- // TODO enforce that, somehow? idk
+ ret = dead->death_msg;
+ regs_savereturn(&parent->regs, ret);
+ process_transition(parent, PS_RUNNING);
}
+
+ process_free(dead);
+ return ret;
}
diff --git a/src/kernel/proc.h b/src/kernel/proc.h
index f9786b9..6266998 100644
--- a/src/kernel/proc.h
+++ b/src/kernel/proc.h
@@ -10,8 +10,7 @@
enum process_state {
PS_RUNNING,
- PS_DEAD, // return message wasn't collected
- PS_DEADER, // return message was collected
+ PS_DEAD, // return message not collected
PS_WAITS4CHILDDEATH,
PS_WAITS4FS,
PS_WAITS4REQUEST,
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 01d42a0..f3161e5 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -23,10 +23,12 @@ int _syscall_await(void) {
// find any already dead children
for (struct process *iter = process_current->child;
iter; iter = iter->sibling) {
- if (iter->state == PS_DEAD && !iter->noreap)
+ if (iter->state == PS_DEAD && !iter->noreap) {
+ assert(!iter->noreap);
SYSCALL_RETURN(process_try2collect(iter));
- if (iter->state != PS_DEADER)
+ } else {
has_children = true;
+ }
}
if (!has_children) {