Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision d84319865c1131f37cbdba6ba952c5d38c735d0d)
+++ kernel/generic/src/proc/thread.c	(revision ea7890e7d40b57d264d11b6a6ded9dd8c6454424)
@@ -68,4 +68,5 @@
 #include <syscall/copy.h>
 #include <errno.h>
+#include <console/klog.h>
 
 
@@ -78,5 +79,5 @@
 	"Entering",
 	"Exiting",
-	"Undead"
+	"JoinMe"
 }; 
 
@@ -329,5 +330,4 @@
 
 	t->interrupted = false;	
-	t->join_type = None;
 	t->detached = false;
 	waitq_initialize(&t->join_wq);
@@ -343,21 +343,4 @@
 	thread_create_arch(t);	
 
-	ipl = interrupts_disable();	 
-	spinlock_lock(&task->lock);
-	if (!task->accept_new_threads) {
-		spinlock_unlock(&task->lock);
-		slab_free(thread_slab, t);
-		interrupts_restore(ipl);
-		return NULL;
-	} else {
-		/*
-		 * Bump the reference count so that this task cannot be
-		 * destroyed while the new thread is being attached to it.
-		 */
-		task->refcount++;
-	}
-	spinlock_unlock(&task->lock);
-	interrupts_restore(ipl);
-
 	if (!(flags & THREAD_FLAG_NOATTACH))
 		thread_attach(t, task);
@@ -374,7 +357,5 @@
 void thread_destroy(thread_t *t)
 {
-	bool destroy_task = false;
-
-	ASSERT(t->state == Exiting || t->state == Undead);
+	ASSERT(t->state == Exiting || t->state == JoinMe);
 	ASSERT(t->task);
 	ASSERT(t->cpu);
@@ -396,11 +377,11 @@
 	spinlock_lock(&t->task->lock);
 	list_remove(&t->th_link);
-	if (--t->task->refcount == 0) {
-		t->task->accept_new_threads = false;
-		destroy_task = true;
-	}
 	spinlock_unlock(&t->task->lock);	
-	
-	if (destroy_task)
+
+	/*
+	 * t is guaranteed to be the very last thread of its task.
+	 * It is safe to destroy the task.
+	 */
+	if (atomic_predec(&t->task->refcount) == 0)
 		task_destroy(t->task);
 	
@@ -432,10 +413,9 @@
 	 * Attach to the current task.
 	 */
-	ipl = interrupts_disable();	 
+	ipl = interrupts_disable();
 	spinlock_lock(&task->lock);
-	ASSERT(task->refcount);
+	atomic_inc(&task->refcount);
+	atomic_inc(&task->lifecount);
 	list_append(&t->th_link, &task->th_head);
-	if (task->refcount == 1)
-		task->main_thread = t;
 	spinlock_unlock(&task->lock);
 
@@ -459,4 +439,19 @@
 {
 	ipl_t ipl;
+
+	if (atomic_predec(&TASK->lifecount) == 0) {
+		/*
+		 * We are the last thread in the task that still has not exited.
+		 * With the exception of the moment the task was created, new
+		 * threads can only be created by threads of the same task.
+		 * We are safe to perform cleanup.
+		 */
+		if (THREAD->flags & THREAD_FLAG_USPACE) {
+			ipc_cleanup();
+		        futex_cleanup();
+			klog_printf("Cleanup of task %llu completed.",
+			    TASK->taskid);
+		}
+	}
 
 restart:
@@ -469,4 +464,5 @@
 		goto restart;
 	}
+	
 	THREAD->state = Exiting;
 	spinlock_unlock(&THREAD->lock);
@@ -525,5 +521,5 @@
 /** Detach thread.
  *
- * Mark the thread as detached, if the thread is already in the Undead state,
+ * Mark the thread as detached, if the thread is already in the JoinMe state,
  * deallocate its resources.
  *
@@ -541,5 +537,5 @@
 	spinlock_lock(&t->lock);
 	ASSERT(!t->detached);
-	if (t->state == Undead) {
+	if (t->state == JoinMe) {
 		thread_destroy(t);	/* unlocks &t->lock */
 		interrupts_restore(ipl);
@@ -703,6 +699,4 @@
 			    sizeof(t->tid));
 			if (rc != 0) {
-				ipl_t ipl;
-
 				/*
 				 * We have encountered a failure, but the thread
@@ -712,23 +706,10 @@
 
 				/*
-				 * The new thread structure is initialized,
-				 * but is still not visible to the system.
+				 * The new thread structure is initialized, but
+				 * is still not visible to the system.
 				 * We can safely deallocate it.
 				 */
 				slab_free(thread_slab, t);
 			 	free(kernel_uarg);
-
-				/*
-				 * Now we need to decrement the task reference
-				 * counter. Because we are running within the
-				 * same task, thread t is not the last thread
-				 * in the task, so it is safe to merely
-				 * decrement the counter.
-				 */
-				ipl = interrupts_disable();
-				spinlock_lock(&TASK->lock);
-				TASK->refcount--;
-				spinlock_unlock(&TASK->lock);
-				interrupts_restore(ipl);
 
 				return (unative_t) rc;
