Index: abi/include/ipc/event.h
===================================================================
--- abi/include/ipc/event.h	(revision b585dfa9a61a823b2ba3b4f72b856063abaf77e3)
+++ abi/include/ipc/event.h	(revision 5d0500cf34f298133f120c2783fb8ef7d5fb2e9c)
@@ -46,4 +46,10 @@
 } event_type_t;
 
+/** Per-task events. */
+typedef enum event_task_type {
+	EVENT_TASK_STATE_CHANGE = EVENT_END,
+	EVENT_TASK_END
+} event_task_type_t;
+
 #endif
 
Index: kernel/generic/include/console/console.h
===================================================================
--- kernel/generic/include/console/console.h	(revision b585dfa9a61a823b2ba3b4f72b856063abaf77e3)
+++ kernel/generic/include/console/console.h	(revision 5d0500cf34f298133f120c2783fb8ef7d5fb2e9c)
@@ -63,5 +63,5 @@
 
 extern void klog_init(void);
-extern void klog_update(void);
+extern void klog_update(void *);
 
 extern wchar_t getc(indev_t *indev);
Index: kernel/generic/include/ipc/event.h
===================================================================
--- kernel/generic/include/ipc/event.h	(revision b585dfa9a61a823b2ba3b4f72b856063abaf77e3)
+++ kernel/generic/include/ipc/event.h	(revision 5d0500cf34f298133f120c2783fb8ef7d5fb2e9c)
@@ -41,5 +41,7 @@
 #include <ipc/ipc.h>
 
-typedef void (*event_callback_t)(void);
+typedef struct task task_t;
+
+typedef void (*event_callback_t)(void *);
 
 /** Event notification structure. */
@@ -61,6 +63,9 @@
 
 extern void event_init(void);
+extern void event_task_init(task_t *);
 extern void event_cleanup_answerbox(answerbox_t *);
 extern void event_set_unmask_callback(event_type_t, event_callback_t);
+extern void event_task_set_unmask_callback(task_t *, event_task_type_t,
+    event_callback_t);
 
 #define event_notify_0(e, m) \
@@ -77,6 +82,21 @@
 	event_notify((e), (m), (a1), (a2), (a3), (a4), (a5))
 
+#define event_task_notify_0(t, e, m) \
+	event_task_notify((t), (e), (m), 0, 0, 0, 0, 0)
+#define event_task_notify_1(t, e, m, a1) \
+	event_task_notify((t), (e), (m), (a1), 0, 0, 0, 0)
+#define event_task_notify_2(t, e, m, a1, a2) \
+	event_task_notify((t), (e), (m), (a1), (a2), 0, 0, 0)
+#define event_task_notify_3(t, e, m, a1, a2, a3) \
+	event_task_notify((t), (e), (m), (a1), (a2), (a3), 0, 0)
+#define event_task_notify_4(t, e, m, a1, a2, a3, a4) \
+	event_task_notify((t), (e), (m), (a1), (a2), (a3), (a4), 0)
+#define event_task_notify_5(t, e, m, a1, a2, a3, a4, a5) \
+	event_task_notify((t), (e), (m), (a1), (a2), (a3), (a4), (a5))
+
 extern int event_notify(event_type_t, bool, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t);
+extern int event_task_notify(task_t *, event_task_type_t, bool, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t);
 
 extern sysarg_t sys_event_subscribe(sysarg_t, sysarg_t);
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision b585dfa9a61a823b2ba3b4f72b856063abaf77e3)
+++ kernel/generic/include/proc/task.h	(revision 5d0500cf34f298133f120c2783fb8ef7d5fb2e9c)
@@ -38,4 +38,6 @@
 #include <cpu.h>
 #include <ipc/ipc.h>
+#include <ipc/event.h>
+#include <ipc/kbox.h>
 #include <synch/spinlock.h>
 #include <synch/mutex.h>
@@ -53,5 +55,4 @@
 #include <proc/scheduler.h>
 #include <udebug/udebug.h>
-#include <ipc/kbox.h>
 #include <mm/as.h>
 #include <abi/sysinfo.h>
@@ -93,6 +94,6 @@
 	phone_t phones[IPC_MAX_PHONES];
 	stats_ipc_t ipc_info;   /**< IPC statistics */
-	/** List of synchronous answerboxes. */
-	list_t sync_boxes;
+	list_t sync_boxes;      /**< List of synchronous answerboxes. */
+	event_t events[EVENT_TASK_END - EVENT_END];
 	
 #ifdef CONFIG_UDEBUG
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision b585dfa9a61a823b2ba3b4f72b856063abaf77e3)
+++ kernel/generic/src/console/console.c	(revision 5d0500cf34f298133f120c2783fb8ef7d5fb2e9c)
@@ -248,5 +248,5 @@
 }
 
-void klog_update(void)
+void klog_update(void *e)
 {
 	if (!atomic_get(&klog_inited))
@@ -327,5 +327,5 @@
 	/* Force notification on newline */
 	if (ch == '\n')
-		klog_update();
+		klog_update(NULL);
 }
 
@@ -358,5 +358,5 @@
 		free(data);
 	} else
-		klog_update();
+		klog_update(NULL);
 	
 	return size;
Index: kernel/generic/src/ipc/event.c
===================================================================
--- kernel/generic/src/ipc/event.c	(revision b585dfa9a61a823b2ba3b4f72b856063abaf77e3)
+++ kernel/generic/src/ipc/event.c	(revision 5d0500cf34f298133f120c2783fb8ef7d5fb2e9c)
@@ -40,4 +40,5 @@
 #include <synch/spinlock.h>
 #include <console/console.h>
+#include <proc/task.h>
 #include <memstr.h>
 #include <errno.h>
@@ -47,4 +48,28 @@
 static event_t events[EVENT_END];
 
+static void event_initialize(event_t *event)
+{
+	spinlock_initialize(&event->lock, "event.lock");
+	event->answerbox = NULL;
+	event->counter = 0;
+	event->imethod = 0;
+	event->masked = false;
+	event->unmask_callback = NULL;
+}
+
+static event_t *evno2event(int evno, task_t *t)
+{
+	ASSERT(evno < EVENT_TASK_END);
+
+	event_t *event;
+
+	if (evno < EVENT_END)
+		event = &events[(event_type_t) evno];
+	else
+		event = &t->events[(event_task_type_t) evno - EVENT_END];
+
+	return event;
+}
+
 /** Initialize kernel events.
  *
@@ -52,13 +77,14 @@
 void event_init(void)
 {
-	for (unsigned int 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_callback = NULL;
-	}
-}
+	for (unsigned int i = 0; i < EVENT_END; i++)
+		event_initialize(evno2event(i, NULL));
+}
+
+void event_task_init(task_t *t)
+{
+	for (unsigned int i = EVENT_END; i < EVENT_TASK_END; i++)
+		event_initialize(evno2event(i, t));
+}
+
 
 /** Unsubscribe kernel events associated with an answerbox
@@ -83,4 +109,11 @@
 }
 
+static void _event_set_unmask_callback(event_t *event, event_callback_t callback)
+{
+	spinlock_lock(&event->lock);
+	event->unmask_callback = callback;
+	spinlock_unlock(&event->lock);
+}
+
 /** Define a callback function for the event unmask event.
  *
@@ -94,7 +127,57 @@
 	ASSERT(evno < EVENT_END);
 	
-	spinlock_lock(&events[evno].lock);
-	events[evno].unmask_callback = callback;
-	spinlock_unlock(&events[evno].lock);
+	_event_set_unmask_callback(evno2event(evno, NULL), callback);
+}
+
+void event_task_set_unmask_callback(task_t *t, event_task_type_t evno,
+    event_callback_t callback)
+{
+	ASSERT(evno >= (int) EVENT_END);
+	ASSERT(evno < EVENT_TASK_END);
+		
+	_event_set_unmask_callback(evno2event(evno, t), callback);
+}
+
+static int event_enqueue(event_t *event, bool mask, sysarg_t a1, sysarg_t a2,
+    sysarg_t a3, sysarg_t a4, sysarg_t a5)
+{
+	int res;
+
+	spinlock_lock(&event->lock);
+	
+	if (event->answerbox != NULL) {
+		if (!event->masked) {
+			call_t *call = ipc_call_alloc(FRAME_ATOMIC);
+			
+			if (call) {
+				call->flags |= IPC_CALL_NOTIF;
+				call->priv = ++event->counter;
+				
+				IPC_SET_IMETHOD(call->data, event->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(&event->answerbox->irq_lock, true);
+				list_append(&call->link, &event->answerbox->irq_notifs);
+				irq_spinlock_unlock(&event->answerbox->irq_lock, true);
+				
+				waitq_wakeup(&event->answerbox->wq, WAKEUP_FIRST);
+				
+				if (mask)
+					event->masked = true;
+				
+				res = EOK;
+			} else
+				res = ENOMEM;
+		} else
+			res = EBUSY;
+	} else
+		res = ENOENT;
+	
+	spinlock_unlock(&event->lock);
+	return res;
 }
 
@@ -123,43 +206,34 @@
 	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;
+	return event_enqueue(evno2event(evno, NULL), mask, a1, a2, a3, a4, a5);
+}
+
+/** Send per-task kernel notification event
+ *
+ * @param t    Destination task.
+ * @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_task_notify(task_t *t, event_task_type_t evno, bool mask, sysarg_t a1,
+    sysarg_t a2, sysarg_t a3, sysarg_t a4, sysarg_t a5)
+{
+	ASSERT(evno >= (int) EVENT_END);
+	ASSERT(evno < EVENT_TASK_END);
+	
+	return event_enqueue(evno2event(evno, t), mask, a1, a2, a3, a4, a5);
 }
 
@@ -176,23 +250,21 @@
  *
  */
-static int event_subscribe(event_type_t evno, sysarg_t imethod,
+static int event_subscribe(event_t *event, sysarg_t imethod,
     answerbox_t *answerbox)
 {
-	ASSERT(evno < EVENT_END);
-	
-	spinlock_lock(&events[evno].lock);
-	
 	int res;
-	
-	if (events[evno].answerbox == NULL) {
-		events[evno].answerbox = answerbox;
-		events[evno].imethod = imethod;
-		events[evno].counter = 0;
-		events[evno].masked = false;
+
+	spinlock_lock(&event->lock);
+	
+	if (event->answerbox == NULL) {
+		event->answerbox = answerbox;
+		event->imethod = imethod;
+		event->counter = 0;
+		event->masked = false;
 		res = EOK;
 	} else
 		res = EEXISTS;
 	
-	spinlock_unlock(&events[evno].lock);
+	spinlock_unlock(&event->lock);
 	
 	return res;
@@ -204,12 +276,10 @@
  *
  */
-static void event_unmask(event_type_t evno)
-{
-	ASSERT(evno < EVENT_END);
-	
-	spinlock_lock(&events[evno].lock);
-	events[evno].masked = false;
-	event_callback_t callback = events[evno].unmask_callback;
-	spinlock_unlock(&events[evno].lock);
+static void event_unmask(event_t *event)
+{
+	spinlock_lock(&event->lock);
+	event->masked = false;
+	event_callback_t callback = event->unmask_callback;
+	spinlock_unlock(&event->lock);
 	
 	/*
@@ -218,5 +288,5 @@
 	 */
 	if (callback != NULL)
-		callback();
+		callback(event);
 }
 
@@ -235,9 +305,9 @@
 sysarg_t sys_event_subscribe(sysarg_t evno, sysarg_t imethod)
 {
-	if (evno >= EVENT_END)
+	if (evno >= EVENT_TASK_END)
 		return ELIMIT;
 	
-	return (sysarg_t) event_subscribe((event_type_t) evno, (sysarg_t)
-	    imethod, &TASK->answerbox);
+	return (sysarg_t) event_subscribe(evno2event(evno, TASK),
+	    (sysarg_t) imethod, &TASK->answerbox);
 }
 
@@ -257,8 +327,9 @@
 sysarg_t sys_event_unmask(sysarg_t evno)
 {
-	if (evno >= EVENT_END)
+	if (evno >= EVENT_TASK_END)
 		return ELIMIT;
 	
-	event_unmask((event_type_t) evno);
+	event_unmask(evno2event(evno, TASK));
+
 	return EOK;
 }
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision b585dfa9a61a823b2ba3b4f72b856063abaf77e3)
+++ kernel/generic/src/proc/task.c	(revision 5d0500cf34f298133f120c2783fb8ef7d5fb2e9c)
@@ -50,4 +50,5 @@
 #include <ipc/ipc.h>
 #include <ipc/ipcrsc.h>
+#include <ipc/event.h>
 #include <print.h>
 #include <errno.h>
@@ -57,5 +58,4 @@
 #include <syscall/copy.h>
 #include <macros.h>
-#include <ipc/event.h>
 
 /** Spinlock protecting the tasks_tree AVL tree. */
@@ -201,4 +201,6 @@
 	task->ipc_info.irq_notif_received = 0;
 	task->ipc_info.forwarded = 0;
+
+	event_task_init(task);
 	
 #ifdef CONFIG_UDEBUG
