Index: kernel/arch/abs32le/src/proc/thread.c
===================================================================
--- kernel/arch/abs32le/src/proc/thread.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/arch/abs32le/src/proc/thread.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -35,7 +35,6 @@
 #include <proc/thread.h>
 
-errno_t thread_create_arch(thread_t *t, thread_flags_t flags)
+void thread_create_arch(thread_t *t)
 {
-	return EOK;
 }
 
Index: kernel/arch/amd64/src/proc/thread.c
===================================================================
--- kernel/arch/amd64/src/proc/thread.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/arch/amd64/src/proc/thread.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -42,5 +42,5 @@
  *
  */
-errno_t thread_create_arch(thread_t *thread, thread_flags_t flags)
+void thread_create_arch(thread_t *thread)
 {
 	/*
@@ -49,5 +49,4 @@
 	thread->arch.kstack_rsp =
 	    (uintptr_t) &thread->kstack[PAGE_SIZE - sizeof(istate_t)];
-	return EOK;
 }
 
Index: kernel/arch/arm32/include/arch/proc/thread.h
===================================================================
--- kernel/arch/arm32/include/arch/proc/thread.h	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/arch/arm32/include/arch/proc/thread.h	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -42,5 +42,5 @@
 #define thr_constructor_arch(t)
 #define thr_destructor_arch(t)
-#define thread_create_arch(t, flags) (EOK)
+#define thread_create_arch(t)
 
 #endif
Index: kernel/arch/ia32/src/proc/thread.c
===================================================================
--- kernel/arch/ia32/src/proc/thread.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/arch/ia32/src/proc/thread.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -39,7 +39,6 @@
  * @param t Thread to be initialized.
  */
-errno_t thread_create_arch(thread_t *t, thread_flags_t flags)
+void thread_create_arch(thread_t *t)
 {
-	return EOK;
 }
 
Index: kernel/arch/ia64/include/arch/proc/thread.h
===================================================================
--- kernel/arch/ia64/include/arch/proc/thread.h	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/arch/ia64/include/arch/proc/thread.h	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -41,5 +41,5 @@
 #define thr_constructor_arch(t)
 #define thr_destructor_arch(t)
-#define thread_create_arch(t, flags) (EOK)
+#define thread_create_arch(t)
 
 #endif
Index: kernel/arch/mips32/include/arch/proc/thread.h
===================================================================
--- kernel/arch/mips32/include/arch/proc/thread.h	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/arch/mips32/include/arch/proc/thread.h	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -41,5 +41,5 @@
 #define thr_constructor_arch(t)
 #define thr_destructor_arch(t)
-#define thread_create_arch(t, flags) (EOK)
+#define thread_create_arch(t)
 
 #endif
Index: kernel/arch/ppc32/include/arch/proc/thread.h
===================================================================
--- kernel/arch/ppc32/include/arch/proc/thread.h	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/arch/ppc32/include/arch/proc/thread.h	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -41,5 +41,5 @@
 #define thr_constructor_arch(t)
 #define thr_destructor_arch(t)
-#define thread_create_arch(t, flags) (EOK)
+#define thread_create_arch(t)
 
 #endif
Index: kernel/arch/riscv64/src/proc/thread.c
===================================================================
--- kernel/arch/riscv64/src/proc/thread.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/arch/riscv64/src/proc/thread.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -35,7 +35,6 @@
 #include <proc/thread.h>
 
-errno_t thread_create_arch(thread_t *t, thread_flags_t flags)
+void thread_create_arch(thread_t *t)
 {
-	return EOK;
 }
 
Index: kernel/arch/sparc64/src/proc/thread.c
===================================================================
--- kernel/arch/sparc64/src/proc/thread.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/arch/sparc64/src/proc/thread.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -62,14 +62,12 @@
 }
 
-errno_t thread_create_arch(thread_t *t, thread_flags_t flags)
+void thread_create_arch(thread_t *t)
 {
-	if ((flags & THREAD_FLAG_USPACE) && (!t->arch.uspace_window_buffer)) {
+	if ((t->uspace) && (!t->arch.uspace_window_buffer)) {
 		/*
 		 * The thread needs userspace window buffer and the object
 		 * returned from the slab allocator doesn't have any.
 		 */
-		t->arch.uspace_window_buffer = slab_alloc(uwb_cache, FRAME_ATOMIC);
-		if (!t->arch.uspace_window_buffer)
-			return ENOMEM;
+		t->arch.uspace_window_buffer = slab_alloc(uwb_cache, 0);
 	} else {
 		uintptr_t uw_buf = (uintptr_t) t->arch.uspace_window_buffer;
@@ -82,5 +80,4 @@
 		    UWB_ALIGNMENT);
 	}
-	return EOK;
 }
 
Index: kernel/genarch/src/mm/asid_fifo.c
===================================================================
--- kernel/genarch/src/mm/asid_fifo.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/genarch/src/mm/asid_fifo.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -65,10 +65,4 @@
 #if (!FIFO_STATIC)
 	fifo_create(free_asids);
-	if (!free_asids.fifo)
-		panic("Not enough memory to allocate ASID FIFO");
-	// TODO: There really is no reason not to statically allocate it
-	//       except to keep binary size low. Once kernel is a regular ELF
-	//       binary supporting .bss section (wip as of the late 2018),
-	//       the dynamic option should be removed.
 #endif
 
Index: kernel/genarch/src/ofw/ofw_tree.c
===================================================================
--- kernel/genarch/src/ofw/ofw_tree.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/genarch/src/ofw/ofw_tree.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -386,7 +386,5 @@
 static void ofw_tree_node_sysinfo(ofw_tree_node_t *node, const char *path)
 {
-	char *cur_path = malloc(PATH_MAX_LEN);
-	if (!cur_path)
-		panic("Not enough memory to process OFW tree.");
+	char *cur_path = (char *) nfmalloc(PATH_MAX_LEN);
 
 	for (ofw_tree_node_t *cur = node; cur; cur = cur->peer) {
Index: kernel/generic/include/adt/fifo.h
===================================================================
--- kernel/generic/include/adt/fifo.h	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/include/adt/fifo.h	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -115,5 +115,5 @@
  */
 #define fifo_create(name) \
-	name.fifo = malloc(sizeof(*name.fifo) * name.items)
+	name.fifo = nfmalloc(sizeof(*name.fifo) * name.items)
 
 #endif
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/include/ipc/ipc.h	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -47,5 +47,4 @@
 struct answerbox;
 struct task;
-struct call;
 
 typedef enum {
@@ -68,6 +67,4 @@
 	struct task *caller;
 	struct answerbox *callee;
-	/* A call prepared for hangup ahead of time, so that it cannot fail. */
-	struct call *hangup_call;
 	ipc_phone_state_t state;
 	atomic_t active_calls;
@@ -174,5 +171,8 @@
 extern void ipc_init(void);
 
-extern call_t *ipc_call_alloc(void);
+extern call_t *ipc_call_alloc(unsigned int);
+extern void ipc_call_free(call_t *);
+extern void ipc_call_hold(call_t *);
+extern void ipc_call_release(call_t *);
 
 extern errno_t ipc_call_sync(phone_t *, call_t *);
Index: kernel/generic/include/mm/as.h
===================================================================
--- kernel/generic/include/mm/as.h	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/include/mm/as.h	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -325,5 +325,5 @@
 
 /* Introspection functions. */
-extern as_area_info_t *as_get_area_info(as_t *, size_t *);
+extern void as_get_area_info(as_t *, as_area_info_t **, size_t *);
 extern void as_print(as_t *);
 
Index: kernel/generic/include/mm/slab.h
===================================================================
--- kernel/generic/include/mm/slab.h	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/include/mm/slab.h	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -146,4 +146,7 @@
 extern void free(void *);
 
+extern void *nfmalloc(size_t)
+    __attribute__((malloc, returns_nonnull));
+
 #endif
 
Index: kernel/generic/include/proc/thread.h
===================================================================
--- kernel/generic/include/proc/thread.h	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/include/proc/thread.h	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -225,5 +225,5 @@
 
 #ifndef thread_create_arch
-extern errno_t thread_create_arch(thread_t *, thread_flags_t);
+extern void thread_create_arch(thread_t *);
 #endif
 
Index: kernel/generic/src/console/kconsole.c
===================================================================
--- kernel/generic/src/console/kconsole.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/console/kconsole.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -219,14 +219,8 @@
 	const char *hint;
 	const char *help;
+	char *output = nfmalloc(MAX_CMDLINE);
 	size_t hints_to_show = MAX_TAB_HINTS - 1;
 	size_t total_hints_shown = 0;
 	bool continue_showing_hints = true;
-
-	char *output = malloc(MAX_CMDLINE);
-	if (!output) {
-		// TODO: fix the function so that it does not need allocation
-		printf("Can't complete command, out of memory.\n");
-		return 0;
-	}
 
 	output[0] = 0;
@@ -331,6 +325,5 @@
 }
 
-NO_TRACE static wchar_t *clever_readline(const char *prompt, indev_t *indev,
-    char *tmp)
+NO_TRACE static wchar_t *clever_readline(const char *prompt, indev_t *indev)
 {
 	printf("%s> ", prompt);
@@ -339,4 +332,5 @@
 	wchar_t *current = history[history_pos];
 	current[0] = 0;
+	char *tmp = nfmalloc(STR_BOUNDS(MAX_CMDLINE));
 
 	while (true) {
@@ -540,4 +534,5 @@
 	}
 
+	free(tmp);
 	return current;
 }
@@ -814,16 +809,7 @@
 		printf("Type \"exit\" to leave the console.\n");
 
-	char *buffer = malloc(STR_BOUNDS(MAX_CMDLINE));
-	char *cmdline = malloc(STR_BOUNDS(MAX_CMDLINE));
-	if (!buffer || !cmdline) {
-		// TODO: fix the function so that it does not need allocations
-		printf("Can't start console, out of memory.\n");
-		free(buffer);
-		free(cmdline);
-		return;
-	}
-
+	char *cmdline = nfmalloc(STR_BOUNDS(MAX_CMDLINE));
 	while (true) {
-		wchar_t *tmp = clever_readline((char *) prompt, stdin, buffer);
+		wchar_t *tmp = clever_readline((char *) prompt, stdin);
 		size_t len = wstr_length(tmp);
 		if (!len)
@@ -841,5 +827,4 @@
 		(void) cmd_info->func(cmd_info->argv);
 	}
-	free(buffer);
 	free(cmdline);
 }
Index: kernel/generic/src/ipc/event.c
===================================================================
--- kernel/generic/src/ipc/event.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/ipc/event.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -147,5 +147,5 @@
 	if (event->answerbox != NULL) {
 		if (!event->masked) {
-			call_t *call = ipc_call_alloc();
+			call_t *call = ipc_call_alloc(FRAME_ATOMIC);
 
 			if (call) {
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/ipc/ipc.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -108,16 +108,22 @@
  * TASK->answerbox.
  *
- * @return Initialized kernel call structure with one reference, or NULL.
- *
- */
-call_t *ipc_call_alloc(void)
-{
-	// TODO: Allocate call and kobject in single allocation
-
-	call_t *call = slab_alloc(call_cache, FRAME_ATOMIC);
+ * @param flags Parameters for slab_alloc (e.g FRAME_ATOMIC).
+ *
+ * @return If flags permit it, return NULL, or initialized kernel
+ *         call structure with one reference.
+ *
+ */
+call_t *ipc_call_alloc(unsigned int flags)
+{
+	call_t *call = slab_alloc(call_cache, flags);
 	if (!call)
 		return NULL;
 
-	kobject_t *kobj = (kobject_t *) malloc(sizeof(kobject_t));
+	kobject_t *kobj;
+	if (flags & FRAME_ATOMIC)
+		kobj = (kobject_t *) malloc(sizeof(kobject_t));
+	else
+		kobj = (kobject_t *) nfmalloc(sizeof(kobject_t));
+
 	if (!kobj) {
 		slab_free(call_cache, call);
@@ -213,8 +219,5 @@
 errno_t ipc_call_sync(phone_t *phone, call_t *request)
 {
-	answerbox_t *mybox = slab_alloc(answerbox_cache, FRAME_ATOMIC);
-	if (!mybox)
-		return ENOMEM;
-
+	answerbox_t *mybox = slab_alloc(answerbox_cache, 0);
 	ipc_answerbox_init(mybox, TASK);
 
@@ -480,8 +483,5 @@
 		kobject_put(phone->kobject);
 
-		call_t *call = phone->hangup_call;
-		phone->hangup_call = NULL;
-		assert(call);
-
+		call_t *call = ipc_call_alloc(0);
 		IPC_SET_IMETHOD(call->data, IPC_M_PHONE_HUNGUP);
 		call->request_method = IPC_M_PHONE_HUNGUP;
@@ -685,8 +685,5 @@
 			 * to exist as soon as we release it.
 			 */
-			call_t *call = phone->hangup_call;
-			phone->hangup_call = NULL;
-			assert(call);
-
+			call_t *call = ipc_call_alloc(0);
 			IPC_SET_IMETHOD(call->data, IPC_M_PHONE_HUNGUP);
 			call->request_method = IPC_M_PHONE_HUNGUP;
Index: kernel/generic/src/ipc/ipcrsc.c
===================================================================
--- kernel/generic/src/ipc/ipcrsc.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/ipc/ipcrsc.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -46,6 +46,4 @@
 {
 	phone_t *phone = (phone_t *) arg;
-	if (phone->hangup_call)
-		kobject_put(phone->hangup_call->kobject);
 	slab_free(phone_cache, phone);
 }
@@ -81,15 +79,7 @@
 			return ENOMEM;
 		}
-		call_t *hcall = ipc_call_alloc();
-		if (!hcall) {
-			cap_free(TASK, handle);
-			slab_free(phone_cache, phone);
-			free(kobj);
-			return ENOMEM;
-		}
 
 		ipc_phone_init(phone, task);
 		phone->state = IPC_PHONE_CONNECTING;
-		phone->hangup_call = hcall;
 
 		kobject_initialize(kobj, KOBJECT_TYPE_PHONE, phone,
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/ipc/irq.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -529,5 +529,5 @@
 
 	if (irq->notif_cfg.answerbox) {
-		call_t *call = ipc_call_alloc();
+		call_t *call = ipc_call_alloc(FRAME_ATOMIC);
 		if (!call)
 			return;
@@ -565,5 +565,5 @@
 
 	if (irq->notif_cfg.answerbox) {
-		call_t *call = ipc_call_alloc();
+		call_t *call = ipc_call_alloc(FRAME_ATOMIC);
 		if (!call) {
 			irq_spinlock_unlock(&irq->lock, true);
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/ipc/sysipc.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -267,5 +267,4 @@
  * @return EOK on success.
  * @return ENOENT if there is no such phone handle.
- * @return ENOMEM if not enough memory to make the call
  *
  */
@@ -277,10 +276,5 @@
 		return ENOENT;
 
-	call_t *call = ipc_call_alloc();
-	if (!call) {
-		kobject_put(kobj);
-		return ENOMEM;
-	}
-
+	call_t *call = ipc_call_alloc(0);
 	call->priv = priv;
 	memcpy(call->data.args, data->args, sizeof(data->args));
@@ -379,10 +373,5 @@
 	}
 
-	call_t *call = ipc_call_alloc();
-	if (!call) {
-		kobject_put(kobj);
-		return ENOMEM;
-	}
-
+	call_t *call = ipc_call_alloc(0);
 	IPC_SET_IMETHOD(call->data, imethod);
 	IPC_SET_ARG1(call->data, arg1);
@@ -431,10 +420,5 @@
 	}
 
-	call_t *call = ipc_call_alloc();
-	if (!call) {
-		kobject_put(kobj);
-		return ENOMEM;
-	}
-
+	call_t *call = ipc_call_alloc(0);
 	errno_t rc = copy_from_uspace(&call->data.args, &data->args,
 	    sizeof(call->data.args));
Index: kernel/generic/src/lib/str.c
===================================================================
--- kernel/generic/src/lib/str.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/lib/str.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -635,7 +635,6 @@
 {
 	size_t size = str_size(src) + 1;
-	char *dest = malloc(size);
-	if (!dest)
-		return NULL;
+	char *dest = nfmalloc(size);
+	assert(dest);
 
 	str_cpy(dest, size, src);
@@ -669,7 +668,6 @@
 		size = n;
 
-	char *dest = malloc(size + 1);
-	if (!dest)
-		return NULL;
+	char *dest = nfmalloc(size + 1);
+	assert(dest);
 
 	str_ncpy(dest, size + 1, src, size);
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/main/kinit.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -120,9 +120,10 @@
 		thread = thread_create(kmp, NULL, TASK,
 		    THREAD_FLAG_UNCOUNTED, "kmp");
-		if (!thread)
+		if (thread != NULL) {
+			thread_wire(thread, &cpus[0]);
+			thread_ready(thread);
+		} else
 			panic("Unable to create kmp thread.");
 
-		thread_wire(thread, &cpus[0]);
-		thread_ready(thread);
 		thread_join(thread);
 		thread_detach(thread);
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/mm/as.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -151,8 +151,5 @@
 as_t *as_create(unsigned int flags)
 {
-	as_t *as = (as_t *) slab_alloc(as_cache, FRAME_ATOMIC);
-	if (!as)
-		return NULL;
-
+	as_t *as = (as_t *) slab_alloc(as_cache, 0);
 	(void) as_create_arch(as, 0);
 
@@ -2240,5 +2237,5 @@
  *
  */
-as_area_info_t *as_get_area_info(as_t *as, size_t *osize)
+void as_get_area_info(as_t *as, as_area_info_t **obuf, size_t *osize)
 {
 	mutex_lock(&as->lock);
@@ -2248,9 +2245,5 @@
 
 	size_t isize = area_cnt * sizeof(as_area_info_t);
-	as_area_info_t *info = malloc(isize);
-	if (!info) {
-		mutex_unlock(&as->lock);
-		return NULL;
-	}
+	as_area_info_t *info = nfmalloc(isize);
 
 	/* Record area data. */
@@ -2274,6 +2267,6 @@
 	mutex_unlock(&as->lock);
 
+	*obuf = info;
 	*osize = isize;
-	return info;
 }
 
Index: kernel/generic/src/mm/slab.c
===================================================================
--- kernel/generic/src/mm/slab.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/mm/slab.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -667,8 +667,5 @@
     size_t (*destructor)(void *obj), unsigned int flags)
 {
-	slab_cache_t *cache = slab_alloc(&slab_cache_cache, FRAME_ATOMIC);
-	if (!cache)
-		panic("Not enough memory to allocate slab cache %s.", name);
-
+	slab_cache_t *cache = slab_alloc(&slab_cache_cache, 0);
 	_slab_cache_create(cache, name, size, align, constructor, destructor,
 	    flags);
@@ -733,7 +730,4 @@
 NO_TRACE static void _slab_free(slab_cache_t *cache, void *obj, slab_t *slab)
 {
-	if (!obj)
-		return;
-
 	ipl_t ipl = interrupts_disable();
 
@@ -960,5 +954,5 @@
 }
 
-void *malloc(size_t size)
+static void *_malloc(size_t size, unsigned int flags)
 {
 	assert(_slab_initialized);
@@ -970,8 +964,21 @@
 	uint8_t idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
 
-	return slab_alloc(malloc_caches[idx], FRAME_ATOMIC);
-}
-
-void *realloc(void *ptr, size_t size)
+	return slab_alloc(malloc_caches[idx], flags);
+}
+
+void *malloc(size_t size)
+{
+	return _malloc(size, FRAME_ATOMIC);
+}
+
+/** Non-failing malloc.
+ *  Never returns NULL, but may block forever if no memory is available.
+ */
+void *nfmalloc(size_t size)
+{
+	return _malloc(size, 0);
+}
+
+static void *_realloc(void *ptr, size_t size, unsigned int flags)
 {
 	assert(_slab_initialized);
@@ -985,5 +992,5 @@
 		uint8_t idx = fnzb(size - 1) - SLAB_MIN_MALLOC_W + 1;
 
-		new_ptr = slab_alloc(malloc_caches[idx], FRAME_ATOMIC);
+		new_ptr = slab_alloc(malloc_caches[idx], flags);
 	} else
 		new_ptr = NULL;
@@ -1000,4 +1007,9 @@
 }
 
+void *realloc(void *ptr, size_t size)
+{
+	return _realloc(ptr, size, FRAME_ATOMIC);
+}
+
 void free(void *ptr)
 {
Index: kernel/generic/src/proc/scheduler.c
===================================================================
--- kernel/generic/src/proc/scheduler.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/proc/scheduler.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -134,4 +134,5 @@
 void scheduler_fpu_lazy_request(void)
 {
+restart:
 	fpu_enable();
 	irq_spinlock_lock(&CPU->lock, false);
@@ -152,4 +153,15 @@
 		fpu_context_restore(THREAD->saved_fpu_context);
 	} else {
+		/* Allocate FPU context */
+		if (!THREAD->saved_fpu_context) {
+			/* Might sleep */
+			irq_spinlock_unlock(&THREAD->lock, false);
+			irq_spinlock_unlock(&CPU->lock, false);
+			THREAD->saved_fpu_context =
+			    (fpu_context_t *) slab_alloc(fpu_context_cache, 0);
+
+			/* We may have switched CPUs during slab_alloc */
+			goto restart;
+		}
 		fpu_init();
 		THREAD->fpu_context_exists = true;
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/proc/task.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -199,7 +199,8 @@
 task_t *task_create(as_t *as, const char *name)
 {
-	task_t *task = (task_t *) slab_alloc(task_cache, FRAME_ATOMIC);
-	if (!task)
+	task_t *task = (task_t *) slab_alloc(task_cache, 0);
+	if (task == NULL) {
 		return NULL;
+	}
 
 	task_create_arch(task);
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/proc/thread.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -165,8 +165,11 @@
 
 #ifdef CONFIG_FPU
-	thread->saved_fpu_context = slab_alloc(fpu_context_cache,
-	    FRAME_ATOMIC | kmflags);
+#ifdef CONFIG_FPU_LAZY
+	thread->saved_fpu_context = NULL;
+#else /* CONFIG_FPU_LAZY */
+	thread->saved_fpu_context = slab_alloc(fpu_context_cache, kmflags);
 	if (!thread->saved_fpu_context)
 		return ENOMEM;
+#endif /* CONFIG_FPU_LAZY */
 #endif /* CONFIG_FPU */
 
@@ -197,6 +200,6 @@
 	if (!stack_phys) {
 #ifdef CONFIG_FPU
-		assert(thread->saved_fpu_context);
-		slab_free(fpu_context_cache, thread->saved_fpu_context);
+		if (thread->saved_fpu_context)
+			slab_free(fpu_context_cache, thread->saved_fpu_context);
 #endif
 		return ENOMEM;
@@ -223,6 +226,6 @@
 
 #ifdef CONFIG_FPU
-	assert(thread->saved_fpu_context);
-	slab_free(fpu_context_cache, thread->saved_fpu_context);
+	if (thread->saved_fpu_context)
+		slab_free(fpu_context_cache, thread->saved_fpu_context);
 #endif
 
@@ -339,12 +342,7 @@
     thread_flags_t flags, const char *name)
 {
-	thread_t *thread = (thread_t *) slab_alloc(thread_cache, FRAME_ATOMIC);
+	thread_t *thread = (thread_t *) slab_alloc(thread_cache, 0);
 	if (!thread)
 		return NULL;
-
-	if (thread_create_arch(thread, flags) != EOK) {
-		slab_free(thread_cache, thread);
-		return NULL;
-	}
 
 	/* Not needed, but good for debugging */
@@ -409,4 +407,7 @@
 	udebug_thread_initialize(&thread->udebug);
 #endif
+
+	/* Might depend on previous initialization */
+	thread_create_arch(thread);
 
 	if ((flags & THREAD_FLAG_NOATTACH) != THREAD_FLAG_NOATTACH)
@@ -653,8 +654,4 @@
 
 	return waitq_sleep_timeout(&thread->join_wq, usec, flags, NULL);
-
-	// FIXME: join should deallocate the thread.
-	//        Current code calls detach after join, that's contrary to how
-	//        join is used in other threading APIs.
 }
 
Index: kernel/generic/src/sysinfo/sysinfo.c
===================================================================
--- kernel/generic/src/sysinfo/sysinfo.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/sysinfo/sysinfo.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -204,25 +204,16 @@
 
 		*psubtree =
-		    (sysinfo_item_t *) slab_alloc(sysinfo_item_cache, FRAME_ATOMIC);
-		if (!*psubtree)
-			return NULL;
+		    (sysinfo_item_t *) slab_alloc(sysinfo_item_cache, 0);
+		assert(*psubtree);
 
 		/* Fill in item name up to the delimiter */
 		(*psubtree)->name = str_ndup(name, i);
-		if (!(*psubtree)->name) {
-			slab_free(sysinfo_item_cache, *psubtree);
-			return NULL;
-		}
+		assert((*psubtree)->name);
 
 		/* Create subtree items */
 		if (name[i] == '.') {
 			(*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE;
-			sysinfo_item_t *item = sysinfo_create_path(name + i + 1,
+			return sysinfo_create_path(name + i + 1,
 			    &((*psubtree)->subtree.table));
-			if (!item) {
-				free((*psubtree)->name);
-				slab_free(sysinfo_item_cache, *psubtree);
-			}
-			return item;
 		}
 
@@ -280,7 +271,6 @@
 
 			sysinfo_item_t *item =
-			    (sysinfo_item_t *) slab_alloc(sysinfo_item_cache, FRAME_ATOMIC);
-			if (!item)
-				return NULL;
+			    (sysinfo_item_t *) slab_alloc(sysinfo_item_cache, 0);
+			assert(item);
 
 			cur->next = item;
@@ -288,20 +278,11 @@
 			/* Fill in item name up to the delimiter */
 			item->name = str_ndup(name, i);
-			if (!item->name) {
-				slab_free(sysinfo_item_cache, item);
-				return NULL;
-			}
+			assert(item->name);
 
 			/* Create subtree items */
 			if (name[i] == '.') {
 				item->subtree_type = SYSINFO_SUBTREE_TABLE;
-				sysinfo_item_t *sub = sysinfo_create_path(
-				    name + i + 1, &(item->subtree.table));
-				if (!sub) {
-					free(item->name);
-					slab_free(sysinfo_item_cache, item);
-					return NULL;
-				}
-				return sub;
+				return sysinfo_create_path(name + i + 1,
+				    &(item->subtree.table));
 			}
 
@@ -337,6 +318,4 @@
 		item->val_type = SYSINFO_VAL_VAL;
 		item->val.val = val;
-	} else {
-		printf("Could not set sysinfo item %s.\n", name);
 	}
 
@@ -371,6 +350,4 @@
 		item->val.data.data = data;
 		item->val.data.size = size;
-	} else {
-		printf("Could not set sysinfo item %s.\n", name);
 	}
 
@@ -401,6 +378,4 @@
 		item->val.gen_val.fn = fn;
 		item->val.gen_val.data = data;
-	} else {
-		printf("Could not set sysinfo item %s.\n", name);
 	}
 
@@ -436,6 +411,4 @@
 		item->val.gen_data.fn = fn;
 		item->val.gen_data.data = data;
-	} else {
-		printf("Could not set sysinfo item %s.\n", name);
 	}
 
@@ -461,6 +434,4 @@
 	if (item != NULL)
 		item->val_type = SYSINFO_VAL_UNDEFINED;
-	else
-		printf("Could not set sysinfo item %s.\n", name);
 
 	mutex_unlock(&sysinfo_lock);
@@ -495,6 +466,4 @@
 		item->subtree.generator.fn = fn;
 		item->subtree.generator.data = data;
-	} else {
-		printf("Could not set sysinfo item %s.\n", name);
 	}
 
@@ -685,8 +654,6 @@
 		return ret;
 
-	// TODO: Change this so that allocation is not needed.
-	char *path = malloc(size + 1);
-	if (!path)
-		return ret;
+	char *path = (char *) nfmalloc(size + 1);
+	assert(path);
 
 	if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
@@ -796,8 +763,6 @@
 		return ret;
 
-	// TODO: Change this so that allocation is not needed.
-	char *path = malloc(size + 1);
-	if (!path)
-		return ret;
+	char *path = (char *) nfmalloc(size + 1);
+	assert(path);
 
 	if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
Index: kernel/generic/src/udebug/udebug_ipc.c
===================================================================
--- kernel/generic/src/udebug/udebug_ipc.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/generic/src/udebug/udebug_ipc.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -266,5 +266,5 @@
 	size_t data_size;
 	size_t buf_size;
-	as_area_info_t *data;
+	void *data;
 
 	uspace_addr = IPC_GET_ARG2(call->data);	/* Destination address */
@@ -274,10 +274,5 @@
 	 * Read area list.
 	 */
-	data = as_get_area_info(AS, &data_size);
-	if (!data) {
-		IPC_SET_RETVAL(call->data, ENOMEM);
-		ipc_answer(&TASK->kb.box, call);
-		return;
-	}
+	as_get_area_info(AS, (as_area_info_t **) &data, &data_size);
 
 	/* Copy MAX(buf_size, data_size) bytes */
@@ -302,5 +297,5 @@
 
 	IPC_SET_ARG3(call->data, data_size);
-	call->buffer = (uint8_t *) data;
+	call->buffer = data;
 
 	ipc_answer(&TASK->kb.box, call);
Index: kernel/test/mm/slab1.c
===================================================================
--- kernel/test/mm/slab1.c	(revision 436a0a5d2cce1b5f7720cb379a4bd818e1599d4d)
+++ kernel/test/mm/slab1.c	(revision 88e43bc385a97c7449a8a8bdd10a598a9497c134)
@@ -50,7 +50,6 @@
 
 	for (i = 0; i < count; i++) {
-		data[i] = slab_alloc(cache, FRAME_ATOMIC);
-		if (data[i])
-			memsetb(data[i], size, 0);
+		data[i] = slab_alloc(cache, 0);
+		memsetb(data[i], size, 0);
 	}
 
@@ -67,7 +66,6 @@
 
 	for (i = 0; i < count; i++) {
-		data[i] = slab_alloc(cache, FRAME_ATOMIC);
-		if (data[i])
-			memsetb(data[i], size, 0);
+		data[i] = slab_alloc(cache, 0);
+		memsetb(data[i], size, 0);
 	}
 
@@ -84,7 +82,6 @@
 
 	for (i = count / 2; i < count; i++) {
-		data[i] = slab_alloc(cache, FRAME_ATOMIC);
-		if (data[i])
-			memsetb(data[i], size, 0);
+		data[i] = slab_alloc(cache, 0);
+		memsetb(data[i], size, 0);
 	}
 
@@ -134,9 +131,9 @@
 	for (j = 0; j < 10; j++) {
 		for (i = 0; i < THR_MEM_COUNT; i++)
-			thr_data[offs][i] = slab_alloc(thr_cache, FRAME_ATOMIC);
+			thr_data[offs][i] = slab_alloc(thr_cache, 0);
 		for (i = 0; i < THR_MEM_COUNT / 2; i++)
 			slab_free(thr_cache, thr_data[offs][i]);
 		for (i = 0; i < THR_MEM_COUNT / 2; i++)
-			thr_data[offs][i] = slab_alloc(thr_cache, FRAME_ATOMIC);
+			thr_data[offs][i] = slab_alloc(thr_cache, 0);
 		for (i = 0; i < THR_MEM_COUNT; i++)
 			slab_free(thr_cache, thr_data[offs][i]);
