1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#include <kernel/arch/generic.h>
#include <kernel/mem.h>
#include <kernel/panic.h>
#include <kernel/proc.h>
#include <kernel/util.h>
#include <kernel/vfs/mount.h>
#include <stdint.h>
struct process *process_first;
struct process *process_current;
uint32_t next_pid = 0;
struct process *process_seed(void) {
struct process *proc = kmalloc(sizeof(struct process));
proc->pages = pagedir_new();
proc->state = PS_RUNNING;
proc->sibling = NULL;
proc->child = NULL;
proc->parent = NULL;
proc->mount = vfs_mount_seed();
proc->id = next_pid++;
process_first = proc;
for (int i = 0; i < HANDLE_MAX; i++)
proc->handles[i].type = HANDLE_EMPTY;
// map the stack to the last page in memory
pagedir_map(proc->pages, ~PAGE_MASK, page_alloc(1), true, true);
proc->stack_top = proc->regs.esp = ~0xF;
// map the kernel
// yup, .text is writeable too. the plan is to not map the kernel
// into user memory at all, but i'll implement that later. TODO
for (size_t p = 0x100000; p < (size_t)&_bss_end; p += PAGE_SIZE)
pagedir_map(proc->pages, p, (void*)p, false, true);
// the kernel still has to load the executable code and set EIP
return proc;
}
struct process *process_fork(struct process *parent) {
struct process *child = kmalloc(sizeof(struct process));
memcpy(child, parent, sizeof(struct process));
child->pages = pagedir_copy(parent->pages);
child->sibling = parent->child;
child->child = NULL;
child->parent = parent;
parent->child = child;
child->id = next_pid++;
return child;
}
void process_switch(struct process *proc) {
process_current = proc;
pagedir_switch(proc->pages);
sysexit(proc->regs);
}
_Noreturn void process_switch_any(void) {
struct process *found = process_find(PS_RUNNING);
if (found)
process_switch(found);
tty_const(" no running processes left...");
panic();
}
// TODO there's no check for going past the stack - VULN
struct process *_process_find_recursive(
enum process_state target, struct process *iter) {
struct process *in;
while (iter) {
if (iter->state == target)
return iter;
// DFS
in = _process_find_recursive(target, iter->child);
if (in)
return in;
iter = iter->sibling;
}
return NULL;
}
struct process *process_find(enum process_state target) {
return _process_find_recursive(target, process_first);
}
handle_t process_find_handle(struct process *proc) {
handle_t handle;
for (handle = 0; handle < HANDLE_MAX; handle++) {
if (proc->handles[handle].type == HANDLE_EMPTY)
break;
}
if (handle == HANDLE_MAX) handle = -1;
return handle;
}
|