diff options
author | dzwdz | 2022-05-06 13:31:11 +0200 |
---|---|---|
committer | dzwdz | 2022-05-06 13:31:11 +0200 |
commit | 292e55a3c344e649d271cfb3c9063ac8b2484de6 (patch) | |
tree | 9484693110882ae0088f72eaa21f859521bb9eb8 | |
parent | d8c330821aa3ae1d441cdf3aed64d457d0ed0cd9 (diff) |
kernel/proc: get rid of the PS_DEADER state, free processes asap
-rw-r--r-- | src/kernel/proc.c | 143 | ||||
-rw-r--r-- | src/kernel/proc.h | 3 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 6 |
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) { |