Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 6bb136b2fbaaf208b1d7f318f3ef4951346fdf35)
+++ uspace/lib/c/generic/fibril_synch.c	(revision d742db216b1d7efda0a82bee848205d7ffe4a730)
@@ -664,4 +664,5 @@
 	 */
 	assert(count >= 0);
+	sem->closed = false;
 	sem->count = count;
 	list_initialize(&sem->waiters);
@@ -679,4 +680,10 @@
 {
 	futex_lock(&fibril_synch_futex);
+
+	if (sem->closed) {
+		futex_unlock(&fibril_synch_futex);
+		return;
+	}
+
 	sem->count++;
 
@@ -700,4 +707,10 @@
 {
 	futex_lock(&fibril_synch_futex);
+
+	if (sem->closed) {
+		futex_unlock(&fibril_synch_futex);
+		return;
+	}
+
 	sem->count--;
 
@@ -715,4 +728,68 @@
 }
 
+errno_t fibril_semaphore_down_timeout(fibril_semaphore_t *sem, suseconds_t timeout)
+{
+	if (timeout < 0)
+		return ETIMEOUT;
+
+	futex_lock(&fibril_synch_futex);
+	if (sem->closed) {
+		futex_unlock(&fibril_synch_futex);
+		return EOK;
+	}
+
+	sem->count--;
+
+	if (sem->count >= 0) {
+		futex_unlock(&fibril_synch_futex);
+		return EOK;
+	}
+
+	awaiter_t wdata = AWAITER_INIT;
+	list_append(&wdata.link, &sem->waiters);
+
+	futex_unlock(&fibril_synch_futex);
+
+	struct timeval tv;
+	struct timeval *expires = NULL;
+	if (timeout) {
+		getuptime(&tv);
+		tv_add_diff(&tv, timeout);
+		expires = &tv;
+	}
+
+	errno_t rc = fibril_wait_timeout(&wdata.event, expires);
+	if (rc == EOK)
+		return EOK;
+
+	futex_lock(&fibril_synch_futex);
+	if (!link_in_use(&wdata.link)) {
+		futex_unlock(&fibril_synch_futex);
+		return EOK;
+	}
+
+	list_remove(&wdata.link);
+	sem->count++;
+	futex_unlock(&fibril_synch_futex);
+
+	return rc;
+}
+
+/**
+ * Close the semaphore.
+ * All future down() operations return instantly.
+ */
+void fibril_semaphore_close(fibril_semaphore_t *sem)
+{
+	futex_lock(&fibril_synch_futex);
+	sem->closed = true;
+	awaiter_t *w;
+
+	while ((w = list_pop(&sem->waiters, awaiter_t, link)))
+		fibril_notify(&w->event);
+
+	futex_unlock(&fibril_synch_futex);
+}
+
 /** @}
  */
Index: uspace/lib/c/include/fibril_synch.h
===================================================================
--- uspace/lib/c/include/fibril_synch.h	(revision 6bb136b2fbaaf208b1d7f318f3ef4951346fdf35)
+++ uspace/lib/c/include/fibril_synch.h	(revision d742db216b1d7efda0a82bee848205d7ffe4a730)
@@ -186,4 +186,5 @@
 	long int count;
 	list_t waiters;
+	bool closed;
 } fibril_semaphore_t;
 
@@ -241,4 +242,6 @@
 extern void fibril_semaphore_up(fibril_semaphore_t *);
 extern void fibril_semaphore_down(fibril_semaphore_t *);
+extern errno_t fibril_semaphore_down_timeout(fibril_semaphore_t *, suseconds_t);
+extern void fibril_semaphore_close(fibril_semaphore_t *);
 
 #endif
