aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2015-03-11 09:27:16 +0100
committerAlex Auvolat <alex@adnab.me>2015-03-11 09:27:16 +0100
commitaa5e2760711c092e1235105ebf097ac594512370 (patch)
treed191ead558d5913cc51df8734398c7fe981d80e9 /src/kernel
parent0e50ada984473de20ba47c2ebdbe36b3dad78dd1 (diff)
downloadkogata-aa5e2760711c092e1235105ebf097ac594512370.tar.gz
kogata-aa5e2760711c092e1235105ebf097ac594512370.zip
Fix process exiting.
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/core/thread.c23
-rw-r--r--src/kernel/include/process.h2
-rw-r--r--src/kernel/include/thread.h1
-rw-r--r--src/kernel/user/process.c55
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);
}
// =========================== //