Index: generic/src/synch/condvar.c
===================================================================
--- generic/src/synch/condvar.c	(revision 2be2786813403912eecf46db5825fb475817e48e)
+++ generic/src/synch/condvar.c	(revision 040542aa18c2031f9e751738ff84939e979b0d49)
@@ -36,8 +36,8 @@
 #include <synch/waitq.h>
 #include <synch/synch.h>
+#include <arch.h>
+#include <typedefs.h>
 
-/** Initialize condition variable
- *
- * Initialize condition variable.
+/** Initialize condition variable.
  *
  * @param cv Condition variable.
@@ -48,6 +48,5 @@
 }
 
-/** Signal the condition has become true
- *
+/**
  * Signal the condition has become true
  * to the first waiting thread by waking it up.
@@ -60,6 +59,5 @@
 }
 
-/** Signal the condition has become true
- *
+/**
  * Signal the condition has become true
  * to all waiting threads by waking them up.
@@ -72,7 +70,5 @@
 }
 
-/** Wait for the condition becoming true
- *
- * Wait for the condition becoming true.
+/** Wait for the condition becoming true.
  *
  * @param cv Condition variable.
@@ -89,8 +85,14 @@
 {
 	int rc;
+	ipl_t ipl;
 
+	ipl = waitq_sleep_prepare(&cv->wq);
 	mutex_unlock(mtx);
-	rc = waitq_sleep_timeout(&cv->wq, usec, trywait);
+	
+	rc = waitq_sleep_timeout_unsafe(&cv->wq, usec, trywait);
+
 	mutex_lock(mtx);
+	waitq_sleep_finish(&cv->wq, rc, ipl);
+
 	return rc;
 }
Index: generic/src/synch/waitq.c
===================================================================
--- generic/src/synch/waitq.c	(revision 2be2786813403912eecf46db5825fb475817e48e)
+++ generic/src/synch/waitq.c	(revision 040542aa18c2031f9e751738ff84939e979b0d49)
@@ -158,5 +158,4 @@
 }
 
-
 /** Sleep until either wakeup, timeout or interruption occurs
  *
@@ -164,5 +163,5 @@
  * interrupted from the sleep, restoring a failover context.
  *
- * Sleepers are organised in FIFO fashion in a structure called wait queue.
+ * Sleepers are organised in a FIFO fashion in a structure called wait queue.
  *
  * This function is really basic in that other functions as waitq_sleep()
@@ -201,10 +200,29 @@
 int waitq_sleep_timeout(waitq_t *wq, __u32 usec, int nonblocking)
 {
-	volatile ipl_t ipl; /* must be live after context_restore() */
-	
+	ipl_t ipl;
+	int rc;
+	
+	ipl = waitq_sleep_prepare(wq);
+	rc = waitq_sleep_timeout_unsafe(wq, usec, nonblocking);
+	waitq_sleep_finish(wq, rc, ipl);
+	return rc;
+}
+
+/** Prepare to sleep in a waitq.
+ *
+ * This function will return holding the lock of the wait queue
+ * and interrupts disabled.
+ *
+ * @param wq Wait queue.
+ *
+ * @return Interrupt level as it existed on entry to this function.
+ */
+ipl_t waitq_sleep_prepare(waitq_t *wq)
+{
+	ipl_t ipl;
 	
 restart:
 	ipl = interrupts_disable();
-	
+
 	/*
 	 * Busy waiting for a delayed timeout.
@@ -217,16 +235,53 @@
 	if (THREAD->timeout_pending) {
 		spinlock_unlock(&THREAD->lock);
-		interrupts_restore(ipl);		
+		interrupts_restore(ipl);
 		goto restart;
 	}
 	spinlock_unlock(&THREAD->lock);
-	
+													
 	spinlock_lock(&wq->lock);
-	
+	return ipl;
+}
+
+/** Finish waiting in a wait queue.
+ *
+ * This function restores interrupts to the state that existed prior
+ * to the call to waitq_sleep_prepare(). If necessary, the wait queue
+ * 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:
+		spinlock_unlock(&wq->lock);
+		break;
+	default:
+		break;
+	}
+	interrupts_restore(ipl);
+}
+
+/** Internal implementation of waitq_sleep_timeout().
+ *
+ * This function implements logic of sleeping in a wait queue.
+ * This call must be preceeded by a call to waitq_sleep_prepare()
+ * and followed by a call to waitq_slee_finish().
+ *
+ * @param wq See waitq_sleep_timeout().
+ * @param usec See waitq_sleep_timeout().
+ * @param nonblocking See waitq_sleep_timeout().
+ *
+ * @return See waitq_sleep_timeout().
+ */
+int waitq_sleep_timeout_unsafe(waitq_t *wq, __u32 usec, int nonblocking)
+{
 	/* checks whether to go to sleep at all */
 	if (wq->missed_wakeups) {
 		wq->missed_wakeups--;
-		spinlock_unlock(&wq->lock);
-		interrupts_restore(ipl);
 		return ESYNCH_OK_ATOMIC;
 	}
@@ -234,6 +289,4 @@
 		if (nonblocking && (usec == 0)) {
 			/* return immediatelly instead of going to sleep */
-			spinlock_unlock(&wq->lock);
-			interrupts_restore(ipl);
 			return ESYNCH_WOULD_BLOCK;
 		}
@@ -252,5 +305,4 @@
 		/* Short emulation of scheduler() return code. */
 		spinlock_unlock(&THREAD->lock);
-		interrupts_restore(ipl);
 		return ESYNCH_INTERRUPTED;
 	}
@@ -261,5 +313,4 @@
 			/* Short emulation of scheduler() return code. */
 			spinlock_unlock(&THREAD->lock);
-			interrupts_restore(ipl);
 			return ESYNCH_TIMEOUT;
 		}
@@ -279,5 +330,4 @@
 
 	scheduler(); 	/* wq->lock is released in scheduler_separated_stack() */
-	interrupts_restore(ipl);
 	
 	return ESYNCH_OK_BLOCKED;
