summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/proc.c190
-rw-r--r--src/kernel/proc.h21
-rw-r--r--src/kernel/syscalls.c4
-rw-r--r--src/kernel/vfs/request.c2
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