Index: uspace/drv/char/i8042/main.c
===================================================================
--- uspace/drv/char/i8042/main.c	(revision f570cdfc2c9877b22611b228e97f7e7201d6e74b)
+++ uspace/drv/char/i8042/main.c	(revision c170438d728300887049dbf52e95765c3106a3ae)
@@ -43,5 +43,4 @@
 #include <ddf/log.h>
 #include <stdio.h>
-#include <async.h>
 #include "i8042.h"
 
@@ -152,10 +151,4 @@
 	ddf_log_init(NAME);
 	
-	/*
-	 * Alleviate the virtual memory / page table pressure caused by
-	 * interrupt storms when the default large stacks are used.
-	 */
-	async_set_notification_handler_stack_size(PAGE_SIZE);
-
 	return ddf_driver_main(&i8042_driver);
 }
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision f570cdfc2c9877b22611b228e97f7e7201d6e74b)
+++ uspace/lib/c/generic/async.c	(revision c170438d728300887049dbf52e95765c3106a3ae)
@@ -493,15 +493,4 @@
 }
 
-static size_t notification_handler_stksz = FIBRIL_DFLT_STK_SIZE;
-
-/** Set the stack size for the notification handler notification fibrils.
- *
- * @param size Stack size in bytes.
- */
-void async_set_notification_handler_stack_size(size_t size)
-{
-	notification_handler_stksz = size;
-}
-
 /** Mutex protecting inactive_exch_list and avail_phone_cv.
  *
@@ -998,27 +987,20 @@
 }
 
-/** Notification fibril.
- *
- * When a notification arrives, a fibril with this implementing function is
- * created. It calls the corresponding notification handler and does the final
- * cleanup.
- *
- * @param arg Message structure pointer.
- *
- * @return Always zero.
- *
- */
-static int notification_fibril(void *arg)
-{
-	assert(arg);
-	
-	msg_t *msg = (msg_t *) arg;
+/** Process notification.
+ *
+ * @param callid Hash of the incoming call.
+ * @param call   Data of the incoming call.
+ */
+static void process_notification(ipc_callid_t callid, ipc_call_t *call)
+{
 	async_notification_handler_t handler = NULL;
 	void *data = NULL;
+
+	assert(call);
 	
 	futex_down(&async_futex);
 	
 	ht_link_t *link = hash_table_find(&notification_hash_table,
-	    &IPC_GET_IMETHOD(msg->call));
+	    &IPC_GET_IMETHOD(*call));
 	if (link) {
 		notification_t *notification =
@@ -1031,48 +1013,5 @@
 	
 	if (handler)
-		handler(msg->callid, &msg->call, data);
-	
-	free(msg);
-	return 0;
-}
-
-/** Process notification.
- *
- * A new fibril is created which would process the notification.
- *
- * @param callid Hash of the incoming call.
- * @param call   Data of the incoming call.
- *
- * @return False if an error occured.
- *         True if the call was passed to the notification fibril.
- *
- */
-static bool process_notification(ipc_callid_t callid, ipc_call_t *call)
-{
-	assert(call);
-	
-	futex_down(&async_futex);
-	
-	msg_t *msg = malloc(sizeof(*msg));
-	if (!msg) {
-		futex_up(&async_futex);
-		return false;
-	}
-	
-	msg->callid = callid;
-	msg->call = *call;
-	
-	fid_t fid = fibril_create_generic(notification_fibril, msg,
-	    notification_handler_stksz);
-	if (fid == 0) {
-		free(msg);
-		futex_up(&async_futex);
-		return false;
-	}
-	
-	fibril_add_ready(fid);
-	
-	futex_up(&async_futex);
-	return true;
+		handler(callid, call, data);
 }
 
@@ -1375,5 +1314,24 @@
 	/* Kernel notification */
 	if ((callid & IPC_CALLID_NOTIFICATION)) {
+		fibril_t *fibril = (fibril_t *) __tcb_get()->fibril_data;
+		unsigned oldsw = fibril->switches;
+
 		process_notification(callid, call);
+
+		if (oldsw != fibril->switches) {
+			/*
+			 * The notification handler did not execute atomically
+			 * and so the current manager fibril assumed the role of
+			 * a notification fibril. While waiting for its
+			 * resources, it switched to another manager fibril that
+			 * had already existed or it created a new one. We
+			 * therefore know there is at least yet another
+			 * manager fibril that can take over. We now kill the
+			 * current 'notification' fibril to prevent fibril
+			 * population explosion.
+			 */
+			futex_down(&async_futex);
+			fibril_switch(FIBRIL_FROM_DEAD);
+		}
 		return;
 	}
@@ -1550,5 +1508,5 @@
 void async_create_manager(void)
 {
-	fid_t fid = fibril_create(async_manager_fibril, NULL);
+	fid_t fid = fibril_create_generic(async_manager_fibril, NULL, PAGE_SIZE);
 	if (fid != 0)
 		fibril_add_manager(fid);
Index: uspace/lib/c/generic/fibril.c
===================================================================
--- uspace/lib/c/generic/fibril.c	(revision f570cdfc2c9877b22611b228e97f7e7201d6e74b)
+++ uspace/lib/c/generic/fibril.c	(revision c170438d728300887049dbf52e95765c3106a3ae)
@@ -113,4 +113,6 @@
 	
 	fibril->waits_for = NULL;
+
+	fibril->switches = 0;
 
 	/*
@@ -216,4 +218,6 @@
 			assert(stype == FIBRIL_TO_MANAGER);
 
+			srcf->switches++;
+
 			/*
 			 * Don't put the current fibril into any list, it should
Index: uspace/lib/c/generic/ipc.c
===================================================================
--- uspace/lib/c/generic/ipc.c	(revision f570cdfc2c9877b22611b228e97f7e7201d6e74b)
+++ uspace/lib/c/generic/ipc.c	(revision c170438d728300887049dbf52e95765c3106a3ae)
@@ -96,5 +96,5 @@
 }
 
-/** Prolog for ipc_call_async_*() functions.
+/** Prologue for ipc_call_async_*() functions.
  *
  * @param private  Argument for the answer/error callback.
@@ -122,5 +122,5 @@
 }
 
-/** Epilog for ipc_call_async_*() functions.
+/** Epilogue for ipc_call_async_*() functions.
  *
  * @param callid      Value returned by the SYS_IPC_CALL_ASYNC_* syscall.
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision f570cdfc2c9877b22611b228e97f7e7201d6e74b)
+++ uspace/lib/c/include/async.h	(revision c170438d728300887049dbf52e95765c3106a3ae)
@@ -165,6 +165,4 @@
 extern int async_create_callback_port(async_exch_t *, iface_t, sysarg_t,
     sysarg_t, async_port_handler_t, void *, port_id_t *);
-
-extern void async_set_notification_handler_stack_size(size_t);
 
 extern int async_irq_subscribe(int, int, async_notification_handler_t, void *,
Index: uspace/lib/c/include/fibril.h
===================================================================
--- uspace/lib/c/include/fibril.h	(revision f570cdfc2c9877b22611b228e97f7e7201d6e74b)
+++ uspace/lib/c/include/fibril.h	(revision c170438d728300887049dbf52e95765c3106a3ae)
@@ -78,4 +78,6 @@
 	
 	fibril_owner_info_t *waits_for;
+
+	unsigned switches;
 } fibril_t;
 
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision f570cdfc2c9877b22611b228e97f7e7201d6e74b)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision c170438d728300887049dbf52e95765c3106a3ae)
@@ -47,5 +47,4 @@
 #include <errno.h>
 #include <ipc/adb.h>
-#include <async.h>
 #include <assert.h>
 #include "cuda_adb.h"
@@ -158,10 +157,4 @@
 	printf(NAME ": VIA-CUDA Apple Desktop Bus driver\n");
 	
-	/*
-	 * Alleviate the virtual memory / page table pressure caused by
-	 * interrupt storms when the default large stacks are used.
-	 */
-	async_set_notification_handler_stack_size(PAGE_SIZE);
-
 	for (i = 0; i < ADB_MAX_ADDR; ++i) {
 		adb_dev[i].client_sess = NULL;
