diff options
author | dzwdz | 2023-01-19 23:36:11 +0100 |
---|---|---|
committer | dzwdz | 2023-01-19 23:36:11 +0100 |
commit | a2f9ae9d4ab678fa66a2ec5d1072ea22a36a18a1 (patch) | |
tree | c048e9165b27d27075d2c17ab943ac52b46a6a40 /src/kernel/proc.c | |
parent | da546a0822b1995efe1832c9cc57aab62ccdcf65 (diff) |
kernel: user interrupts
Diffstat (limited to 'src/kernel/proc.c')
-rwxr-xr-x | src/kernel/proc.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c index d105f66..d8c7e57 100755 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -3,6 +3,7 @@ #include <kernel/arch/generic.h> #include <kernel/execbuf.h> #include <kernel/mem/alloc.h> +#include <kernel/mem/virt.h> #include <kernel/panic.h> #include <kernel/proc.h> #include <kernel/vfs/mount.h> @@ -65,6 +66,7 @@ struct process *process_fork(struct process *parent, int flags) { child->regs = parent->regs; child->state = parent->state; assert(child->state == PS_RUNNING); // not copying the state union + child->intr_fn = parent->intr_fn; child->noreap = (flags & FORK_NOREAP) > 0; @@ -188,12 +190,15 @@ void process_kill(struct process *p, int ret) { } if (p->state == PS_DYING) { - if (p->parent && proc_alive(p->parent) && !p->noreap) { + if (p->parent && proc_alive(p->parent)) { process_transition(p, PS_TOREAP); } else { process_transition(p, PS_TOMBSTONE); } } + if (p == process_first) { + assert(!p->child); + } process_tryreap(p); if (p == process_first) { @@ -271,6 +276,21 @@ void process_tryreap(struct process *dead) { } } +void process_intr(struct process *p) { + if (!p->intr_fn) return; + + /* save old rsp,rip */ + struct intr_data d; + void __user *sp = p->regs.rsp - 128 - sizeof(d); + d.ip = (void __user *)p->regs.rcx; + d.sp = p->regs.rsp; + virt_cpy_to(p->pages, sp, &d, sizeof(d)); + + /* switch to intr handler */ + p->regs.rcx = (uint64_t)p->intr_fn; + p->regs.rsp = sp; +} + /** Removes a process from the process tree. */ static void process_forget(struct process *p) { assert(p->parent); @@ -447,6 +467,11 @@ void process_transition(struct process *p, enum process_state state) { assert(p->state == PS_TOREAP || p->state == PS_DYING); } else if (state == PS_TOREAP) { assert(p->state == PS_DYING); + + assert(!p->parent || proc_alive(p->parent)); + for (struct process *it = p->child; it; it = it->sibling) { + assert(p->state != PS_TOREAP); + } } else if (state != PS_RUNNING && state != PS_DYING) { assert(p->state == PS_RUNNING); } |