Index: kernel/generic/include/ipc/event.h
===================================================================
--- kernel/generic/include/ipc/event.h	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ kernel/generic/include/ipc/event.h	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -51,32 +51,26 @@
 	/** Counter. */
 	size_t counter;
-	/** Masked flag. */
-	bool masked;
-	/** Unmask callback. */
-	void (*unmask_cb)(void);
 } event_t;
 
 extern void event_init(void);
+extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
+extern bool event_is_subscribed(event_type_t);
 extern void event_cleanup_answerbox(answerbox_t *);
-extern void event_set_unmask_callback(event_type_t, void (*)(void));
 
-#define event_notify_0(e, m) \
-	event_notify((e), (m), 0, 0, 0, 0, 0)
-#define event_notify_1(e, m, a1) \
-	event_notify((e), (m), (a1), 0, 0, 0, 0)
-#define event_notify_2(e, m, a1, a2) \
-	event_notify((e), (m), (a1), (a2), 0, 0, 0)
-#define event_notify_3(e, m, a1, a2, a3) \
-	event_notify((e), (m), (a1), (a2), (a3), 0, 0)
-#define event_notify_4(e, m, a1, a2, a3, a4) \
-	event_notify((e), (m), (a1), (a2), (a3), (a4), 0)
-#define event_notify_5(e, m, a1, a2, a3, a4, a5) \
-	event_notify((e), (m), (a1), (a2), (a3), (a4), (a5))
+#define event_notify_0(e) \
+	event_notify((e), 0, 0, 0, 0, 0)
+#define event_notify_1(e, a1) \
+	event_notify((e), (a1), 0, 0, 0, 0)
+#define event_notify_2(e, a1, a2) \
+	event_notify((e), (a1), (a2), 0, 0, 0)
+#define event_notify_3(e, a1, a2, a3) \
+	event_notify((e), (a1), (a2), (a3), 0, 0)
+#define event_notify_4(e, a1, a2, a3, a4) \
+	event_notify((e), (a1), (a2), (a3), (a4), 0)
+#define event_notify_5(e, a1, a2, a3, a4, a5) \
+	event_notify((e), (a1), (a2), (a3), (a4), (a5))
 
-extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,
+extern void event_notify(event_type_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t);
-
-extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
-extern sysarg_t sys_event_unmask(sysarg_t);
 
 #endif
Index: kernel/generic/include/ipc/event_types.h
===================================================================
--- kernel/generic/include/ipc/event_types.h	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ kernel/generic/include/ipc/event_types.h	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -39,5 +39,5 @@
 	/** New data available in kernel log */
 	EVENT_KLOG = 0,
-	/** Returning from kernel console to uspace */
+	/** Returning from kernel console to userspace */
 	EVENT_KCONSOLE,
 	/** A task/thread has faulted and will be terminated */
Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ kernel/generic/include/syscall/syscall.h	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -75,5 +75,4 @@
 	
 	SYS_EVENT_SUBSCRIBE,
-	SYS_EVENT_UNMASK,
 	
 	SYS_CAP_GRANT,
Index: kernel/generic/src/console/cmd.c
===================================================================
--- kernel/generic/src/console/cmd.c	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ kernel/generic/src/console/cmd.c	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -1107,5 +1107,5 @@
 	release_console();
 	
-	event_notify_0(EVENT_KCONSOLE, false);
+	event_notify_0(EVENT_KCONSOLE);
 	indev_pop_character(stdin);
 	
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ kernel/generic/src/console/console.c	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -53,5 +53,5 @@
 #include <str.h>
 
-#define KLOG_PAGES    8
+#define KLOG_PAGES    4
 #define KLOG_LENGTH   (KLOG_PAGES * PAGE_SIZE / sizeof(wchar_t))
 #define KLOG_LATENCY  8
@@ -165,6 +165,4 @@
 	sysinfo_set_item_val("klog.faddr", NULL, (sysarg_t) faddr);
 	sysinfo_set_item_val("klog.pages", NULL, KLOG_PAGES);
-
-	event_set_unmask_callback(EVENT_KLOG, klog_update);
 	
 	spinlock_lock(&klog_lock);
@@ -267,8 +265,7 @@
 	spinlock_lock(&klog_lock);
 	
-	if ((klog_inited) && (klog_uspace > 0)) {
-		if (event_notify_3(EVENT_KLOG, true, klog_start, klog_len,
-		    klog_uspace) == EOK)
-			klog_uspace = 0;
+	if ((klog_inited) && (event_is_subscribed(EVENT_KLOG)) && (klog_uspace > 0)) {
+		event_notify_3(EVENT_KLOG, klog_start, klog_len, klog_uspace);
+		klog_uspace = 0;
 	}
 	
Index: kernel/generic/src/ipc/event.c
===================================================================
--- kernel/generic/src/ipc/event.c	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ kernel/generic/src/ipc/event.c	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -48,136 +48,22 @@
 static event_t events[EVENT_END];
 
-/** Initialize kernel events.
- *
- */
+/** Initialize kernel events. */
 void event_init(void)
 {
-	for (unsigned int i = 0; i < EVENT_END; i++) {
+	unsigned int i;
+	
+	for (i = 0; i < EVENT_END; i++) {
 		spinlock_initialize(&events[i].lock, "event.lock");
 		events[i].answerbox = NULL;
 		events[i].counter = 0;
 		events[i].imethod = 0;
-		events[i].masked = false;
-		events[i].unmask_cb = NULL;
 	}
 }
 
-/** Unsubscribe kernel events associated with an answerbox
- *
- * @param answerbox Answerbox to be unsubscribed.
- *
- */
-void event_cleanup_answerbox(answerbox_t *answerbox)
-{
-	for (unsigned int i = 0; i < EVENT_END; i++) {
-		spinlock_lock(&events[i].lock);
-		
-		if (events[i].answerbox == answerbox) {
-			events[i].answerbox = NULL;
-			events[i].counter = 0;
-			events[i].imethod = 0;
-			events[i].masked = false;
-		}
-		
-		spinlock_unlock(&events[i].lock);
-	}
-}
-
-/** Define a callback function for the event unmask event.
- *
- * @param evno Event type.
- * @param cb   Callback function to be called when the event is unmasked.
- *
- */
-void event_set_unmask_callback(event_type_t evno, void (*cb)(void))
-{
-	ASSERT(evno < EVENT_END);
-	
-	spinlock_lock(&events[evno].lock);
-	events[evno].unmask_cb = cb;
-	spinlock_unlock(&events[evno].lock);
-}
-
-/** Send kernel notification event
- *
- * @param evno Event type.
- * @param mask Mask further notifications after a successful
- *             sending.
- * @param a1   First argument.
- * @param a2   Second argument.
- * @param a3   Third argument.
- * @param a4   Fourth argument.
- * @param a5   Fifth argument.
- *
- * @return EOK if notification was successfully sent.
- * @return ENOMEM if the notification IPC message failed to allocate.
- * @return EBUSY if the notifications of the given type are
- *         currently masked.
- * @return ENOENT if the notifications of the given type are
- *         currently not subscribed.
- *
- */
-int event_notify(event_type_t evno, bool mask, sysarg_t a1, sysarg_t a2,
-    sysarg_t a3, sysarg_t a4, sysarg_t a5)
-{
-	ASSERT(evno < EVENT_END);
-	
-	spinlock_lock(&events[evno].lock);
-	
-	int ret;
-	
-	if (events[evno].answerbox != NULL) {
-		if (!events[evno].masked) {
-			call_t *call = ipc_call_alloc(FRAME_ATOMIC);
-			
-			if (call) {
-				call->flags |= IPC_CALL_NOTIF;
-				call->priv = ++events[evno].counter;
-				
-				IPC_SET_IMETHOD(call->data, events[evno].imethod);
-				IPC_SET_ARG1(call->data, a1);
-				IPC_SET_ARG2(call->data, a2);
-				IPC_SET_ARG3(call->data, a3);
-				IPC_SET_ARG4(call->data, a4);
-				IPC_SET_ARG5(call->data, a5);
-				
-				irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);
-				list_append(&call->link, &events[evno].answerbox->irq_notifs);
-				irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);
-				
-				waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);
-				
-				if (mask)
-					events[evno].masked = true;
-				
-				ret = EOK;
-			} else
-				ret = ENOMEM;
-		} else
-			ret = EBUSY;
-	} else
-		ret = ENOENT;
-	
-	spinlock_unlock(&events[evno].lock);
-	
-	return ret;
-}
-
-/** Subscribe event notifications
- *
- * @param evno      Event type.
- * @param imethod   IPC interface and method to be used for
- *                  the notifications.
- * @param answerbox Answerbox to send the notifications to.
- *
- * @return EOK if the subscription was successful.
- * @return EEXISTS if the notifications of the given type are
- *         already subscribed.
- *
- */
 static int event_subscribe(event_type_t evno, sysarg_t imethod,
     answerbox_t *answerbox)
 {
-	ASSERT(evno < EVENT_END);
+	if (evno >= EVENT_END)
+		return ELIMIT;
 	
 	spinlock_lock(&events[evno].lock);
@@ -189,5 +75,4 @@
 		events[evno].imethod = imethod;
 		events[evno].counter = 0;
-		events[evno].masked = false;
 		res = EOK;
 	} else
@@ -199,67 +84,65 @@
 }
 
-/** Unmask event notifications
- *
- * @param evno Event type to unmask.
- *
- */
-static void event_unmask(event_type_t evno)
-{
-	void (*cb)(void);
-	ASSERT(evno < EVENT_END);
-	
-	spinlock_lock(&events[evno].lock);
-	events[evno].masked = false;
-	cb = events[evno].unmask_cb;
-	spinlock_unlock(&events[evno].lock);
-	
-	/*
-	 * Check if there is an unmask callback function defined for this event.
-	 */
-	if (cb)
-	    cb();
-}
-
-/** Event notification syscall wrapper
- *
- * @param evno    Event type to subscribe.
- * @param imethod IPC interface and method to be used for
- *                the notifications.
- *
- * @return EOK on success.
- * @return ELIMIT on unknown event type.
- * @return EEXISTS if the notifications of the given type are
- *         already subscribed.
- *
- */
 sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
 {
-	if (evno >= EVENT_END)
-		return ELIMIT;
-	
 	return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
 	    imethod, &TASK->answerbox);
 }
 
-/** Event notification unmask syscall wrapper
- *
- * Note that currently no tests are performed whether the calling
- * task is entitled to unmask the notifications. However, thanks
- * to the fact that notification masking is only a performance
- * optimization, this has probably no security implications.
- *
- * @param evno Event type to unmask.
- *
- * @return EOK on success.
- * @return ELIMIT on unknown event type.
- *
- */
-sysarg_t sys_event_unmask(sysarg_t evno)
+bool event_is_subscribed(event_type_t evno)
 {
-	if (evno >= EVENT_END)
-		return ELIMIT;
+	bool res;
 	
-	event_unmask((event_type_t) evno);
-	return EOK;
+	ASSERT(evno < EVENT_END);
+	
+	spinlock_lock(&events[evno].lock);
+	res = events[evno].answerbox != NULL;
+	spinlock_unlock(&events[evno].lock);
+	
+	return res;
+}
+
+
+void event_cleanup_answerbox(answerbox_t *answerbox)
+{
+	unsigned int i;
+	
+	for (i = 0; i < EVENT_END; i++) {
+		spinlock_lock(&events[i].lock);
+		if (events[i].answerbox == answerbox) {
+			events[i].answerbox = NULL;
+			events[i].counter = 0;
+			events[i].imethod = 0;
+		}
+		spinlock_unlock(&events[i].lock);
+	}
+}
+
+void event_notify(event_type_t evno, sysarg_t a1, sysarg_t a2, sysarg_t a3,
+    sysarg_t a4, sysarg_t a5)
+{
+	ASSERT(evno < EVENT_END);
+	
+	spinlock_lock(&events[evno].lock);
+	if (events[evno].answerbox != NULL) {
+		call_t *call = ipc_call_alloc(FRAME_ATOMIC);
+		if (call) {
+			call->flags |= IPC_CALL_NOTIF;
+			call->priv = ++events[evno].counter;
+			IPC_SET_IMETHOD(call->data, events[evno].imethod);
+			IPC_SET_ARG1(call->data, a1);
+			IPC_SET_ARG2(call->data, a2);
+			IPC_SET_ARG3(call->data, a3);
+			IPC_SET_ARG4(call->data, a4);
+			IPC_SET_ARG5(call->data, a5);
+			
+			irq_spinlock_lock(&events[evno].answerbox->irq_lock, true);
+			list_append(&call->link, &events[evno].answerbox->irq_notifs);
+			irq_spinlock_unlock(&events[evno].answerbox->irq_lock, true);
+			
+			waitq_wakeup(&events[evno].answerbox->wq, WAKEUP_FIRST);
+		}
+	}
+	spinlock_unlock(&events[evno].lock);
 }
 
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ kernel/generic/src/proc/task.c	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -534,7 +534,9 @@
 	*/
 	if (notify) {
-		/* Notify the subscriber that a fault occurred. */
-		if (event_notify_3(EVENT_FAULT, false, LOWER32(TASK->taskid),
-		    UPPER32(TASK->taskid), (sysarg_t) THREAD) == EOK) {
+		if (event_is_subscribed(EVENT_FAULT)) {
+			/* Notify the subscriber that a fault occurred. */
+			event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid),
+			    UPPER32(TASK->taskid), (sysarg_t) THREAD);
+		
 #ifdef CONFIG_UDEBUG
 			/* Wait for a debugging session. */
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ kernel/generic/src/syscall/syscall.c	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -161,5 +161,4 @@
 	/* Event notification syscalls. */
 	(syshandler_t) sys_event_subscribe,
-	(syshandler_t) sys_event_unmask,
 	
 	/* Capabilities related syscalls. */
Index: uspace/app/klog/klog.c
===================================================================
--- uspace/app/klog/klog.c	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ uspace/app/klog/klog.c	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -44,20 +44,7 @@
 #include <io/klog.h>
 #include <sysinfo.h>
-#include <malloc.h>
-#include <fibril_synch.h>
-#include <adt/list.h>
-#include <adt/prodcons.h>
 
 #define NAME       "klog"
 #define LOG_FNAME  "/log/klog"
-
-/* Producer/consumer buffers */
-typedef struct {
-	link_t link;
-	size_t length;
-	wchar_t *data;
-} item_t;
-
-static prodcons_t pc;
 
 /* Pointer to klog area */
@@ -65,120 +52,26 @@
 static size_t klog_length;
 
-/* Notification mutex */
-static FIBRIL_MUTEX_INITIALIZE(mtx);
+static FILE *log;
 
-/** Klog producer
- *
- * Copies the contents of a character buffer to local
- * producer/consumer queue.
- *
- * @param length Number of characters to copy.
- * @param data   Pointer to the kernel klog buffer.
- *
- */
-static void producer(size_t length, wchar_t *data)
+static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
 {
-	item_t *item = (item_t *) malloc(sizeof(item_t));
-	if (item == NULL)
-		return;
-	
-	size_t sz = sizeof(wchar_t) * length;
-	wchar_t *buf = (wchar_t *) malloc(sz);
-	if (data == NULL) {
-		free(item);
-		return;
-	}
-	
-	memcpy(buf, data, sz);
-	
-	link_initialize(&item->link);
-	item->length = length;
-	item->data = buf;
-	prodcons_produce(&pc, &item->link);
-}
-
-/** Klog consumer
- *
- * Waits in an infinite loop for the character data created by
- * the producer and outputs them to stdout and optionally into
- * a file.
- *
- * @param data Unused.
- *
- * @return Always EOK (unreachable).
- *
- */
-static int consumer(void *data)
-{
-	FILE *log = fopen(LOG_FNAME, "a");
-	if (log == NULL)
-		printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME,
-		    str_error(errno));
-	
-	while (true) {
-		link_t *link = prodcons_consume(&pc);
-		item_t *item = list_get_instance(link, item_t, link);
-		
-		for (size_t i = 0; i < item->length; i++)
-			putchar(item->data[i]);
-		
-		if (log != NULL) {
-			for (size_t i = 0; i < item->length; i++)
-				fputc(item->data[i], log);
-			
-			fflush(log);
-			fsync(fileno(log));
-		}
-		
-		free(item->data);
-		free(item);
-	}
-	
-	fclose(log);
-	return EOK;
-}
-
-/** Kernel notification handler
- *
- * Receives kernel klog notifications.
- *
- * @param callid IPC call ID.
- * @param call   IPC call structure.
- *
- */
-static void notification_received(ipc_callid_t callid, ipc_call_t *call)
-{
-	/*
-	 * Make sure we process only a single notification
-	 * at any time to limit the chance of the consumer
-	 * starving.
-	 *
-	 * Note: Usually the automatic masking of the klog
-	 * notifications on the kernel side does the trick
-	 * of limiting the chance of accidentally copying
-	 * the same data multiple times. However, due to
-	 * the non-blocking architecture of klog notifications,
-	 * this possibility cannot be generally avoided.
-	 */
-	
-	fibril_mutex_lock(&mtx);
-	
 	size_t klog_start = (size_t) IPC_GET_ARG1(*call);
 	size_t klog_len = (size_t) IPC_GET_ARG2(*call);
 	size_t klog_stored = (size_t) IPC_GET_ARG3(*call);
+	size_t i;
 	
-	size_t offset = (klog_start + klog_len - klog_stored) % klog_length;
+	for (i = klog_len - klog_stored; i < klog_len; i++) {
+		wchar_t ch = klog[(klog_start + i) % klog_length];
+		
+		putchar(ch);
+		
+		if (log != NULL)
+			fputc(ch, log);
+	}
 	
-	/* Copy data from the ring buffer */
-	if (offset + klog_stored >= klog_length) {
-		size_t split = klog_length - offset;
-		
-		producer(split, klog + offset);
-		producer(klog_stored - split, klog);
-	} else
-		producer(klog_stored, klog + offset);
-	
-	event_unmask(EVENT_KLOG);
-	fibril_mutex_unlock(&mtx);
+	if (log != NULL) {
+		fflush(log);
+		fsync(fileno(log));
+	}
 }
 
@@ -218,6 +111,4 @@
 	}
 	
-	prodcons_initialize(&pc);
-	async_set_interrupt_received(notification_received);
 	rc = event_subscribe(EVENT_KLOG, 0);
 	if (rc != EOK) {
@@ -227,16 +118,11 @@
 	}
 	
-	fid_t fid = fibril_create(consumer, NULL);
-	if (!fid) {
-		fprintf(stderr, "%s: Unable to create consumer fibril\n",
-		    NAME);
-		return ENOMEM;
-	}
+	log = fopen(LOG_FNAME, "a");
+	if (log == NULL)
+		printf("%s: Unable to create log file %s (%s)\n", NAME, LOG_FNAME,
+		    str_error(errno));
 	
-	fibril_add_ready(fid);
-	event_unmask(EVENT_KLOG);
+	async_set_interrupt_received(interrupt_received);
 	klog_update();
-	
-	task_retval(0);
 	async_manager();
 	
Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ uspace/lib/c/Makefile	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -108,5 +108,4 @@
 	generic/adt/measured_strings.c \
 	generic/adt/char_map.c \
-	generic/adt/prodcons.c \
 	generic/time.c \
 	generic/stdlib.c \
Index: uspace/lib/c/generic/event.c
===================================================================
--- uspace/lib/c/generic/event.c	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ uspace/lib/c/generic/event.c	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -41,28 +41,14 @@
 #include <kernel/ipc/event_types.h>
 
-/** Subscribe event notifications.
+/** Subscribe for event notifications.
  *
- * @param evno    Event type to subscribe.
- * @param imethod Use this interface and method for notifying me.
+ * @param evno   Event number.
+ * @param method Use this method for notifying me.
  *
  * @return Value returned by the kernel.
- *
  */
-int event_subscribe(event_type_t evno, sysarg_t imethod)
+int event_subscribe(event_type_t e, sysarg_t method)
 {
-	return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) evno,
-	    (sysarg_t) imethod);
-}
-
-/** Unmask event notifications.
- *
- * @param evno Event type to unmask.
- *
- * @return Value returned by the kernel.
- *
- */
-int event_unmask(event_type_t evno)
-{
-	return __SYSCALL1(SYS_EVENT_UNMASK, (sysarg_t) evno);
+	return __SYSCALL2(SYS_EVENT_SUBSCRIBE, (sysarg_t) e, (sysarg_t) method);
 }
 
Index: uspace/lib/c/include/event.h
===================================================================
--- uspace/lib/c/include/event.h	(revision 0d8a304c1941d4b637abf937d8947384c88d0e1c)
+++ uspace/lib/c/include/event.h	(revision 8d308b91dd790ada0c5d8348bda8fc122a39f6b6)
@@ -39,5 +39,4 @@
 
 extern int event_subscribe(event_type_t, sysarg_t);
-extern int event_unmask(event_type_t);
 
 #endif
