diff options
author | Alex Auvolat <alex@adnab.me> | 2015-03-11 09:27:16 +0100 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2015-03-11 09:27:16 +0100 |
commit | aa5e2760711c092e1235105ebf097ac594512370 (patch) | |
tree | d191ead558d5913cc51df8734398c7fe981d80e9 | |
parent | 0e50ada984473de20ba47c2ebdbe36b3dad78dd1 (diff) | |
download | kogata-aa5e2760711c092e1235105ebf097ac594512370.tar.gz kogata-aa5e2760711c092e1235105ebf097ac594512370.zip |
Fix process exiting.
-rw-r--r-- | src/common/include/proto/proc.h | 7 | ||||
-rw-r--r-- | src/kernel/core/thread.c | 23 | ||||
-rw-r--r-- | src/kernel/include/process.h | 2 | ||||
-rw-r--r-- | src/kernel/include/thread.h | 1 | ||||
-rw-r--r-- | src/kernel/user/process.c | 55 | ||||
-rw-r--r-- | src/sysbin/giosrv/main.c | 6 |
6 files changed, 54 insertions, 40 deletions
diff --git a/src/common/include/proto/proc.h b/src/common/include/proto/proc.h index fafb2fd..29b5b91 100644 --- a/src/common/include/proto/proc.h +++ b/src/common/include/proto/proc.h @@ -7,10 +7,9 @@ typedef int pid_t; #define PS_LOADING 1 #define PS_RUNNING 2 -#define PS_EXITING 3 -#define PS_FINISHED 4 -#define PS_FAILURE 5 // exception or segfault or stuff -#define PS_KILLED 6 +#define PS_FINISHED 3 +#define PS_FAILURE 4 // exception or segfault or stuff +#define PS_KILLED 5 #define FAIL_EXCEPTION 1 // unhandled processor exception #define FAIL_ZEROPTR 2 // segfault at < 4k diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c index 3086be0..4e15c0e 100644 --- a/src/kernel/core/thread.c +++ b/src/kernel/core/thread.c @@ -208,11 +208,10 @@ thread_t *new_thread(entry_t entry, void* data) { return t; } -static void delete_thread(thread_t *t) { - dbg_printf("Deleting thread 0x%p\n", t); +void delete_thread(thread_t *t) { + ASSERT(t->state == T_STATE_FINISHED); - if (t->proc != 0) - process_thread_deleted(t); + dbg_printf("Deleting thread 0x%p\n", t); region_free_unmap_free(t->stack_region->addr); free(t); @@ -340,8 +339,16 @@ void usleep(int usecs) { } void exit() { - void delete_thread_v(void* v) { - delete_thread((thread_t*)v); + void exit_cleanup_task(void* v) { + thread_t *t = (thread_t*)v; + + if (t->proc == 0) { + // stand alone thread, can be deleted safely + delete_thread(t); + } else { + // call specific routine from process code + process_thread_exited(t); + } } int st = enter_critical(CL_NOSWITCH); @@ -351,9 +358,9 @@ void exit() { dbg_printf("Thread 0x%p exiting.\n", current_thread); - worker_push(delete_thread_v, current_thread); - current_thread->state = T_STATE_FINISHED; + worker_push(exit_cleanup_task, current_thread); + current_thread->state = T_STATE_FINISHED; exit_critical(st); yield(); // expected never to return! diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index d4fcfc3..ddeac90 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -84,7 +84,7 @@ void process_exit(process_t *p, int status, int exit_code); // exit specified p void current_process_exit(int status, int exit_code); bool process_new_thread(process_t *p, proc_entry_t entry, void* sp); -void process_thread_deleted(thread_t *t); // called by threading code when a thread exits +void process_thread_exited(thread_t *t); // called by threading code when a thread exits process_t *process_find_child(process_t *p, int pid); void process_get_status(process_t *p, proc_status_t *st); diff --git a/src/kernel/include/thread.h b/src/kernel/include/thread.h index f9df0ea..4b140fa 100644 --- a/src/kernel/include/thread.h +++ b/src/kernel/include/thread.h @@ -44,6 +44,7 @@ typedef void (*entry_t)(void*); void threading_setup(entry_t cont, void* data); // never returns thread_t *new_thread(entry_t entry, void* data); // thread is PAUSED, and must be started with start_thread void start_thread(thread_t *t); +void delete_thread(thread_t *t); void irq0_handler(registers_t *regs, int crit_level); diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c index 63b568a..e46fde8 100644 --- a/src/kernel/user/process.c +++ b/src/kernel/user/process.c @@ -161,26 +161,14 @@ void current_process_exit(int status, int exit_code) { free(d); } - process_t *p = current_process(); - - mutex_lock(&p->lock); - if (p->status == PS_EXITING) { - mutex_unlock(&p->lock); - exit(); - } - - p->status = PS_EXITING; - exit_data_t *d = (exit_data_t*)malloc(sizeof(exit_data_t)); - d->proc = p; + d->proc = current_process();; d->status = status; d->exit_code = exit_code; while (!worker_push(process_exit_v, d)) yield(); - mutex_unlock(&p->lock); - exit(); } @@ -197,17 +185,21 @@ void process_exit(process_t *p, int status, int exit_code) { mutex_lock(&p->lock); - ASSERT(p->status == PS_RUNNING || p->status == PS_LOADING || p->status == PS_EXITING); + if (!(p->status == PS_RUNNING || p->status == PS_LOADING)) { + mutex_unlock(&p->lock); + return; + } + 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; + p->threads = t->next_in_proc; - t->proc = 0; // we don't want process_thread_deleted to be called kill_thread(t); + delete_thread(t); } // terminate all the children as well and free associated process_t structures @@ -259,26 +251,35 @@ void process_exit(process_t *p, int status, int exit_code) { mutex_unlock(&p->lock); } -void process_thread_deleted(thread_t *t) { +void process_thread_exited(thread_t *t) { process_t *p = t->proc; + if (p->status != PS_RUNNING) return; + mutex_lock(&p->lock); - if (p->threads == t) { - p->threads = t->next_in_proc; - } else { - for (thread_t *it = p->threads; it != 0; it = it->next_in_proc) { - if (it->next_in_proc == t) { - it->next_in_proc = t->next_in_proc; - break; + if (p->status == PS_RUNNING) { + if (p->threads == t) { + p->threads = t->next_in_proc; + } else { + for (thread_t *it = p->threads; it != 0; it = it->next_in_proc) { + if (it->next_in_proc == t) { + it->next_in_proc = t->next_in_proc; + break; + } } } + + delete_thread(t); + + if (p->threads == 0) { + mutex_unlock(&p->lock); + process_exit(p, PS_FINISHED, 0); + return; + } } mutex_unlock(&p->lock); - - if (p->threads == 0 && p->status == PS_RUNNING) - process_exit(p, PS_FINISHED, 0); } // =========================== // diff --git a/src/sysbin/giosrv/main.c b/src/sysbin/giosrv/main.c index 04e57ea..7827670 100644 --- a/src/sysbin/giosrv/main.c +++ b/src/sysbin/giosrv/main.c @@ -20,6 +20,12 @@ int main(int argc, char **argv) { ASSERT(r == 1); dbg_printf("[giosrv] Running on FB %dx%d\n", i.width, i.height); + void* fb_map = region_alloc(i.height * i.pitch, "Framebuffer"); + ASSERT(fb_map != 0); + + ASSERT(mmap_file(fbdev, 0, fb_map, i.height * i.pitch, MM_READ | MM_WRITE)); + memset(fb_map, 0, i.height * i.pitch); + while(true); // nothing to do return 0; |