Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
+++ uspace/lib/c/generic/async.c	(revision 3bd1b3ab5056db3b196fc9608179dfd2886d214b)
@@ -820,5 +820,5 @@
 	if (usecs) {
 		getuptime(&conn->wdata.to_event.expires);
-		tv_add(&conn->wdata.to_event.expires, usecs);
+		tv_add_diff(&conn->wdata.to_event.expires, usecs);
 	} else
 		conn->wdata.to_event.inlist = false;
@@ -1214,5 +1214,6 @@
 
 			} else {
-				timeout = tv_sub(&waiter->to_event.expires, &tv);
+				timeout = tv_sub_diff(&waiter->to_event.expires,
+				    &tv);
 				futex_up(&async_futex);
 			}
@@ -1505,5 +1506,5 @@
 
 	getuptime(&msg->wdata.to_event.expires);
-	tv_add(&msg->wdata.to_event.expires, timeout);
+	tv_add_diff(&msg->wdata.to_event.expires, timeout);
 	
 	/*
@@ -1587,5 +1588,5 @@
 	
 	getuptime(&msg->wdata.to_event.expires);
-	tv_add(&msg->wdata.to_event.expires, timeout);
+	tv_add_diff(&msg->wdata.to_event.expires, timeout);
 	
 	futex_down(&async_futex);
Index: uspace/lib/c/generic/fibril_synch.c
===================================================================
--- uspace/lib/c/generic/fibril_synch.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
+++ uspace/lib/c/generic/fibril_synch.c	(revision 3bd1b3ab5056db3b196fc9608179dfd2886d214b)
@@ -380,5 +380,5 @@
 	if (timeout) {
 		getuptime(&wdata.to_event.expires);
-		tv_add(&wdata.to_event.expires, timeout);
+		tv_add_diff(&wdata.to_event.expires, timeout);
 		async_insert_timeout(&wdata);
 	}
Index: uspace/lib/c/generic/io/console.c
===================================================================
--- uspace/lib/c/generic/io/console.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
+++ uspace/lib/c/generic/io/console.c	(revision 3bd1b3ab5056db3b196fc9608179dfd2886d214b)
@@ -259,5 +259,5 @@
 	struct timeval t1;
 	gettimeofday(&t1, NULL);
-	*timeout -= tv_sub(&t1, &t0);
+	*timeout -= tv_sub_diff(&t1, &t0);
 	
 	return true;
Index: uspace/lib/c/generic/io/window.c
===================================================================
--- uspace/lib/c/generic/io/window.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
+++ uspace/lib/c/generic/io/window.c	(revision 3bd1b3ab5056db3b196fc9608179dfd2886d214b)
@@ -40,8 +40,9 @@
 #include <stdio.h>
 
-int win_register(async_sess_t *sess, service_id_t *in, service_id_t *out)
+int win_register(async_sess_t *sess, window_flags_t flags, service_id_t *in,
+    service_id_t *out)
 {
 	async_exch_t *exch = async_exchange_begin(sess);
-	int ret = async_req_0_2(exch, WINDOW_REGISTER, in, out);
+	int ret = async_req_1_2(exch, WINDOW_REGISTER, flags, in, out);
 	async_exchange_end(exch);
 	
Index: uspace/lib/c/generic/time.c
===================================================================
--- uspace/lib/c/generic/time.c	(revision 053fc2bcb6fbea6b3e6edf10ca784c77402816d4)
+++ uspace/lib/c/generic/time.c	(revision 3bd1b3ab5056db3b196fc9608179dfd2886d214b)
@@ -59,4 +59,5 @@
 #define MINS_PER_HOUR  60
 #define SECS_PER_MIN   60
+#define USECS_PER_SEC  1000000
 #define MINS_PER_DAY   (MINS_PER_HOUR * HOURS_PER_DAY)
 #define SECS_PER_HOUR  (SECS_PER_MIN * MINS_PER_HOUR)
@@ -252,16 +253,17 @@
  * Optionally add specified amount of seconds.
  *
- * @param tm      Broken-down time to normalize.
- * @param sec_add Seconds to add.
+ * @param tm Broken-down time to normalize.
+ * @param tv Timeval to add.
  *
  * @return 0 on success, -1 on overflow
  *
  */
-static int normalize_time(struct tm *tm, time_t sec_add)
+static int normalize_tm_tv(struct tm *tm, const struct timeval *tv)
 {
 	// TODO: DST correction
 	
 	/* Set initial values. */
-	time_t sec = tm->tm_sec + sec_add;
+	time_t usec = tm->tm_usec + tv->tv_usec;
+	time_t sec = tm->tm_sec + tv->tv_sec;
 	time_t min = tm->tm_min;
 	time_t hour = tm->tm_hour;
@@ -271,4 +273,6 @@
 	
 	/* Adjust time. */
+	sec += floor_div(usec, USECS_PER_SEC);
+	usec = floor_mod(usec, USECS_PER_SEC);
 	min += floor_div(sec, SECS_PER_MIN);
 	sec = floor_mod(sec, SECS_PER_MIN);
@@ -319,4 +323,5 @@
 	
 	/* And put the values back to the struct. */
+	tm->tm_usec = (int) usec;
 	tm->tm_sec = (int) sec;
 	tm->tm_min = (int) min;
@@ -335,4 +340,15 @@
 }
 
+static int normalize_tm_time(struct tm *tm, time_t time)
+{
+	struct timeval tv = {
+		.tv_sec = time,
+		.tv_usec = 0
+	};
+
+	return normalize_tm_tv(tm, &tv);
+}
+
+
 /** Which day the week-based year starts on.
  *
@@ -442,4 +458,16 @@
 }
 
+static void tv_normalize(struct timeval *tv)
+{
+	while (tv->tv_usec > USECS_PER_SEC) {
+		tv->tv_sec++;
+		tv->tv_usec -= USECS_PER_SEC;
+	}
+	while (tv->tv_usec < 0) {
+		tv->tv_sec--;
+		tv->tv_usec += USECS_PER_SEC;
+	}
+}
+
 /** Add microseconds to given timeval.
  *
@@ -448,19 +476,27 @@
  *
  */
-void tv_add(struct timeval *tv, suseconds_t usecs)
-{
-	tv->tv_sec += usecs / 1000000;
-	tv->tv_usec += usecs % 1000000;
-	
-	if (tv->tv_usec > 1000000) {
-		tv->tv_sec++;
-		tv->tv_usec -= 1000000;
-	}
-}
-
-/** Subtract two timevals.
+void tv_add_diff(struct timeval *tv, suseconds_t usecs)
+{
+	tv->tv_sec += usecs / USECS_PER_SEC;
+	tv->tv_usec += usecs % USECS_PER_SEC;
+	tv_normalize(tv);
+}
+
+/** Add two timevals.
  *
  * @param tv1 First timeval.
  * @param tv2 Second timeval.
+ */
+void tv_add(struct timeval *tv1, struct timeval *tv2)
+{
+	tv1->tv_sec += tv2->tv_sec;
+	tv1->tv_usec += tv2->tv_usec;
+	tv_normalize(tv1);
+}
+
+/** Subtract two timevals.
+ *
+ * @param tv1 First timeval.
+ * @param tv2 Second timeval.
  *
  * @return Difference between tv1 and tv2 (tv1 - tv2) in
@@ -468,8 +504,21 @@
  *
  */
-suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2)
+suseconds_t tv_sub_diff(struct timeval *tv1, struct timeval *tv2)
 {
 	return (tv1->tv_usec - tv2->tv_usec) +
-	    ((tv1->tv_sec - tv2->tv_sec) * 1000000);
+	    ((tv1->tv_sec - tv2->tv_sec) * USECS_PER_SEC);
+}
+
+/** Subtract two timevals.
+ *
+ * @param tv1 First timeval.
+ * @param tv2 Second timeval.
+ *
+ */
+void tv_sub(struct timeval *tv1, struct timeval *tv2)
+{
+	tv1->tv_sec -= tv2->tv_sec;
+	tv1->tv_usec -= tv2->tv_usec;
+	tv_normalize(tv1);
 }
 
@@ -573,5 +622,5 @@
 		goto fallback;
 	
-	tv->tv_usec = 0;
+	tv->tv_usec = time.tm_usec;
 	tv->tv_sec = mktime(&time);
 	
@@ -689,5 +738,5 @@
 	// TODO: detect overflow
 	
-	normalize_time(tm, 0);
+	normalize_tm_time(tm, 0);
 	return secs_since_epoch(tm);
 }
@@ -944,4 +993,5 @@
 	
 	/* Set result to epoch. */
+	result->tm_usec = 0;
 	result->tm_sec = 0;
 	result->tm_min = 0;
@@ -951,5 +1001,5 @@
 	result->tm_year = 70; /* 1970 */
 	
-	if (normalize_time(result, time) == -1)
+	if (normalize_tm_time(result, time) == -1)
 		return EOVERFLOW;
 	
@@ -1014,5 +1064,5 @@
  * Time is expressed relative to the user's specified timezone.
  *
- * @param timer  Time to convert.
+ * @param tv     Timeval to convert.
  * @param result Structure to store the result to.
  *
@@ -1020,5 +1070,5 @@
  *
  */
-int time_local2tm(const time_t time, struct tm *restrict result)
+int time_tv2tm(const struct timeval *tv, struct tm *restrict result)
 {
 	// TODO: Deal with timezones.
@@ -1026,4 +1076,5 @@
 	
 	/* Set result to epoch. */
+	result->tm_usec = 0;
 	result->tm_sec = 0;
 	result->tm_min = 0;
@@ -1033,8 +1084,28 @@
 	result->tm_year = 70; /* 1970 */
 	
-	if (normalize_time(result, time) == -1)
+	if (normalize_tm_tv(result, tv) == -1)
 		return EOVERFLOW;
 	
 	return EOK;
+}
+
+/** Converts a time value to a broken-down local time.
+ *
+ * Time is expressed relative to the user's specified timezone.
+ *
+ * @param timer  Time to convert.
+ * @param result Structure to store the result to.
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int time_local2tm(const time_t time, struct tm *restrict result)
+{
+	struct timeval tv = {
+		.tv_sec = time,
+		.tv_usec = 0
+	};
+
+	return time_tv2tm(&tv, result);
 }
 
