aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/core/thread.c
diff options
context:
space:
mode:
authorAlex Auvolat <alex.auvolat@ens.fr>2015-03-02 23:30:16 +0100
committerAlex Auvolat <alex.auvolat@ens.fr>2015-03-03 10:30:03 +0100
commit155f63c4f6995acff2b9c7467cfd91d1f77f3272 (patch)
tree28e8239e13b50ad3d07b1e777f919ac5297bf6bf /src/kernel/core/thread.c
parentbb1a5fc74769301c0a792cb83d3fa0bda8a780cb (diff)
downloadkogata-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.c55
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 :*/