summaryrefslogtreecommitdiff
path: root/src/kernel/proc.c
diff options
context:
space:
mode:
authordzwdz2022-08-12 13:45:20 +0200
committerdzwdz2022-08-12 13:45:20 +0200
commit3fa9fee167b9e6f070aba9a1cec1ce69531d9601 (patch)
treeb4ec7896050bb699db0ceaf57a62b3534a386d71 /src/kernel/proc.c
parent215aa95c8d8c85985c1dcc5a994ad164823b39e6 (diff)
kernel/proc: don't expose internal fuctions, clean up api
Diffstat (limited to 'src/kernel/proc.c')
-rw-r--r--src/kernel/proc.c108
1 files changed, 40 insertions, 68 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index fd02f33..2e765c7 100644
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -1,21 +1,25 @@
-#include <camellia/syscalls.h>
#include <kernel/arch/generic.h>
#include <kernel/execbuf.h>
-#include <kernel/main.h>
#include <kernel/mem/alloc.h>
-#include <kernel/mem/virt.h>
#include <kernel/panic.h>
#include <kernel/proc.h>
#include <kernel/vfs/mount.h>
#include <shared/mem.h>
#include <stdint.h>
-struct process *process_first;
+static struct process *process_first = NULL;
struct process *process_current;
static uint32_t next_pid = 0;
-struct process *process_seed(struct kmain_info *info) {
+
+/** Removes a process from the process tree. */
+static void process_forget(struct process *p);
+static _Noreturn void process_switch(struct process *proc);
+
+
+struct process *process_seed(void *data, size_t datalen) {
+ assert(!process_first);
process_first = kmalloc(sizeof *process_first);
memset(process_first, 0, sizeof *process_first);
process_first->state = PS_RUNNING;
@@ -24,6 +28,7 @@ struct process *process_seed(struct kmain_info *info) {
process_first->id = next_pid++;
// map the stack to the last page in memory
+ // TODO move to user bootstrap
pagedir_map(process_first->pages, (userptr_t)~PAGE_MASK, page_zalloc(1), true, true);
process_first->regs.rsp = (userptr_t) ~0xF;
@@ -34,9 +39,8 @@ struct process *process_seed(struct kmain_info *info) {
// map the init module as rw
void __user *init_base = (userptr_t)0x200000;
- for (uintptr_t off = 0; off < info->init.size; off += PAGE_SIZE)
- pagedir_map(process_first->pages, init_base + off, info->init.at + off,
- true, true);
+ for (uintptr_t off = 0; off < datalen; off += PAGE_SIZE)
+ pagedir_map(process_first->pages, init_base + off, data + off, true, true);
process_first->regs.rcx = (uintptr_t)init_base; // SYSRET jumps to %rcx
return process_first;
@@ -164,34 +168,26 @@ void process_kill(struct process *p, int ret) {
if (p == process_first) shutdown();
}
-int process_try2collect(struct process *dead) {
- struct process *parent = dead->parent;
- int ret = -1;
-
+void process_try2collect(struct process *dead) {
assert(dead && dead->state == PS_DEAD);
+ assert(!dead->child);
- 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);
+ struct process *parent = dead->parent;
+ if (!dead->noreap && parent && parent->state != PS_DEAD) { /* reapable? */
+ if (parent->state != PS_WAITS4CHILDDEATH)
+ return; /* don't reap yet */
+ regs_savereturn(&parent->regs, dead->death_msg);
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);
+ if (dead != process_first) {
+ process_forget(dead);
+ kfree(dead);
+ }
}
-void process_forget(struct process *p) {
+/** Removes a process from the process tree. */
+static void process_forget(struct process *p) {
assert(p->parent);
if (p->parent->child == p) {
@@ -222,24 +218,26 @@ _Noreturn void process_switch_any(void) {
if (process_current && process_current->state == PS_RUNNING)
process_switch(process_current);
- struct process *found = process_find(PS_RUNNING);
- if (found) process_switch(found);
+ for (struct process *p = process_first; p; p = process_next(p)) {
+ if (p->state == PS_RUNNING)
+ process_switch(p);
+ }
cpu_pause();
}
}
struct process *process_next(struct process *p) {
- /* is a weird depth-first search, the search order is:
+ /* depth-first search, the order is:
* 1
* / \
* 2 5
* /| |\
* 3 4 6 7
*/
- if (!p) return NULL;
- if (p->child) return p->child;
- if (p->sibling) return p->sibling;
+ if (!p) return NULL;
+ if (p->child) return p->child;
+ if (p->sibling) return p->sibling;
/* looking at the diagram above - we're at 4, want to find 5 */
while (!p->sibling) {
@@ -249,22 +247,12 @@ struct process *process_next(struct process *p) {
return p->sibling;
}
-struct process *process_find(enum process_state target) {
- for (struct process *p = process_first; p; p = process_next(p)) {
- if (p->state == target) return p;
- }
- return NULL;
-}
-
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++) {
- if (proc->handles[handle] == NULL)
- break;
+ for (handle_t hid = start_at; hid < HANDLE_MAX; hid++) {
+ if (proc->handles[hid] == NULL)
+ return hid;
}
- if (handle >= HANDLE_MAX) handle = -1;
- return handle;
+ return -1;
}
struct handle *process_handle_get(struct process *p, handle_t id) {
@@ -273,24 +261,8 @@ struct handle *process_handle_get(struct process *p, handle_t id) {
}
void process_transition(struct process *p, enum process_state state) {
- enum process_state last = p->state;
+ assert(p->state != PS_DEAD);
+ if (state != PS_RUNNING && state != PS_DEAD)
+ assert(p->state == PS_RUNNING);
p->state = state;
- switch (state) {
- case PS_RUNNING:
- assert(last != PS_DEAD);
- break;
- case PS_DEAD:
- // see process_kill
- break;
- case PS_WAITS4CHILDDEATH:
- case PS_WAITS4FS:
- case PS_WAITS4REQUEST:
- case PS_WAITS4PIPE:
- case PS_WAITS4TIMER:
- assert(last == PS_RUNNING);
- break;
-
- case PS_LAST:
- panic_invalid_state();
- }
}