Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision c1b979a5a2332e971f29013cd230bf1a1c6f35d4)
+++ uspace/lib/c/generic/fibril_synch.c	(revision f303f2cf17466cfa96a47fb4cacbaa7484ec3e23)
@@ -448,5 +448,5 @@
 	int rc;
 
-	fibril_mutex_lock(&timer->lock);
+	fibril_mutex_lock(timer->lockp);
 
 	while (timer->state != fts_cleanup) {
@@ -454,14 +454,16 @@
 		case fts_not_set:
 		case fts_fired:
-			fibril_condvar_wait(&timer->cv, &timer->lock);
+			fibril_condvar_wait(&timer->cv, timer->lockp);
 			break;
 		case fts_active:
 			rc = fibril_condvar_wait_timeout(&timer->cv,
-			    &timer->lock, timer->delay);
+			    timer->lockp, timer->delay);
 			if (rc == ETIMEOUT && timer->state == fts_active) {
 				timer->state = fts_fired;
-				fibril_mutex_unlock(&timer->lock);
+				timer->handler_running = true;
+				fibril_mutex_unlock(timer->lockp);
 				timer->fun(timer->arg);
-				fibril_mutex_lock(&timer->lock);
+				fibril_mutex_lock(timer->lockp);
+				timer->handler_running = false;
 			}
 			break;
@@ -475,6 +477,6 @@
 	/* Acknowledge timer fibril has finished cleanup. */
 	timer->state = fts_clean;
-	fibril_condvar_broadcast(&timer->cv);
-	fibril_mutex_unlock(&timer->lock);
+	fibril_mutex_unlock(timer->lockp);
+	free(timer);
 
 	return 0;
@@ -485,5 +487,5 @@
  * @return		New timer on success, @c NULL if out of memory.
  */
-fibril_timer_t *fibril_timer_create(void)
+fibril_timer_t *fibril_timer_create(fibril_mutex_t *lock)
 {
 	fid_t fid;
@@ -505,7 +507,7 @@
 	timer->fibril = fid;
 	timer->state = fts_not_set;
+	timer->lockp = (lock != NULL) ? lock : &timer->lock;
 
 	fibril_add_ready(fid);
-
 	return timer;
 }
@@ -517,5 +519,5 @@
 void fibril_timer_destroy(fibril_timer_t *timer)
 {
-	fibril_mutex_lock(&timer->lock);
+	fibril_mutex_lock(timer->lockp);
 	assert(timer->state == fts_not_set || timer->state == fts_fired);
 
@@ -523,10 +525,5 @@
 	timer->state = fts_cleanup;
 	fibril_condvar_broadcast(&timer->cv);
-
-	/* Wait for timer fibril to acknowledge. */
-	while (timer->state != fts_clean)
-		fibril_condvar_wait(&timer->cv, &timer->lock);
-
-	fibril_mutex_unlock(&timer->lock);
+	fibril_mutex_unlock(timer->lockp);
 }
 
@@ -544,5 +541,23 @@
     fibril_timer_fun_t fun, void *arg)
 {
-	fibril_mutex_lock(&timer->lock);
+	fibril_mutex_lock(timer->lockp);
+	fibril_timer_set_locked(timer, delay, fun, arg);
+	fibril_mutex_unlock(timer->lockp);
+}
+
+/** Set locked timer.
+ *
+ * Set timer to execute a callback function after the specified
+ * interval. Must be called when the timer is locked.
+ *
+ * @param timer		Timer
+ * @param delay		Delay in microseconds
+ * @param fun		Callback function
+ * @param arg		Argument for @a fun
+ */
+void fibril_timer_set_locked(fibril_timer_t *timer, suseconds_t delay,
+    fibril_timer_fun_t fun, void *arg)
+{
+	assert(fibril_mutex_is_locked(timer->lockp));
 	assert(timer->state == fts_not_set || timer->state == fts_fired);
 	timer->state = fts_active;
@@ -551,5 +566,4 @@
 	timer->arg = arg;
 	fibril_condvar_broadcast(&timer->cv);
-	fibril_mutex_unlock(&timer->lock);
 }
 
@@ -569,5 +583,32 @@
 	fibril_timer_state_t old_state;
 
-	fibril_mutex_lock(&timer->lock);
+	fibril_mutex_lock(timer->lockp);
+	old_state = fibril_timer_clear_locked(timer);
+	fibril_mutex_unlock(timer->lockp);
+
+	return old_state;
+}
+
+/** Clear locked timer.
+ *
+ * Clears (cancels) timer and returns last state of the timer.
+ * This can be one of:
+ *    - fts_not_set	If the timer has not been set or has been cleared
+ *    - fts_active	Timer was set but did not fire
+ *    - fts_fired	Timer fired
+ * Must be called when the timer is locked.
+ *
+ * @param timer		Timer
+ * @return		Last timer state
+ */
+fibril_timer_state_t fibril_timer_clear_locked(fibril_timer_t *timer)
+{
+	fibril_timer_state_t old_state;
+
+	assert(fibril_mutex_is_locked(timer->lockp));
+
+	while (timer->handler_running)
+		fibril_condvar_wait(&timer->cv, timer->lockp);
+
 	old_state = timer->state;
 	timer->state = fts_not_set;
@@ -577,5 +618,4 @@
 	timer->arg = NULL;
 	fibril_condvar_broadcast(&timer->cv);
-	fibril_mutex_unlock(&timer->lock);
 
 	return old_state;
