Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision a35b458e9db1ca95e679799dc7c1b12c83359ca3)
+++ uspace/lib/c/generic/fibril.c	(revision 80f345c2d6df8e54090633e7132fcb9939f93150)
@@ -44,5 +44,5 @@
 #include <stdio.h>
 #include <libarch/barrier.h>
-#include <libarch/faddr.h>
+#include <context.h>
 #include <futex.h>
 #include <assert.h>
@@ -155,5 +155,27 @@
 	futex_lock(&fibril_futex);
 
+	fibril_t *srcf = __tcb_get()->fibril_data;
+	fibril_t *dstf = NULL;
+
+	/* Choose a new fibril to run */
 	switch (stype) {
+	case FIBRIL_TO_MANAGER:
+	case FIBRIL_FROM_DEAD:
+		/* Make sure the async_futex is held. */
+		assert((atomic_signed_t) async_futex.val.count <= 0);
+
+		/* If we are going to manager and none exists, create it */
+		while (list_empty(&manager_list)) {
+			futex_unlock(&fibril_futex);
+			async_create_manager();
+			futex_lock(&fibril_futex);
+		}
+
+		dstf = list_get_instance(list_first(&manager_list),
+		    fibril_t, link);
+
+		if (stype == FIBRIL_FROM_DEAD)
+			dstf->clean_after_me = srcf;
+		break;
 	case FIBRIL_PREEMPT:
 	case FIBRIL_FROM_MANAGER:
@@ -162,88 +184,30 @@
 			return 0;
 		}
-		break;
-	case FIBRIL_TO_MANAGER:
-	case FIBRIL_FROM_DEAD:
-		/* Make sure the async_futex is held. */
-		assert((atomic_signed_t) async_futex.val.count <= 0);
-
-		/* If we are going to manager and none exists, create it */
-		while (list_empty(&manager_list)) {
-			futex_unlock(&fibril_futex);
-			async_create_manager();
-			futex_lock(&fibril_futex);
-		}
-		break;
-	}
-
-	fibril_t *srcf = __tcb_get()->fibril_data;
-	if (stype != FIBRIL_FROM_DEAD) {
-
-		/* Save current state */
-		if (!context_save(&srcf->ctx)) {
-			if (srcf->clean_after_me) {
-				/*
-				 * Cleanup after the dead fibril from which we
-				 * restored context here.
-				 */
-				void *stack = srcf->clean_after_me->stack;
-				if (stack) {
-					/*
-					 * This check is necessary because a
-					 * thread could have exited like a
-					 * normal fibril using the
-					 * FIBRIL_FROM_DEAD switch type. In that
-					 * case, its fibril will not have the
-					 * stack member filled.
-					 */
-					as_area_destroy(stack);
-				}
-				fibril_teardown(srcf->clean_after_me, true);
-				srcf->clean_after_me = NULL;
-			}
-
-			return 1;	/* futex_unlock already done here */
-		}
-
-		/* Put the current fibril into the correct run list */
-		switch (stype) {
-		case FIBRIL_PREEMPT:
-			list_append(&srcf->link, &ready_list);
-			break;
-		case FIBRIL_FROM_MANAGER:
-			list_append(&srcf->link, &manager_list);
-			break;
-		default:
-			assert(stype == FIBRIL_TO_MANAGER);
-
-			srcf->switches++;
-
-			/*
-			 * Don't put the current fibril into any list, it should
-			 * already be somewhere, or it will be lost.
-			 */
-			break;
-		}
-	}
-
-	fibril_t *dstf;
-
-	/* Choose a new fibril to run */
-	switch (stype) {
-	case FIBRIL_TO_MANAGER:
-	case FIBRIL_FROM_DEAD:
-		dstf = list_get_instance(list_first(&manager_list), fibril_t,
-		    link);
-
-		if (stype == FIBRIL_FROM_DEAD)
-			dstf->clean_after_me = srcf;
-		break;
-	default:
+
 		dstf = list_get_instance(list_first(&ready_list), fibril_t,
 		    link);
 		break;
 	}
-
 	list_remove(&dstf->link);
+
+	/* Put the current fibril into the correct run list */
+	switch (stype) {
+	case FIBRIL_PREEMPT:
+		list_append(&srcf->link, &ready_list);
+		break;
+	case FIBRIL_FROM_MANAGER:
+		list_append(&srcf->link, &manager_list);
+		break;
+	case FIBRIL_FROM_DEAD:
+		// Nothing.
+		break;
+	case FIBRIL_TO_MANAGER:
+		srcf->switches++;
+		/*
+		 * Don't put the current fibril into any list, it should
+		 * already be somewhere, or it will be lost.
+		 */
+		break;
+	}
 
 	futex_unlock(&fibril_futex);
@@ -255,6 +219,31 @@
 #endif
 
-	context_restore(&dstf->ctx);
-	/* not reached */
+	/* Swap to the next fibril. */
+	context_swap(&srcf->ctx, &dstf->ctx);
+
+	/* Restored by another fibril! */
+
+	if (srcf->clean_after_me) {
+		/*
+		 * Cleanup after the dead fibril from which we
+		 * restored context here.
+		 */
+		void *stack = srcf->clean_after_me->stack;
+		if (stack) {
+			/*
+			 * This check is necessary because a
+			 * thread could have exited like a
+			 * normal fibril using the
+			 * FIBRIL_FROM_DEAD switch type. In that
+			 * case, its fibril will not have the
+			 * stack member filled.
+			 */
+			as_area_destroy(stack);
+		}
+		fibril_teardown(srcf->clean_after_me, true);
+		srcf->clean_after_me = NULL;
+	}
+
+	return 1;
 }
 
@@ -289,8 +278,12 @@
 	fibril->arg = arg;
 
-	context_save(&fibril->ctx);
-	context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack,
-	    stack_size, fibril->tcb);
-
+	context_create_t sctx = {
+		.fn = fibril_main,
+		.stack_base = fibril->stack,
+		.stack_size = stack_size,
+		.tls = fibril->tcb,
+	};
+
+	context_create(&fibril->ctx, &sctx);
 	return (fid_t) fibril;
 }
