diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/proc.c | 190 | ||||
-rw-r--r-- | src/kernel/proc.h | 21 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 4 | ||||
-rw-r--r-- | src/kernel/vfs/request.c | 2 |
4 files changed, 103 insertions, 114 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 3233725..ed257fd 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -74,6 +74,92 @@ struct process *process_fork(struct process *parent, int flags) { return child; } +void process_kill(struct process *p, int ret) { + if (p->state != PS_DEAD) { + if (p->handled_req) { + vfsreq_finish(p->handled_req, -1); + p->handled_req = NULL; + } + + 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; + } + if (p->controlled->user.handler == p) { + assert(p->state == PS_WAITS4REQUEST); + p->controlled->user.handler = NULL; + } + + vfs_backend_refdown(p->controlled); + p->controlled = NULL; + } + + if (p->state == PS_WAITS4FS) + p->waits4fs.req->caller = NULL; + + for (handle_t h = 0; h < HANDLE_MAX; h++) + handle_close(p->handles[h]); + + vfs_mount_remref(p->mount); + p->mount = NULL; + + process_transition(p, PS_DEAD); + p->death_msg = ret; + + if (p->parent) + pagedir_free(p->pages); // TODO put init's pages in the allocator + + // TODO VULN unbounded recursion + struct process *c2; + for (struct process *c = p->child; c; c = c2) { + c2 = c->sibling; + process_kill(c, -1); + } + } + + assert(!p->child); + process_try2collect(p); + + if (p == process_first) shutdown(); +} + +int process_try2collect(struct process *dead) { + struct process *parent = dead->parent; + int ret = -1; + + assert(dead && dead->state == PS_DEAD); + + if (!dead->noreap && parent && parent->state != PS_DEAD) { // might be reaped + if (parent->state != PS_WAITS4CHILDDEATH) return -1; + + ret = dead->death_msg; + regs_savereturn(&parent->regs, ret); + process_transition(parent, PS_RUNNING); + } + + process_free(dead); + return ret; +} + +void process_free(struct process *p) { + assert(p->state == PS_DEAD); + assert(!p->child); + + if (!p->parent) return; + process_forget(p); + kfree(p); +} + void process_forget(struct process *p) { assert(p->parent); @@ -90,15 +176,6 @@ void process_forget(struct process *p) { } } -void process_free(struct process *p) { - assert(p->state == PS_DEAD); - assert(!p->child); - - if (!p->parent) return; - process_forget(p); - kfree(p); -} - static _Noreturn void process_switch(struct process *proc) { assert(proc->state == PS_RUNNING); process_current = proc; @@ -138,23 +215,13 @@ struct process *process_next(struct process *p) { } struct process *process_find(enum process_state target) { - struct process *result = NULL; - process_find_multiple(target, &result, 1); - return result; -} - -size_t process_find_multiple(enum process_state target, struct process **buf, size_t max) { - size_t i = 0; - for (struct process *p = process_first; - i < max && p; - p = process_next(p)) - { - if (p->state == target) buf[i++] = p; + for (struct process *p = process_first; p; p = process_next(p)) { + if (p->state == target) return p; } - return i; + return NULL; } -handle_t process_find_handle(struct process *proc, handle_t start_at) { +handle_t process_find_free_handle(struct process *proc, handle_t start_at) { // TODO start_at is a bit of a hack handle_t handle; for (handle = start_at; handle < HANDLE_MAX; handle++) { @@ -194,80 +261,3 @@ void process_transition(struct process *p, enum process_state state) { panic_invalid_state(); } } - -void process_kill(struct process *p, int ret) { - if (p->state != PS_DEAD) { - if (p->handled_req) { - vfsreq_finish(p->handled_req, -1); - p->handled_req = NULL; - } - - 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; - } - if (p->controlled->user.handler == p) { - assert(p->state == PS_WAITS4REQUEST); - p->controlled->user.handler = NULL; - } - - vfs_backend_refdown(p->controlled); - p->controlled = NULL; - } - - if (p->state == PS_WAITS4FS) - p->waits4fs.req->caller = NULL; - - for (handle_t h = 0; h < HANDLE_MAX; h++) - handle_close(p->handles[h]); - - vfs_mount_remref(p->mount); - p->mount = NULL; - - process_transition(p, PS_DEAD); - p->death_msg = ret; - - if (p->parent) - pagedir_free(p->pages); // TODO put init's pages in the allocator - - // TODO VULN unbounded recursion - struct process *c2; - for (struct process *c = p->child; c; c = c2) { - c2 = c->sibling; - process_kill(c, -1); - } - } - - assert(!p->child); - process_try2collect(p); - - if (p == process_first) shutdown(); -} - -int process_try2collect(struct process *dead) { - struct process *parent = dead->parent; - int ret = -1; - - assert(dead && dead->state == PS_DEAD); - - if (!dead->noreap && parent && parent->state != PS_DEAD) { // might be reaped - if (parent->state != PS_WAITS4CHILDDEATH) return -1; - - 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 6266998..93044d2 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -56,27 +56,26 @@ struct process { extern struct process *process_first; extern struct process *process_current; -// creates the root process +/** Creates the root process. */ struct process *process_seed(struct kmain_info *info); struct process *process_fork(struct process *parent, int flags); -void process_forget(struct process *); // remove references to process +void process_kill(struct process *proc, int ret); +/** Tries to free a process / collect its return value. */ +int process_try2collect(struct process *dead); void process_free(struct process *); -_Noreturn void process_switch_any(void); // switches to any running process +/** Removes a process from the process tree. */ +void process_forget(struct process *); + +/** Switches execution to any running process. */ +_Noreturn void process_switch_any(void); /** Used for iterating over all processes */ struct process *process_next(struct process *); struct process *process_find(enum process_state); -size_t process_find_multiple(enum process_state, struct process **buf, size_t max); -handle_t process_find_handle(struct process *proc, handle_t start_at); // finds the first free handle +handle_t process_find_free_handle(struct process *proc, handle_t start_at); struct handle *process_handle_get(struct process *, handle_t, enum handle_type); void process_transition(struct process *, enum process_state); - -void process_kill(struct process *proc, int ret); - -/** Tries to transistion from PS_DEAD to PS_DEADER. - * @return a nonnegative length of the quit message if successful, a negative val otherwise*/ -int process_try2collect(struct process *dead); diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index f3161e5..3443b60 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -51,7 +51,7 @@ handle_t _syscall_open(const char __user *path, int len) { if (PATH_MAX < len) SYSCALL_RETURN(-1); - if (process_find_handle(process_current, 0) < 0) + if (process_find_free_handle(process_current, 0) < 0) SYSCALL_RETURN(-1); path_buf = virt_cpy2kmalloc(process_current->pages, path, len); @@ -184,7 +184,7 @@ handle_t _syscall_fs_fork2(void) { struct process *child; handle_t front; - front = process_find_handle(process_current, 1); + front = process_find_free_handle(process_current, 1); if (front < 0) SYSCALL_RETURN(-1); process_current->handles[front] = handle_init(HANDLE_FS_FRONT); diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 516e6e0..d6f348a 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -35,7 +35,7 @@ void vfsreq_finish(struct vfs_request *req, int ret) { // we need to wrap the id returned by the VFS in a handle passed to // the client if (req->caller) { - handle_t handle = process_find_handle(req->caller, 0); + handle_t handle = process_find_free_handle(req->caller, 0); if (handle < 0) panic_invalid_state(); // we check for free handles before the open() call |