diff options
author | Alex Auvolat <alex.auvolat@ens.fr> | 2015-03-02 23:30:16 +0100 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ens.fr> | 2015-03-03 10:30:03 +0100 |
commit | 155f63c4f6995acff2b9c7467cfd91d1f77f3272 (patch) | |
tree | 28e8239e13b50ad3d07b1e777f919ac5297bf6bf /src/kernel/core/thread.c | |
parent | bb1a5fc74769301c0a792cb83d3fa0bda8a780cb (diff) | |
download | kogata-155f63c4f6995acff2b9c7467cfd91d1f77f3272.tar.gz kogata-155f63c4f6995acff2b9c7467cfd91d1f77f3272.zip |
Implement process termination and cleaning up (not completely though)
Diffstat (limited to 'src/kernel/core/thread.c')
-rw-r--r-- | src/kernel/core/thread.c | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c index 02e81e1..63523af 100644 --- a/src/kernel/core/thread.c +++ b/src/kernel/core/thread.c @@ -88,6 +88,21 @@ thread_t* dequeue_thread() { return t; } +void remove_thread_from_queue(thread_t *t) { + if (queue_first_thread == t) { + queue_first_thread = t->next_in_queue; + if (queue_first_thread == 0) queue_last_thread = 0; + } else { + for (thread_t *it = queue_first_thread; it != 0; it = it->next_in_queue) { + if (it->next_in_queue == t) { + it->next_in_queue = t->next_in_queue; + if (it->next_in_queue == 0) queue_last_thread = t; + break; + } + } + } +} + // ================ // // THE TASKING CODE // // ================ // @@ -118,6 +133,9 @@ void run_scheduler() { static void run_thread(void (*entry)(void*), void* data) { ASSERT(current_thread->state == T_STATE_RUNNING); + dbg_printf("Begin thread 0x%p (in process %d)\n", + current_thread, (current_thread->proc ? current_thread->proc->pid : 0)); + switch_pagedir(get_kernel_pagedir()); asm volatile("sti"); @@ -166,15 +184,24 @@ thread_t *new_thread(entry_t entry, void* data) { t->last_ran = 0; t->current_pd_d = get_kernel_pagedir(); + t->critical_level = CL_USER; // used by user processes t->proc = 0; + t->next_in_proc = 0; t->user_ex_handler = 0; - t->critical_level = CL_USER; return t; } +static void delete_thread(thread_t *t) { + if (t->proc != 0) + process_thread_deleted(t); + + region_free_unmap_free(t->stack_region->addr); + free(t); +} + // ========== // // SETUP CODE // // ========== // @@ -227,8 +254,20 @@ void usleep(int usecs) { } void exit() { + void delete_thread_v(void* v) { + delete_thread((thread_t*)v); + } + + int st = enter_critical(CL_NOSWITCH); + // the critical section here does not guarantee that worker_push will return immediately + // (it may switch before adding the delete_thread task), but once the task is added + // no other switch may happen, therefore this thread will not get re-enqueued + + worker_push(delete_thread_v, current_thread); current_thread->state = T_STATE_FINISHED; - // TODO : add job for deleting the thread, or whatever + + exit_critical(st); + yield(); // expected never to return! ASSERT(false); } @@ -249,4 +288,16 @@ bool resume_thread(thread_t *thread) { return ret; } +void kill_thread(thread_t *thread) { + ASSERT(thread != current_thread); + + int st = enter_critical(CL_NOSWITCH); + + thread->state = T_STATE_FINISHED; + remove_thread_from_queue(thread); + delete_thread(thread); + + exit_critical(st); +} + /* vim: set ts=4 sw=4 tw=0 noet :*/ |