diff options
Diffstat (limited to 'src/kernel')
-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 |
4 files changed, 45 insertions, 36 deletions
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); } // =========================== // |