diff options
author | Alex Auvolat <alex.auvolat@ens.fr> | 2015-03-04 11:51:30 +0100 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ens.fr> | 2015-03-04 11:51:30 +0100 |
commit | 503f176e001ddf15e6e32bc912cf10b5764bc23b (patch) | |
tree | 2595bc45e582df3ede9241c00656b65866301e38 /src/kernel/user | |
parent | 0934f9943ef7bdec8c2eee3ea31b5e0f1e8a3faf (diff) | |
download | kogata-503f176e001ddf15e6e32bc912cf10b5764bc23b.tar.gz kogata-503f176e001ddf15e6e32bc912cf10b5764bc23b.zip |
Process exiting & thread termination. IMPORTANT NOTE FOLLOWS.
Threads may now communicate via wait_on(void* ressource) and resume_on (void* ressource).
Previous pause() is replaced by wait_on(current_thread) and resume(thread) by resume_on(thread).
wait_on(x) may return false, indicating that the reason for returning is NOT that resume_on(x)
was called but something else happenned. Typically false indicates that the curent thread
is being killed and must terminate its kernel-land processing as soon as possible.
Diffstat (limited to 'src/kernel/user')
-rw-r--r-- | src/kernel/user/process.c | 105 | ||||
-rw-r--r-- | src/kernel/user/syscall.c | 2 |
2 files changed, 66 insertions, 41 deletions
diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c index a003143..4514218 100644 --- a/src/kernel/user/process.c +++ b/src/kernel/user/process.c @@ -50,10 +50,26 @@ process_t *new_process(process_t *parent) { proc->last_ran = 0; proc->regions = 0; proc->threads = 0; - proc->pid = (next_pid++); + proc->parent = parent; + proc->children = 0; + proc->next_child = 0; + proc->next_fd = 1; + proc->pid = (next_pid++); proc->status = PS_LOADING; + proc->exit_code = 0; + + proc->lock = MUTEX_UNLOCKED; + + if (parent != 0) { + mutex_lock(&parent->lock); + + proc->next_child = parent->children; + parent->children = proc; + + mutex_unlock(&parent->lock); + } return proc; @@ -111,14 +127,14 @@ bool process_new_thread(process_t *p, proc_entry_t entry, void* sp) { th->proc = p; th->user_ex_handler = proc_user_exception; - { int st = enter_critical(CL_NOSWITCH); // it's a bit complicated to use mutexes on process_t + { mutex_lock(&p->lock); th->next_in_proc = p->threads; p->threads = th; - exit_critical(st); } + mutex_unlock(&p->lock); } - resume_thread(th); + start_thread(th); return true; } @@ -138,41 +154,59 @@ bool start_process(process_t *p, void* entry) { return true; } -void process_exit(process_t *p, int status, int exit_code) { - // --- Make sure we are not running in a thread we are about to kill - +void current_process_exit(int status, int exit_code) { void process_exit_v(void* args) { exit_data_t *d = (exit_data_t*)args; process_exit(d->proc, d->status, d->exit_code); free(d); } - if (current_process() == p) { - exit_data_t *d = (exit_data_t*)malloc(sizeof(exit_data_t)); + exit_data_t *d = (exit_data_t*)malloc(sizeof(exit_data_t)); + + d->proc = current_process();; + d->status = status; + d->exit_code = exit_code; - d->proc = p; - d->status = status; - d->exit_code = exit_code; + worker_push(process_exit_v, d); + exit(); +} + +void process_exit(process_t *p, int status, int exit_code) { + // --- Make sure we are not running in a thread we are about to kill + ASSERT(current_process() != p); - worker_push(process_exit_v, d); - pause(); + // ---- Check we are not killing init process + if (p->parent == 0) { + PANIC("Attempted to exit init process!"); } // ---- Now we can do the actual cleanup - int st = enter_critical(CL_NOSWITCH); + mutex_lock(&p->lock); + ASSERT(p->status == PS_RUNNING || p->status == PS_LOADING); p->status = status; p->exit_code = exit_code; + // neutralize the process while (p->threads != 0) { thread_t *t = p->threads; p->threads = p->threads->next_in_proc; - t->proc = 0; + t->proc = 0; // we don't want process_thread_deleted to be called kill_thread(t); } + // terminate all the children as well and free associated process_t structures + while (p->children != 0) { + process_t *ch = p->children; + p->children = ch->next_child; + + if (ch->status == PS_RUNNING || ch->status == PS_LOADING) + process_exit(ch, PS_KILLED, 0); + free(ch); + } + // release file descriptors void release_fd(void* a, void* fd) { unref_file((fs_handle_t*)fd); @@ -202,29 +236,20 @@ void process_exit(process_t *p, int status, int exit_code) { delete_pagedir(p->pd); p->pd = 0; - // orphan children - while (p->children != 0) { - process_t *c = p->children; - p->children = c->next_child; - - c->parent = 0; - c->next_child = 0; - // TODO : if c was terminated, free it or what ? - } - - if (p->parent == 0) { - free(p); - } else { - // TODO : notify parent + // notify parent + process_t *par = p->parent; + if (par->status == PS_RUNNING) { + // TODO: notify that child is exited } - exit_critical(st); + mutex_unlock(&p->lock); } void process_thread_deleted(thread_t *t) { - int st = enter_critical(CL_NOSWITCH); - process_t *p = t->proc; + + mutex_lock(&p->lock); + if (p->threads == t) { p->threads = t->next_in_proc; } else { @@ -236,10 +261,10 @@ void process_thread_deleted(thread_t *t) { } } + mutex_unlock(&p->lock); + if (p->threads == 0 && p->status == PS_RUNNING) process_exit(p, PS_FINISHED, 0); - - exit_critical(st); } @@ -457,7 +482,7 @@ bool munmap(process_t *proc, void* addr) { static void proc_user_exception(registers_t *regs) { dbg_printf("Usermode exception in user process : exiting.\n"); dbg_dump_registers(regs); - process_exit(current_process(), PS_FAILURE, FAIL_EXCEPTION); + current_process_exit(PS_FAILURE, FAIL_EXCEPTION); } static void proc_usermem_pf(void* p, registers_t *regs, void* addr) { process_t *proc = (process_t*)p; @@ -466,13 +491,13 @@ static void proc_usermem_pf(void* p, registers_t *regs, void* addr) { if (r == 0) { dbg_printf("Segmentation fault in process %d (0x%p : not mapped) : exiting.\n", proc->pid, addr); dbg_dump_registers(regs); - process_exit(current_process(), PS_FAILURE, (addr < (void*)PAGE_SIZE ? FAIL_ZEROPTR : FAIL_SEGFAULT)); + current_process_exit(PS_FAILURE, (addr < (void*)PAGE_SIZE ? FAIL_ZEROPTR : FAIL_SEGFAULT)); } bool wr = ((regs->err_code & PF_WRITE_BIT) != 0); if (wr && !(r->mode & MM_WRITE)) { dbg_printf("Segmentation fault in process %d (0x%p : not allowed to write) : exiting.\n", proc->pid, addr); - process_exit(current_process(), PS_FAILURE, (addr < (void*)PAGE_SIZE ? FAIL_ZEROPTR : FAIL_SEGFAULT)); + current_process_exit(PS_FAILURE, (addr < (void*)PAGE_SIZE ? FAIL_ZEROPTR : FAIL_SEGFAULT)); } bool pr = ((regs->err_code & PF_PRESENT_BIT) != 0); @@ -506,7 +531,7 @@ void probe_for_read(const void* addr, size_t len) { if (r == 0 || addr + len > r->addr + r->size || !(r->mode & MM_READ)) { dbg_printf("Access violation on read at 0x%p len 0x%p in process %d : exiting.\n", addr, len, proc->pid); - process_exit(current_process(), PS_FAILURE, FAIL_SC_SEGFAULT); + current_process_exit(PS_FAILURE, FAIL_SC_SEGFAULT); } } @@ -516,7 +541,7 @@ void probe_for_write(const void* addr, size_t len) { if (r == 0 || addr + len > r->addr + r->size || !(r->mode & MM_WRITE)) { dbg_printf("Access violation on write at 0x%p len 0x%p in process %d : exiting.\n", addr, len, proc->pid); - process_exit(current_process(), PS_FAILURE, FAIL_SC_SEGFAULT); + current_process_exit(PS_FAILURE, FAIL_SC_SEGFAULT); } } diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c index d9131b2..73b3341 100644 --- a/src/kernel/user/syscall.c +++ b/src/kernel/user/syscall.c @@ -34,7 +34,7 @@ static char* sc_copy_string(uint32_t s, uint32_t slen) { static uint32_t exit_sc(sc_args_t args) { dbg_printf("Proc %d exit with code %d\n", current_process()->pid, args.a); - process_exit(current_process(), PS_FINISHED, args.a); + current_process_exit(PS_FINISHED, args.a); ASSERT(false); return 0; } |