Index: kernel/generic/src/synch/condvar.c
===================================================================
--- kernel/generic/src/synch/condvar.c	(revision 89ea2dc48f26dfcd2aba2a270dac8523cec931c2)
+++ kernel/generic/src/synch/condvar.c	(revision 4547f1115bd8270b9a1bcf3bb8d3e02111295371)
@@ -80,5 +80,5 @@
  * For exact description of meaning of possible combinations of usec and flags,
  * see comment for waitq_sleep_timeout().  Note that when
- * SYNCH_FLAGS_NON_BLOCKING is specified here, ESYNCH_WOULD_BLOCK is always
+ * SYNCH_FLAGS_NON_BLOCKING is specified here, EAGAIN is always
  * returned.
  *
@@ -89,4 +89,5 @@
 	int rc;
 	ipl_t ipl;
+	bool blocked;
 
 	ipl = waitq_sleep_prepare(&cv->wq);
@@ -95,7 +96,8 @@
 
 	cv->wq.missed_wakeups = 0;	/* Enforce blocking. */
-	rc = waitq_sleep_timeout_unsafe(&cv->wq, usec, flags);
+	rc = waitq_sleep_timeout_unsafe(&cv->wq, usec, flags, &blocked);
+	assert(blocked || rc != EOK);
 
-	waitq_sleep_finish(&cv->wq, rc, ipl);
+	waitq_sleep_finish(&cv->wq, blocked, ipl);
 	/* Lock only after releasing the waitq to avoid a possible deadlock. */
 	mutex_lock(mtx);
@@ -117,5 +119,5 @@
  * For exact description of meaning of possible combinations of usec and flags,
  * see comment for waitq_sleep_timeout().  Note that when
- * SYNCH_FLAGS_NON_BLOCKING is specified here, ESYNCH_WOULD_BLOCK is always
+ * SYNCH_FLAGS_NON_BLOCKING is specified here, EAGAIN is always
  * returned.
  *
@@ -127,5 +129,6 @@
 	int rc;
 	ipl_t ipl;
-	
+	bool blocked;
+
 	ipl = waitq_sleep_prepare(&cv->wq);
 
@@ -134,7 +137,8 @@
 
 	cv->wq.missed_wakeups = 0;	/* Enforce blocking. */
-	rc = waitq_sleep_timeout_unsafe(&cv->wq, usec, flags);
+	rc = waitq_sleep_timeout_unsafe(&cv->wq, usec, flags, &blocked);
+	assert(blocked || rc != EOK);
 
-	waitq_sleep_finish(&cv->wq, rc, ipl);
+	waitq_sleep_finish(&cv->wq, blocked, ipl);
 	/* Lock only after releasing the waitq to avoid a possible deadlock. */
 	spinlock_lock(lock);
@@ -152,5 +156,5 @@
  * For exact description of meaning of possible combinations of usec and flags,
  * see comment for waitq_sleep_timeout().  Note that when
- * SYNCH_FLAGS_NON_BLOCKING is specified here, ESYNCH_WOULD_BLOCK is always
+ * SYNCH_FLAGS_NON_BLOCKING is specified here, EAGAIN is always
  * returned.
  *
Index: kernel/generic/src/synch/futex.c
===================================================================
--- kernel/generic/src/synch/futex.c	(revision 89ea2dc48f26dfcd2aba2a270dac8523cec931c2)
+++ kernel/generic/src/synch/futex.c	(revision 4547f1115bd8270b9a1bcf3bb8d3e02111295371)
@@ -395,6 +395,6 @@
  *
  * @return		If there is no physical mapping for uaddr ENOENT is
- *			returned. Otherwise returns a wait result as defined in
- *			synch.h.
+ *			returned. Otherwise returns the return value of
+ *                      waitq_sleep_timeout().
  */
 sysarg_t sys_futex_sleep(uintptr_t uaddr)
@@ -409,5 +409,6 @@
 #endif
 
-	int rc = waitq_sleep_timeout(&futex->wq, 0, SYNCH_FLAGS_INTERRUPTIBLE); 
+	int rc = waitq_sleep_timeout(
+	    &futex->wq, 0, SYNCH_FLAGS_INTERRUPTIBLE, NULL);
 
 #ifdef CONFIG_UDEBUG
@@ -430,5 +431,5 @@
 	if (futex) {
 		waitq_wakeup(&futex->wq, WAKEUP_FIRST);
-		return 0;
+		return EOK;
 	} else {
 		return (sysarg_t) ENOENT;
Index: kernel/generic/src/synch/mutex.c
===================================================================
--- kernel/generic/src/synch/mutex.c	(revision 89ea2dc48f26dfcd2aba2a270dac8523cec931c2)
+++ kernel/generic/src/synch/mutex.c	(revision 4547f1115bd8270b9a1bcf3bb8d3e02111295371)
@@ -37,4 +37,5 @@
 
 #include <assert.h>
+#include <errno.h>
 #include <synch/mutex.h>
 #include <synch/semaphore.h>
@@ -95,8 +96,8 @@
 		if (mtx->owner == THREAD) {
 			mtx->nesting++;
-			return ESYNCH_OK_ATOMIC;
+			return EOK;
 		} else {
 			rc = _semaphore_down_timeout(&mtx->sem, usec, flags);
-			if (SYNCH_OK(rc)) {
+			if (rc == EOK) {
 				mtx->owner = THREAD;
 				mtx->nesting = 1;
@@ -119,6 +120,5 @@
 			}
 			rc = semaphore_trydown(&mtx->sem);
-		} while (SYNCH_FAILED(rc) &&
-		    !(flags & SYNCH_FLAGS_NON_BLOCKING));
+		} while (rc != EOK && !(flags & SYNCH_FLAGS_NON_BLOCKING));
 		if (deadlock_reported)
 			printf("cpu%u: not deadlocked\n", CPU->id);
Index: kernel/generic/src/synch/rcu.c
===================================================================
--- kernel/generic/src/synch/rcu.c	(revision 89ea2dc48f26dfcd2aba2a270dac8523cec931c2)
+++ kernel/generic/src/synch/rcu.c	(revision 4547f1115bd8270b9a1bcf3bb8d3e02111295371)
@@ -960,5 +960,5 @@
 				SYNCH_NO_TIMEOUT, SYNCH_FLAGS_INTERRUPTIBLE);
 			
-			if (ret == ESYNCH_INTERRUPTED) {
+			if (ret == EINTR) {
 				spinlock_unlock(&rcu.gp_lock);
 				return false;			
@@ -1018,5 +1018,5 @@
 
 		/* rcu.expedite_now was signaled. */
-		if (ret == ESYNCH_OK_BLOCKED) {
+		if (ret == EOK) {
 			*expedite = true;
 		}
@@ -1024,5 +1024,5 @@
 		spinlock_unlock(&rcu.gp_lock);
 
-		return (ret != ESYNCH_INTERRUPTED);
+		return (ret != EINTR);
 	}
 }
@@ -1271,5 +1271,5 @@
 		int ret = _condvar_wait_timeout_spinlock(&rcu.gp_ended, &rcu.gp_lock, 
 			SYNCH_NO_TIMEOUT, SYNCH_FLAGS_INTERRUPTIBLE);
-		interrupted = (ret == ESYNCH_INTERRUPTED);
+		interrupted = (ret == EINTR);
 	}
 	
@@ -1332,5 +1332,5 @@
 			&rcu.gp_lock, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_INTERRUPTIBLE);
 		
-		interrupted = (ret == ESYNCH_INTERRUPTED);
+		interrupted = (ret == EINTR);
 	}
 	
@@ -1406,5 +1406,5 @@
 	spinlock_unlock(&rcu.gp_lock);
 	
-	return (ret != ESYNCH_INTERRUPTED);
+	return (ret != EINTR);
 }
 
Index: kernel/generic/src/synch/semaphore.c
===================================================================
--- kernel/generic/src/synch/semaphore.c	(revision 89ea2dc48f26dfcd2aba2a270dac8523cec931c2)
+++ kernel/generic/src/synch/semaphore.c	(revision 4547f1115bd8270b9a1bcf3bb8d3e02111295371)
@@ -73,5 +73,5 @@
 int _semaphore_down_timeout(semaphore_t *sem, uint32_t usec, unsigned int flags)
 {
-	return waitq_sleep_timeout(&sem->wq, usec, flags);
+	return waitq_sleep_timeout(&sem->wq, usec, flags, NULL);
 }
 
Index: kernel/generic/src/synch/waitq.c
===================================================================
--- kernel/generic/src/synch/waitq.c	(revision 89ea2dc48f26dfcd2aba2a270dac8523cec931c2)
+++ kernel/generic/src/synch/waitq.c	(revision 4547f1115bd8270b9a1bcf3bb8d3e02111295371)
@@ -45,4 +45,5 @@
 
 #include <assert.h>
+#include <errno.h>
 #include <synch/waitq.h>
 #include <synch/spinlock.h>
@@ -238,4 +239,8 @@
  * @param flags Specify mode of the sleep.
  *
+ * @param[out] blocked  On return, regardless of the return code,
+ *                      `*blocked` is set to `true` iff the thread went to
+ *                      sleep.
+ *
  * The sleep can be interrupted only if the
  * SYNCH_FLAGS_INTERRUPTIBLE bit is specified in flags.
@@ -251,23 +256,28 @@
  * call will immediately return, reporting either success or failure.
  *
- * @return ESYNCH_WOULD_BLOCK, meaning that the sleep failed because at the
- *         time of the call there was no pending wakeup
- * @return ESYNCH_TIMEOUT, meaning that the sleep timed out.
- * @return ESYNCH_INTERRUPTED, meaning that somebody interrupted the sleeping
- *         thread.
- * @return ESYNCH_OK_ATOMIC, meaning that the sleep succeeded and that there
- *         was a pending wakeup at the time of the call. The caller was not put
- *         asleep at all.
- * @return ESYNCH_OK_BLOCKED, meaning that the sleep succeeded; the full sleep
- *         was attempted.
- *
- */
-int waitq_sleep_timeout(waitq_t *wq, uint32_t usec, unsigned int flags)
+ * @return EAGAIN, meaning that the sleep failed because it was requested
+ *                 as SYNCH_FLAGS_NON_BLOCKING, but there was no pending wakeup.
+ * @return ETIMEOUT, meaning that the sleep timed out.
+ * @return EINTR, meaning that somebody interrupted the sleeping
+ *         thread. Check the value of `*blocked` to see if the thread slept,
+ *         or if a pending interrupt forced it to return immediately.
+ * @return EOK, meaning that none of the above conditions occured, and the
+ *              thread was woken up successfuly by `waitq_wakeup()`. Check
+ *              the value of `*blocked` to see if the thread slept or if
+ *              the wakeup was already pending.
+ *
+ */
+int waitq_sleep_timeout(waitq_t *wq, uint32_t usec, unsigned int flags, bool *blocked)
 {
 	assert((!PREEMPTION_DISABLED) || (PARAM_NON_BLOCKING(flags, usec)));
 	
 	ipl_t ipl = waitq_sleep_prepare(wq);
-	int rc = waitq_sleep_timeout_unsafe(wq, usec, flags);
-	waitq_sleep_finish(wq, rc, ipl);
+	bool nblocked;
+	int rc = waitq_sleep_timeout_unsafe(wq, usec, flags, &nblocked);
+	waitq_sleep_finish(wq, nblocked, ipl);
+
+	if (blocked != NULL) {
+		*blocked = nblocked;
+	}
 	return rc;
 }
@@ -320,32 +330,27 @@
  * lock is released.
  *
- * @param wq  Wait queue.
- * @param rc  Return code of waitq_sleep_timeout_unsafe().
- * @param ipl Interrupt level returned by waitq_sleep_prepare().
- *
- */
-void waitq_sleep_finish(waitq_t *wq, int rc, ipl_t ipl)
-{
-	switch (rc) {
-	case ESYNCH_WOULD_BLOCK:
-	case ESYNCH_OK_ATOMIC:
-		irq_spinlock_unlock(&wq->lock, false);
-		break;
-	default:
-		/* 
+ * @param wq       Wait queue.
+ * @param blocked  Out parameter of waitq_sleep_timeout_unsafe().
+ * @param ipl      Interrupt level returned by waitq_sleep_prepare().
+ *
+ */
+void waitq_sleep_finish(waitq_t *wq, bool blocked, ipl_t ipl)
+{
+	if (blocked) {
+		/*
 		 * Wait for a waitq_wakeup() or waitq_unsleep() to complete
 		 * before returning from waitq_sleep() to the caller. Otherwise
 		 * the caller might expect that the wait queue is no longer used 
 		 * and deallocate it (although the wakeup on a another cpu has 
-		 * not yet completed and is using the wait queue). 
-		 * 
-		 * Note that we have to do this for ESYNCH_OK_BLOCKED and
-		 * ESYNCH_INTERRUPTED, but not necessarily for ESYNCH_TIMEOUT
-		 * where the timeout handler stops using the waitq before waking 
-		 * us up. To be on the safe side, ensure the waitq is not in use 
-		 * anymore in this case as well.
+		 * not yet completed and is using the wait queue).
+		 *
+		 * Note that we have to do this for EOK and EINTR, but not
+		 * necessarily for ETIMEOUT where the timeout handler stops
+		 * using the waitq before waking us up. To be on the safe side,
+		 * ensure the waitq is not in use anymore in this case as well.
 		 */
 		waitq_complete_wakeup(wq);
-		break;
+	} else {
+		irq_spinlock_unlock(&wq->lock, false);
 	}
 	
@@ -363,17 +368,21 @@
  * @param flags See waitq_sleep_timeout().
  *
+ * @param[out] blocked  See waitq_sleep_timeout().
+ *
  * @return See waitq_sleep_timeout().
  *
  */
-int waitq_sleep_timeout_unsafe(waitq_t *wq, uint32_t usec, unsigned int flags)
-{
+int waitq_sleep_timeout_unsafe(waitq_t *wq, uint32_t usec, unsigned int flags, bool *blocked)
+{
+	*blocked = false;
+
 	/* Checks whether to go to sleep at all */
 	if (wq->missed_wakeups) {
 		wq->missed_wakeups--;
-		return ESYNCH_OK_ATOMIC;
+		return EOK;
 	} else {
 		if (PARAM_NON_BLOCKING(flags, usec)) {
 			/* Return immediately instead of going to sleep */
-			return ESYNCH_WOULD_BLOCK;
+			return EAGAIN;
 		}
 	}
@@ -392,6 +401,5 @@
 		if (THREAD->interrupted) {
 			irq_spinlock_unlock(&THREAD->lock, false);
-			irq_spinlock_unlock(&wq->lock, false);
-			return ESYNCH_INTERRUPTED;
+			return EINTR;
 		}
 		
@@ -405,5 +413,5 @@
 			THREAD->last_cycle = get_cycle();
 			irq_spinlock_unlock(&THREAD->lock, false);
-			return ESYNCH_INTERRUPTED;
+			return EINTR;
 		}
 	} else
@@ -416,5 +424,5 @@
 			THREAD->last_cycle = get_cycle();
 			irq_spinlock_unlock(&THREAD->lock, false);
-			return ESYNCH_TIMEOUT;
+			return ETIMEOUT;
 		}
 		
@@ -433,4 +441,9 @@
 	THREAD->sleep_queue = wq;
 	
+	/* Must be before entry to scheduler, because there are multiple
+	 * return vectors.
+	 */
+	*blocked = true;
+	
 	irq_spinlock_unlock(&THREAD->lock, false);
 	
@@ -438,5 +451,5 @@
 	scheduler();
 	
-	return ESYNCH_OK_BLOCKED;
+	return EOK;
 }
 
Index: kernel/generic/src/synch/workqueue.c
===================================================================
--- kernel/generic/src/synch/workqueue.c	(revision 89ea2dc48f26dfcd2aba2a270dac8523cec931c2)
+++ kernel/generic/src/synch/workqueue.c	(revision 4547f1115bd8270b9a1bcf3bb8d3e02111295371)
@@ -38,4 +38,5 @@
 
 #include <assert.h>
+#include <errno.h>
 #include <synch/workqueue.h>
 #include <synch/spinlock.h>
@@ -897,5 +898,5 @@
 			&info->lock, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_INTERRUPTIBLE);
 		
-		stop = (ret == ESYNCH_INTERRUPTED);
+		stop = (ret == EINTR);
 	}
 	
