Index: kernel/arch/ia64/src/drivers/ski.c
===================================================================
--- kernel/arch/ia64/src/drivers/ski.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/arch/ia64/src/drivers/ski.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -258,5 +258,5 @@
 
 	instance->srlnin = srlnin;
-	thread_ready(instance->thread);
+	thread_start(instance->thread);
 
 	sysinfo_set_item_val("kbd", NULL, true);
Index: kernel/arch/sparc64/src/drivers/niagara.c
===================================================================
--- kernel/arch/sparc64/src/drivers/niagara.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/arch/sparc64/src/drivers/niagara.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -253,5 +253,5 @@
 
 			instance->srlnin = srln;
-			thread_ready(instance->thread);
+			thread_start(instance->thread);
 		}
 	}
Index: kernel/genarch/src/kbrd/kbrd.c
===================================================================
--- kernel/genarch/src/kbrd/kbrd.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/genarch/src/kbrd/kbrd.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -200,5 +200,5 @@
 
 	instance->sink = sink;
-	thread_ready(instance->thread);
+	thread_start(instance->thread);
 
 	return &instance->raw;
Index: kernel/genarch/src/kbrd/kbrd_at.c
===================================================================
--- kernel/genarch/src/kbrd/kbrd_at.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/genarch/src/kbrd/kbrd_at.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -198,5 +198,5 @@
 
 	instance->sink = sink;
-	thread_ready(instance->thread);
+	thread_start(instance->thread);
 
 	return &instance->raw;
Index: kernel/genarch/src/srln/srln.c
===================================================================
--- kernel/genarch/src/srln/srln.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/genarch/src/srln/srln.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -156,5 +156,5 @@
 
 	instance->sink = sink;
-	thread_ready(instance->thread);
+	thread_start(instance->thread);
 
 	return &instance->raw;
Index: kernel/generic/include/proc/thread.h
===================================================================
--- kernel/generic/include/proc/thread.h	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/generic/include/proc/thread.h	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -185,4 +185,5 @@
 extern void thread_wire(thread_t *, cpu_t *);
 extern void thread_attach(thread_t *, task_t *);
+extern void thread_start(thread_t *);
 extern void thread_ready(thread_t *);
 extern void thread_exit(void) __attribute__((noreturn));
@@ -242,4 +243,5 @@
 extern errno_t thread_join(thread_t *);
 extern errno_t thread_join_timeout(thread_t *, uint32_t, unsigned int);
+extern void thread_detach(thread_t *);
 
 extern void thread_yield(void);
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/generic/src/console/cmd.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -1004,5 +1004,5 @@
 			printf("cpu%u: ", i);
 			thread_wire(thread, &cpus[i]);
-			thread_ready(thread_ref(thread));
+			thread_start(thread);
 			thread_join(thread);
 		} else
Index: kernel/generic/src/ipc/kbox.c
===================================================================
--- kernel/generic/src/ipc/kbox.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/generic/src/ipc/kbox.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -246,6 +246,6 @@
 		}
 
-		task->kb.thread = thread_ref(kb_thread);
-		thread_ready(kb_thread);
+		task->kb.thread = kb_thread;
+		thread_start(kb_thread);
 	}
 
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/generic/src/main/kinit.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -122,5 +122,5 @@
 
 		thread_wire(thread, &cpus[0]);
-		thread_ready(thread_ref(thread));
+		thread_start(thread);
 		thread_join(thread);
 
@@ -135,5 +135,6 @@
 			if (thread != NULL) {
 				thread_wire(thread, &cpus[i]);
-				thread_ready(thread);
+				thread_start(thread);
+				thread_detach(thread);
 			} else
 				log(LF_OTHER, LVL_ERROR,
@@ -151,8 +152,10 @@
 	thread = thread_create(kload, NULL, TASK, THREAD_FLAG_NONE,
 	    "kload");
-	if (thread != NULL)
-		thread_ready(thread);
-	else
+	if (thread != NULL) {
+		thread_start(thread);
+		thread_detach(thread);
+	} else {
 		log(LF_OTHER, LVL_ERROR, "Unable to create kload thread");
+	}
 
 #ifdef CONFIG_KCONSOLE
@@ -163,9 +166,11 @@
 		thread = thread_create(kconsole_thread, NULL, TASK,
 		    THREAD_FLAG_NONE, "kconsole");
-		if (thread != NULL)
-			thread_ready(thread);
-		else
+		if (thread != NULL) {
+			thread_start(thread);
+			thread_detach(thread);
+		} else {
 			log(LF_OTHER, LVL_ERROR,
 			    "Unable to create kconsole thread");
+		}
 	}
 #endif /* CONFIG_KCONSOLE */
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/generic/src/main/main.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -282,5 +282,6 @@
 	if (!kinit_thread)
 		panic("Cannot create kinit thread.");
-	thread_ready(kinit_thread);
+	thread_start(kinit_thread);
+	thread_detach(kinit_thread);
 
 	/*
Index: kernel/generic/src/proc/program.c
===================================================================
--- kernel/generic/src/proc/program.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/generic/src/proc/program.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -212,5 +212,6 @@
 void program_ready(program_t *prg)
 {
-	thread_ready(prg->main_thread);
+	thread_start(prg->main_thread);
+	thread_detach(prg->main_thread);
 	prg->main_thread = NULL;
 }
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/generic/src/proc/thread.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -234,4 +234,14 @@
 }
 
+/** Start a thread that wasn't started yet since it was created.
+ *
+ * @param thread A reference to the newly created thread.
+ */
+void thread_start(thread_t *thread)
+{
+	assert(thread->state == Entering);
+	thread_ready(thread_ref(thread));
+}
+
 /** Make thread ready
  *
@@ -696,4 +706,6 @@
 errno_t thread_join_timeout(thread_t *thread, uint32_t usec, unsigned int flags)
 {
+	assert(thread != NULL);
+
 	if (thread == THREAD)
 		return EINVAL;
@@ -712,4 +724,9 @@
 
 	return rc;
+}
+
+void thread_detach(thread_t *thread)
+{
+	thread_put(thread);
 }
 
Index: kernel/test/mm/falloc2.c
===================================================================
--- kernel/test/mm/falloc2.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/test/mm/falloc2.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -43,5 +43,4 @@
 #define THREADS      8
 
-static atomic_size_t thread_cnt;
 static atomic_size_t thread_fail;
 
@@ -56,5 +55,4 @@
 		    "Unable to allocate frames\n", THREAD->tid, CPU->id);
 		atomic_inc(&thread_fail);
-		atomic_dec(&thread_cnt);
 		return;
 	}
@@ -108,11 +106,11 @@
 	TPRINTF("Thread #%" PRIu64 " (cpu%u): Exiting\n",
 	    THREAD->tid, CPU->id);
-	atomic_dec(&thread_cnt);
 }
 
 const char *test_falloc2(void)
 {
-	atomic_store(&thread_cnt, THREADS);
 	atomic_store(&thread_fail, 0);
+
+	thread_t *threads[THREADS] = { };
 
 	for (unsigned int i = 0; i < THREADS; i++) {
@@ -123,11 +121,13 @@
 			break;
 		}
-		thread_ready(thrd);
+		thread_start(thrd);
+		threads[i] = thrd;
 	}
 
-	while (atomic_load(&thread_cnt) > 0) {
-		TPRINTF("Threads left: %zu\n",
-		    atomic_load(&thread_cnt));
-		thread_sleep(1);
+	for (unsigned int i = 0; i < THREADS; i++) {
+		if (threads[i] != NULL)
+			thread_join(threads[i]);
+
+		TPRINTF("Threads left: %u\n", THREADS - i - 1);
 	}
 
Index: kernel/test/mm/slab1.c
===================================================================
--- kernel/test/mm/slab1.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/test/mm/slab1.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -121,5 +121,4 @@
 static void *thr_data[THREADS][THR_MEM_COUNT];
 static slab_cache_t *thr_cache;
-static semaphore_t thr_sem;
 
 static void slabtest(void *data)
@@ -142,26 +141,27 @@
 
 	TPRINTF("Thread #%" PRIu64 " finished\n", THREAD->tid);
-
-	semaphore_up(&thr_sem);
 }
 
 static void testthreads(void)
 {
-	thread_t *t;
-	int i;
-
 	thr_cache = slab_cache_create("thread_cache", THR_MEM_SIZE, 0, NULL, NULL,
 	    SLAB_CACHE_NOMAGAZINE);
 
-	semaphore_initialize(&thr_sem, 0);
-	for (i = 0; i < THREADS; i++) {
-		if (!(t = thread_create(slabtest, (void *) (sysarg_t) i, TASK, THREAD_FLAG_NONE, "slabtest"))) {
+	thread_t *threads[THREADS] = { };
+
+	for (int i = 0; i < THREADS; i++) {
+		threads[i] = thread_create(slabtest, (void *) (sysarg_t) i,
+		    TASK, THREAD_FLAG_NONE, "slabtest");
+		if (threads[i]) {
+			thread_start(threads[i]);
+		} else {
 			TPRINTF("Could not create thread %d\n", i);
-		} else
-			thread_ready(t);
+		}
 	}
 
-	for (i = 0; i < THREADS; i++)
-		semaphore_down(&thr_sem);
+	for (int i = 0; i < THREADS; i++) {
+		if (threads[i] != NULL)
+			thread_join(threads[i]);
+	}
 
 	slab_cache_destroy(thr_cache);
Index: kernel/test/mm/slab2.c
===================================================================
--- kernel/test/mm/slab2.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/test/mm/slab2.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -127,5 +127,4 @@
 
 static slab_cache_t *thr_cache;
-static semaphore_t thr_sem;
 static condvar_t thread_starter;
 static mutex_t starter_mutex;
@@ -188,6 +187,4 @@
 	if (!test_quiet)
 		slab_print_list();
-
-	semaphore_up(&thr_sem);
 }
 
@@ -198,6 +195,4 @@
 	 * then release everything, then again allocate, then release
 	 */
-	thread_t *t;
-	int i;
 
 	TPRINTF("Running stress test with size %d\n", size);
@@ -207,16 +202,24 @@
 
 	thr_cache = slab_cache_create("thread_cache", size, 0, NULL, NULL, 0);
-	semaphore_initialize(&thr_sem, 0);
-	for (i = 0; i < THREADS; i++) {
-		if (!(t = thread_create(slabtest, NULL, TASK, THREAD_FLAG_NONE, "slabtest"))) {
+
+	thread_t *threads[THREADS] = { };
+
+	for (int i = 0; i < THREADS; i++) {
+		threads[i] = thread_create(slabtest, NULL,
+		    TASK, THREAD_FLAG_NONE, "slabtest");
+		if (threads[i]) {
+			thread_start(threads[i]);
+		} else {
 			TPRINTF("Could not create thread %d\n", i);
-		} else
-			thread_ready(t);
-	}
+		}
+	}
+
 	thread_sleep(1);
 	condvar_broadcast(&thread_starter);
 
-	for (i = 0; i < THREADS; i++)
-		semaphore_down(&thr_sem);
+	for (int i = 0; i < THREADS; i++) {
+		if (threads[i] != NULL)
+			thread_join(threads[i]);
+	}
 
 	slab_cache_destroy(thr_cache);
Index: kernel/test/synch/semaphore1.c
===================================================================
--- kernel/test/synch/semaphore1.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/test/synch/semaphore1.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -89,16 +89,20 @@
 				thrd = thread_create(consumer, NULL, TASK,
 				    THREAD_FLAG_NONE, "consumer");
-				if (thrd)
-					thread_ready(thrd);
-				else
+				if (thrd) {
+					thread_start(thrd);
+					thread_detach(thrd);
+				} else {
 					TPRINTF("could not create consumer %d\n", i);
+				}
 			}
 			for (k = 0; k < (4 - i); k++) {
 				thrd = thread_create(producer, NULL, TASK,
 				    THREAD_FLAG_NONE, "producer");
-				if (thrd)
-					thread_ready(thrd);
-				else
+				if (thrd) {
+					thread_start(thrd);
+					thread_detach(thrd);
+				} else {
 					TPRINTF("could not create producer %d\n", i);
+				}
 			}
 		}
Index: kernel/test/synch/semaphore2.c
===================================================================
--- kernel/test/synch/semaphore2.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/test/synch/semaphore2.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -92,8 +92,10 @@
 		thrd = thread_create(consumer, NULL, TASK,
 		    THREAD_FLAG_NONE, "consumer");
-		if (thrd)
-			thread_ready(thrd);
-		else
+		if (thrd) {
+			thread_start(thrd);
+			thread_detach(thrd);
+		} else {
 			TPRINTF("Error creating thread\n");
+		}
 	}
 
Index: kernel/test/thread/thread1.c
===================================================================
--- kernel/test/thread/thread1.c	(revision a064d4fc00192ecc7d42d04ecfb3474585fef055)
+++ kernel/test/thread/thread1.c	(revision 0f4f1b286ec18fe5bc220bbc629fc26b6813d889)
@@ -38,5 +38,4 @@
 
 static atomic_bool finish;
-static atomic_size_t threads_finished;
 
 static void threadtest(void *data)
@@ -46,24 +45,22 @@
 		thread_usleep(100000);
 	}
-	atomic_inc(&threads_finished);
 }
 
 const char *test_thread1(void)
 {
-	unsigned int i;
-	size_t total = 0;
+	atomic_store(&finish, true);
 
-	atomic_store(&finish, true);
-	atomic_store(&threads_finished, 0);
+	thread_t *threads[THREADS] = { };
 
-	for (i = 0; i < THREADS; i++) {
-		thread_t *t;
-		if (!(t = thread_create(threadtest, NULL, TASK,
-		    THREAD_FLAG_NONE, "threadtest"))) {
+	for (int i = 0; i < THREADS; i++) {
+		threads[i] = thread_create(threadtest, NULL,
+		    TASK, THREAD_FLAG_NONE, "threadtest");
+
+		if (threads[i]) {
+			thread_start(threads[i]);
+		} else {
 			TPRINTF("Could not create thread %d\n", i);
 			break;
 		}
-		thread_ready(t);
-		total++;
 	}
 
@@ -72,7 +69,10 @@
 
 	atomic_store(&finish, false);
-	while (atomic_load(&threads_finished) < total) {
-		TPRINTF("Threads left: %zu\n", total - atomic_load(&threads_finished));
-		thread_sleep(1);
+
+	for (int i = 0; i < THREADS; i++) {
+		if (threads[i] != NULL)
+			thread_join(threads[i]);
+
+		TPRINTF("Threads left: %d\n", THREADS - i - 1);
 	}
 
