Index: uspace/lib/libc/generic/fibril_sync.c
===================================================================
--- uspace/lib/libc/generic/fibril_sync.c	(revision b6ee5b112c06c03a7a1b7e50e20d88d3e5413c99)
+++ uspace/lib/libc/generic/fibril_sync.c	(revision cadfa8e37bd57b0ecdb6ecb56bf3e1e89431dced)
@@ -36,6 +36,9 @@
 #include <fibril.h>
 #include <async.h>
+#include <async_priv.h>
 #include <adt/list.h>
 #include <futex.h>
+#include <sys/time.h>
+#include <errno.h>
 #include <assert.h>
 
@@ -194,13 +197,51 @@
 }
 
-void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
-{
-	fibril_t *f = (fibril_t *) fibril_get_id();
-
-	futex_down(&async_futex);
-	list_append(&f->link, &fcv->waiters);
+int
+fibril_condvar_wait_timeout(fibril_condvar_t *fcv, fibril_mutex_t *fm,
+    suseconds_t timeout)
+{
+	awaiter_t wdata;
+
+	if (timeout < 0)
+		return ETIMEOUT;
+
+	wdata.fid = fibril_get_id();
+	wdata.active = false;
+	
+	wdata.to_event.inlist = timeout > 0;
+	wdata.to_event.occurred = false;
+	link_initialize(&wdata.to_event.link);
+
+	wdata.wu_event.inlist = true;
+	link_initialize(&wdata.wu_event.link);
+
+	futex_down(&async_futex);
+	if (timeout) {
+		gettimeofday(&wdata.to_event.expires, NULL);
+		tv_add(&wdata.to_event.expires, timeout);
+		async_insert_timeout(&wdata);
+	}
+	list_append(&wdata.wu_event.link, &fcv->waiters);
 	_fibril_mutex_unlock_unsafe(fm);
 	fibril_switch(FIBRIL_TO_MANAGER);
 	fibril_mutex_lock(fm);
+
+	/* async_futex not held after fibril_switch() */
+	futex_down(&async_futex);
+	if (wdata.to_event.inlist)
+		list_remove(&wdata.to_event.link);
+	if (wdata.wu_event.inlist)
+		list_remove(&wdata.wu_event.link);
+	futex_up(&async_futex);
+	
+	return wdata.to_event.occurred ? ETIMEOUT : EOK;
+}
+
+void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
+{
+	int rc;
+
+	rc = fibril_condvar_wait_timeout(fcv, fm, 0);
+	assert(rc == EOK);
 }
 
@@ -208,15 +249,19 @@
 {
 	link_t *tmp;
-	fibril_t *f;
+	awaiter_t *wdp;
 
 	futex_down(&async_futex);
 	while (!list_empty(&fcv->waiters)) {
 		tmp = fcv->waiters.next;
-		f = list_get_instance(tmp, fibril_t, link);
-		list_remove(&f->link);
-		fibril_add_ready((fid_t) f);
-		optimize_execution_power();
-		if (once)
-			break;
+		wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
+		list_remove(&wdp->wu_event.link);
+		wdp->wu_event.inlist = false;
+		if (!wdp->active) {
+			wdp->active = true;
+			fibril_add_ready(wdp->fid);
+			optimize_execution_power();
+			if (once)
+				break;
+		}
 	}
 	futex_up(&async_futex);
Index: uspace/lib/libc/include/async_priv.h
===================================================================
--- uspace/lib/libc/include/async_priv.h	(revision b6ee5b112c06c03a7a1b7e50e20d88d3e5413c99)
+++ uspace/lib/libc/include/async_priv.h	(revision cadfa8e37bd57b0ecdb6ecb56bf3e1e89431dced)
@@ -56,4 +56,14 @@
 } to_event_t;
 
+/** Structures of this type are used to track the wakeup events. */
+typedef struct {
+	/** If true, this struct is in a synchronization object wait queue. */
+	bool inlist;
+	
+	/** Wait queue linkage. */
+	link_t link;
+} wu_event_t;
+
+
 /** Structures of this type represent a waiting fibril. */
 typedef struct {
@@ -66,4 +76,6 @@
 	/** Timeout wait data. */
 	to_event_t to_event;
+	/** Wakeup wait data. */
+	wu_event_t wu_event;
 } awaiter_t;
 
Index: uspace/lib/libc/include/fibril_sync.h
===================================================================
--- uspace/lib/libc/include/fibril_sync.h	(revision b6ee5b112c06c03a7a1b7e50e20d88d3e5413c99)
+++ uspace/lib/libc/include/fibril_sync.h	(revision cadfa8e37bd57b0ecdb6ecb56bf3e1e89431dced)
@@ -40,4 +40,5 @@
 #include <adt/list.h>
 #include <libarch/tls.h>
+#include <sys/time.h>
 
 typedef struct {
@@ -95,4 +96,6 @@
 
 extern void fibril_condvar_initialize(fibril_condvar_t *);
+extern int fibril_condvar_wait_timeout(fibril_condvar_t *, fibril_mutex_t *,
+    suseconds_t);
 extern void fibril_condvar_wait(fibril_condvar_t *, fibril_mutex_t *);
 extern void fibril_condvar_signal(fibril_condvar_t *);
