aboutsummaryrefslogtreecommitdiff
path: root/src/tcb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcb.c')
-rw-r--r--src/tcb.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/src/tcb.c b/src/tcb.c
index c0f82cc..8280deb 100644
--- a/src/tcb.c
+++ b/src/tcb.c
@@ -7,6 +7,7 @@
*/
#include <kmi/tcb.h>
+#include <kmi/ipi.h>
#include <kmi/mem.h>
#include <kmi/conf.h>
#include <kmi/pmem.h>
@@ -200,15 +201,23 @@ struct tcb *create_proc(struct tcb *p)
*/
static stat_t __destroy_thread_data(struct tcb *t)
{
+ catastrophic_assert(t->refcount == 0);
+
+ /* free memory backing rpc stack */
+ destroy_rpc_stack(t);
+
/* free rpc vmem */
destroy_vmem(t->rpc.vmem);
+ /* remove ourselves from the thread pool */
+ tcbs[t->tid] = 0;
+
+ /* forcefully free last struggling bits of memory */
+ destroy_uvmem(t);
+
/* free associated kernel stack and the structure itself */
vm_t bottom = align_down((vm_t)t, order_size(MM_O0));
free_page(MM_O0, (pm_t)bottom);
-
- /** \todo free stacks */
-
return OK;
}
@@ -217,14 +226,19 @@ stat_t destroy_thread(struct tcb *t)
hard_assert(tcbs, ERR_NOINIT);
hard_assert(!is_proc(t), ERR_INVAL);
- /* remove thread id from list */
- /** @todo what about if thread is in rpc? should it rather just be
- * marked dead? */
- tcbs[t->tid] = 0;
+ /* mark us as zombies */
+ t->rid = 0;
/* remove reference to root process */
unreference_proc(get_rproc(t));
+ unqueue_ipi(t);
+
+ /* someone still relies on us existing, don't actually free thread data
+ * quite yet */
+ if (t->refcount)
+ return OK;
+
return __destroy_thread_data(t);
}
@@ -238,22 +252,31 @@ stat_t destroy_proc(struct tcb *p)
unreference_proc(p);
catastrophic_assert(destroy_uvmem(p));
- return __destroy_thread_data(p);
+
+ /* don't destroy thread data just yet, let the thread destroy itself
+ * later */
+ return OK;
}
void reference_proc(struct tcb *p)
{
+ if (!p)
+ return;
+
hard_assert(is_proc(p), RETURN_VOID);
p->refcount++;
}
void unreference_proc(struct tcb *p)
{
+ if (!p)
+ return;
+
hard_assert(is_proc(p), RETURN_VOID);
p->refcount--;
if (p->dead && p->refcount == 0) {
dbg("thread %d is completely destroyed\n", p->tid);
- /** @todo actually destroy */
+ __destroy_thread_data(p);
}
}
@@ -308,3 +331,13 @@ bool running(struct tcb *t)
{
return cpu_tcb(t->cpu_id) == t;
}
+
+bool zombie(struct tcb *t)
+{
+ /* we shouldn't see any NULLs but they're effectively the same thing */
+ if (!t)
+ return true;
+
+ /* thread doesn't belong to any process, a zombie */
+ return t->rid == 0;
+}