Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/Makefile	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -65,4 +65,5 @@
 	generic/clipboard.c \
 	generic/config.c \
+	generic/context.c \
 	generic/corecfg.c \
 	generic/devman.c \
Index: uspace/lib/c/arch/abs32le/include/libarch/fibril.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/libarch/fibril.h	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/arch/abs32le/include/libarch/fibril.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -37,4 +37,5 @@
 
 #include <stdint.h>
+#include <libarch/fibril_context.h>
 
 #define SP_DELTA  0
@@ -48,16 +49,5 @@
 	} while (0)
 
-/*
- * On real hardware this stores the registers which
- * need to be preserved across function calls.
- */
-typedef struct {
-	uintptr_t sp;
-	uintptr_t fp;
-	uintptr_t pc;
-	uintptr_t tls;
-} context_t;
-
-static inline uintptr_t context_get_fp(context_t *ctx)
+static inline uintptr_t _context_get_fp(context_t *ctx)
 {
 	/* On real hardware, this function returns the frame pointer. */
Index: uspace/lib/c/arch/abs32le/include/libarch/fibril_context.h
===================================================================
--- uspace/lib/c/arch/abs32le/include/libarch/fibril_context.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
+++ uspace/lib/c/arch/abs32le/include/libarch/fibril_context.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBC_abs32le_FIBRIL_CONTEXT_H_
+#define LIBC_abs32le_FIBRIL_CONTEXT_H_
+
+#include <stdint.h>
+
+/*
+ * On real hardware this stores the registers which
+ * need to be preserved across function calls.
+ */
+typedef struct context {
+	uintptr_t sp;
+	uintptr_t fp;
+	uintptr_t pc;
+	uintptr_t tls;
+} context_t;
+
+#endif
Index: uspace/lib/c/arch/amd64/include/libarch/fibril.h
===================================================================
--- uspace/lib/c/arch/amd64/include/libarch/fibril.h	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/arch/amd64/include/libarch/fibril.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -53,5 +53,5 @@
 	} while (0)
 
-static inline uintptr_t context_get_fp(context_t *ctx)
+static inline uintptr_t _context_get_fp(context_t *ctx)
 {
 	return ctx->rbp;
Index: uspace/lib/c/arch/arm32/include/libarch/fibril.h
===================================================================
--- uspace/lib/c/arch/arm32/include/libarch/fibril.h	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/arch/arm32/include/libarch/fibril.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -67,5 +67,5 @@
 	} while (0)
 
-static inline uintptr_t context_get_fp(context_t *ctx)
+static inline uintptr_t _context_get_fp(context_t *ctx)
 {
 	return ctx->fp;
Index: uspace/lib/c/arch/ia32/include/libarch/fibril.h
===================================================================
--- uspace/lib/c/arch/ia32/include/libarch/fibril.h	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/arch/ia32/include/libarch/fibril.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -54,5 +54,5 @@
 	} while (0)
 
-static inline uintptr_t context_get_fp(context_t *ctx)
+static inline uintptr_t _context_get_fp(context_t *ctx)
 {
 	return ctx->ebp;
Index: uspace/lib/c/arch/ia64/include/libarch/fibril.h
===================================================================
--- uspace/lib/c/arch/ia64/include/libarch/fibril.h	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/arch/ia64/include/libarch/fibril.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -65,5 +65,5 @@
 	} while (0)
 
-static inline uintptr_t context_get_fp(context_t *ctx)
+static inline uintptr_t _context_get_fp(context_t *ctx)
 {
 	return 0;	/* FIXME */
Index: uspace/lib/c/arch/mips32/include/libarch/fibril.h
===================================================================
--- uspace/lib/c/arch/mips32/include/libarch/fibril.h	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/arch/mips32/include/libarch/fibril.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -57,5 +57,5 @@
 	} while (0)
 
-static inline uintptr_t context_get_fp(context_t *ctx)
+static inline uintptr_t _context_get_fp(context_t *ctx)
 {
 	return ctx->sp;
Index: uspace/lib/c/arch/ppc32/include/libarch/fibril.h
===================================================================
--- uspace/lib/c/arch/ppc32/include/libarch/fibril.h	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/arch/ppc32/include/libarch/fibril.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -54,5 +54,5 @@
 	} while (0)
 
-static inline uintptr_t context_get_fp(context_t *ctx)
+static inline uintptr_t _context_get_fp(context_t *ctx)
 {
 	return ctx->sp;
Index: uspace/lib/c/arch/riscv64/include/libarch/fibril.h
===================================================================
--- uspace/lib/c/arch/riscv64/include/libarch/fibril.h	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/arch/riscv64/include/libarch/fibril.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -59,5 +59,5 @@
 } context_t;
 
-static inline uintptr_t context_get_fp(context_t *ctx)
+static inline uintptr_t _context_get_fp(context_t *ctx)
 {
 	/* This function returns the frame pointer. */
Index: uspace/lib/c/arch/sparc64/include/libarch/fibril.h
===================================================================
--- uspace/lib/c/arch/sparc64/include/libarch/fibril.h	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/arch/sparc64/include/libarch/fibril.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -52,5 +52,5 @@
 	} while (0)
 
-static inline uintptr_t context_get_fp(context_t *ctx)
+static inline uintptr_t _context_get_fp(context_t *ctx)
 {
 	return ctx->sp + STACK_BIAS;
Index: uspace/lib/c/generic/context.c
===================================================================
--- uspace/lib/c/generic/context.c	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
+++ uspace/lib/c/generic/context.c	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2018 CZ.NIC, z.s.p.o.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <context.h>
+#include <libarch/tls.h>
+#include <libarch/fibril.h>
+#include <libarch/faddr.h>
+
+/**
+ * Saves current context to the variable pointed to by `self`,
+ * and restores the context denoted by `other`.
+ *
+ * When the `self` context is later restored by another call to
+ * `context_swap()`, the control flow behaves as if the earlier call to
+ * `context_swap()` just returned.
+ */
+void context_swap(context_t *self, context_t *other)
+{
+	if (context_save(self))
+		context_restore(other);
+}
+
+void context_create(context_t *context, const context_create_t *arg)
+{
+	context_save(context);
+	context_set(context, FADDR(arg->fn), arg->stack_base,
+	    arg->stack_size, arg->tls);
+}
+
+uintptr_t context_get_pc(context_t *ctx)
+{
+	// This is a simple wrapper for now, and exists to allow
+	// potential future implementation of context_swap to omit
+	// program counter from the context structure (e.g. if it's
+	// stored on the stack).
+	return ctx->pc;
+}
+
+uintptr_t context_get_fp(context_t *ctx)
+{
+	return _context_get_fp(ctx);
+}
Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/generic/fibril.c	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -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;
 }
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/generic/fibril_synch.c	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -73,6 +73,7 @@
 		if (oi->owned_by == f)
 			break;
-		stacktrace_print_fp_pc(context_get_fp(&oi->owned_by->ctx),
-		    oi->owned_by->ctx.pc);
+		stacktrace_print_fp_pc(
+		    context_get_fp(&oi->owned_by->ctx),
+		    context_get_pc(&oi->owned_by->ctx));
 		printf("Fibril %p waits for primitive %p.\n",
 		     oi->owned_by, oi->owned_by->waits_for);
Index: uspace/lib/c/generic/setjmp.c
===================================================================
--- uspace/lib/c/generic/setjmp.c	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/generic/setjmp.c	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -37,6 +37,10 @@
 
 #include <setjmp.h>
-#include <libarch/fibril.h>
-#include <fibril.h>
+#include <context.h>
+
+// TODO: setjmp/longjmp are basically a stronger version of
+// context_save/context_restore. It would be preferable to turn
+// those two into setjmp/longjmp (all it would need is preserving the
+// return value).
 
 /**
@@ -52,5 +56,4 @@
 	env[0].return_value = (val == 0) ? 1 : val;
 	context_restore(&env[0].context);
-	__builtin_unreachable();
 }
 
Index: uspace/lib/c/include/context.h
===================================================================
--- uspace/lib/c/include/context.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
+++ uspace/lib/c/include/context.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018 CZ.NIC, z.s.p.o.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBC_CONTEXT_H_
+#define LIBC_CONTEXT_H_
+
+#include <_bits/size_t.h>
+#include <libarch/fibril_context.h>
+
+/* Context initialization data. */
+typedef struct {
+	void (*fn)(void);
+	void *stack_base;
+	size_t stack_size;
+	void *tls;
+} context_create_t;
+
+extern void context_swap(context_t *self, context_t *other);
+extern void context_create(context_t *context, const context_create_t *arg);
+extern uintptr_t context_get_fp(context_t *ctx);
+extern uintptr_t context_get_pc(context_t *ctx);
+
+// TODO: These should go away.
+
+extern int context_save(context_t *ctx) __attribute__((returns_twice));
+extern void context_restore(context_t *ctx) __attribute__((noreturn));
+
+#endif
+
Index: uspace/lib/c/include/fibril.h
===================================================================
--- uspace/lib/c/include/fibril.h	(revision f1380b76772fb5d1aa03637b5e57bd9b929fea61)
+++ uspace/lib/c/include/fibril.h	(revision 338d54a7c4a77bbe3bf0bdff3c750bad8bb1ea9a)
@@ -36,15 +36,8 @@
 #define LIBC_FIBRIL_H_
 
-#include <libarch/fibril.h>
+#include <context.h>
 #include <types/common.h>
 #include <adt/list.h>
 #include <libarch/tls.h>
-
-#define context_set_generic(c, _pc, stack, size, ptls) \
-	do { \
-		(c)->pc = (sysarg_t) (_pc); \
-		(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \
-		(c)->tls = (sysarg_t) (ptls); \
-	} while (0)
 
 #define FIBRIL_WRITER	1
@@ -86,11 +79,6 @@
 #define fibril_local __thread
 
-extern int context_save(context_t *ctx) __attribute__((returns_twice));
-extern void context_restore(context_t *ctx) __attribute__((noreturn));
-
 #define FIBRIL_DFLT_STK_SIZE	0
 
-#define fibril_create(func, arg) \
-	fibril_create_generic((func), (arg), FIBRIL_DFLT_STK_SIZE)
 extern fid_t fibril_create_generic(errno_t (*func)(void *), void *arg, size_t);
 extern void fibril_destroy(fid_t fid);
@@ -103,4 +91,9 @@
 extern fid_t fibril_get_id(void);
 
+static inline fid_t fibril_create(errno_t (*func)(void *), void *arg)
+{
+	return fibril_create_generic(func, arg, FIBRIL_DFLT_STK_SIZE);
+}
+
 static inline int fibril_yield(void)
 {
