Index: uspace/lib/c/Makefile
===================================================================
--- uspace/lib/c/Makefile	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/Makefile	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -68,5 +68,7 @@
 	generic/clipboard.c \
 	generic/devmap.c \
+	generic/devmap_obsolete.c \
 	generic/devman.c \
+	generic/devman_obsolete.c \
 	generic/device/hw_res.c \
 	generic/device/char_dev.c \
@@ -96,10 +98,11 @@
 	generic/io/console.c \
 	generic/io/screenbuffer.c \
-	generic/ipc/ns.c \
 	generic/malloc.c \
 	generic/sysinfo.c \
 	generic/ipc.c \
+	generic/ns.c \
+	generic/ns_obsolete.c \
 	generic/async.c \
-	generic/async_sess.c \
+	generic/async_obsolete.c \
 	generic/loader.c \
 	generic/getopt.c \
@@ -129,5 +132,5 @@
 	generic/assert.c
 
-ifeq ($(CONFIG_RTLD), y)
+ifeq ($(CONFIG_RTLD),y)
 	GENERIC_SOURCES += \
 		generic/dlfcn.c \
Index: uspace/lib/c/generic/adt/measured_strings.c
===================================================================
--- uspace/lib/c/generic/adt/measured_strings.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/adt/measured_strings.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -42,4 +42,5 @@
 #include <errno.h>
 #include <async.h>
+#include <async_obsolete.h>
 
 /** Creates a new measured string bundled with a copy of the given string
@@ -326,5 +327,5 @@
 		return ENOMEM;
 
-	rc = async_data_read_start(phone, lengths,
+	rc = async_obsolete_data_read_start(phone, lengths,
 	    sizeof(size_t) * (count + 1));
 	if (rc != EOK) {
@@ -351,5 +352,5 @@
 		(*strings)[index].length = lengths[index];
 		if (lengths[index] > 0) {
-			rc = async_data_read_start(phone, next, lengths[index]);
+			rc = async_obsolete_data_read_start(phone, next, lengths[index]);
 			if (rc != EOK) {
 			    	free(lengths);
@@ -399,5 +400,5 @@
 		return ENOMEM;
 
-	rc = async_data_write_start(phone, lengths,
+	rc = async_obsolete_data_write_start(phone, lengths,
 	    sizeof(size_t) * (count + 1));
 	if (rc != EOK) {
@@ -410,5 +411,5 @@
 	for (index = 0; index < count; index++) {
 		if (strings[index].length > 0) {
-			rc = async_data_write_start(phone, strings[index].value,
+			rc = async_obsolete_data_write_start(phone, strings[index].value,
 			    strings[index].length);
 			if (rc != EOK)
Index: uspace/lib/c/generic/async.c
===================================================================
--- uspace/lib/c/generic/async.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/async.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -40,6 +40,7 @@
  * programming.
  *
- * You should be able to write very simple multithreaded programs, the async
- * framework will automatically take care of most synchronization problems.
+ * You should be able to write very simple multithreaded programs. The async
+ * framework will automatically take care of most of the synchronization
+ * problems.
  *
  * Example of use (pseudo C):
@@ -53,7 +54,14 @@
  *   int fibril1(void *arg)
  *   {
- *     conn = async_connect_me_to();
- *     c1 = async_send(conn);
- *     c2 = async_send(conn);
+ *     conn = async_connect_me_to(...);
+ *
+ *     exch = async_exchange_begin(conn);
+ *     c1 = async_send(exch);
+ *     async_exchange_end(exch);
+ *
+ *     exch = async_exchange_begin(conn);
+ *     c2 = async_send(exch);
+ *     async_exchange_end(exch);
+ *
  *     async_wait_for(c1);
  *     async_wait_for(c2);
@@ -94,5 +102,4 @@
 #include <futex.h>
 #include <fibril.h>
-#include <stdio.h>
 #include <adt/hash_table.h>
 #include <adt/list.h>
@@ -102,8 +109,13 @@
 #include <arch/barrier.h>
 #include <bool.h>
+#include <malloc.h>
+#include <mem.h>
 #include <stdlib.h>
-#include <malloc.h>
 #include "private/async.h"
 
+#define CLIENT_HASH_TABLE_BUCKETS  32
+#define CONN_HASH_TABLE_BUCKETS    32
+
+/** Async framework global futex */
 atomic_t async_futex = FUTEX_INITIALIZER;
 
@@ -111,33 +123,25 @@
 atomic_t threads_in_ipc_wait = { 0 };
 
-typedef struct {
-	awaiter_t wdata;
-	
-	/** If reply was received. */
-	bool done;
-	
-	/** Pointer to where the answer data is stored. */
-	ipc_call_t *dataptr;
-	
-	sysarg_t retval;
-} amsg_t;
-
-/**
- * Structures of this type are used to group information about
- * a call and about a message queue link.
- */
+/** Naming service session */
+async_sess_t *session_ns;
+
+/** Call data */
 typedef struct {
 	link_t link;
+	
 	ipc_callid_t callid;
 	ipc_call_t call;
 } msg_t;
 
+/* Client connection data */
 typedef struct {
+	link_t link;
+	
 	sysarg_t in_task_hash;
-	link_t link;
-	int refcnt;
+	atomic_t refcnt;
 	void *data;
 } client_t;
 
+/* Server connection data */
 typedef struct {
 	awaiter_t wdata;
@@ -148,4 +152,5 @@
 	/** Incoming client task hash. */
 	sysarg_t in_task_hash;
+	
 	/** Incoming phone hash. */
 	sysarg_t in_phone_hash;
@@ -170,5 +175,5 @@
 
 /** Identifier of the incoming connection handled by the current fibril. */
-static fibril_local connection_t *FIBRIL_connection;
+static fibril_local connection_t *fibril_connection;
 
 static void *default_client_data_constructor(void)
@@ -196,8 +201,8 @@
 }
 
-void *async_client_data_get(void)
-{
-	assert(FIBRIL_connection);
-	return FIBRIL_connection->client->data;
+void *async_get_client_data(void)
+{
+	assert(fibril_connection);
+	return fibril_connection->client->data;
 }
 
@@ -215,9 +220,4 @@
 }
 
-/**
- * Pointer to a fibril function that will be used to handle connections.
- */
-static async_client_conn_t client_connection = default_client_connection;
-
 /** Default fibril function that gets called to handle interrupt notifications.
  *
@@ -232,9 +232,41 @@
 }
 
-/**
- * Pointer to a fibril function that will be used to handle interrupt
- * notifications.
- */
+static async_client_conn_t client_connection = default_client_connection;
 static async_client_conn_t interrupt_received = default_interrupt_received;
+
+/** Setter for client_connection function pointer.
+ *
+ * @param conn Function that will implement a new connection fibril.
+ *
+ */
+void async_set_client_connection(async_client_conn_t conn)
+{
+	client_connection = conn;
+}
+
+/** Setter for interrupt_received function pointer.
+ *
+ * @param intr Function that will implement a new interrupt
+ *             notification fibril.
+ */
+void async_set_interrupt_received(async_client_conn_t intr)
+{
+	interrupt_received = intr;
+}
+
+/** Mutex protecting inactive_exch_list and avail_phone_cv.
+ *
+ */
+static FIBRIL_MUTEX_INITIALIZE(async_sess_mutex);
+
+/** List of all currently inactive exchanges.
+ *
+ */
+static LIST_INITIALIZE(inactive_exch_list);
+
+/** Condition variable to wait for a phone to become available.
+ *
+ */
+static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);
 
 static hash_table_t client_hash_table;
@@ -242,10 +274,8 @@
 static LIST_INITIALIZE(timeout_list);
 
-#define CLIENT_HASH_TABLE_BUCKETS  32
-#define CONN_HASH_TABLE_BUCKETS    32
-
 static hash_index_t client_hash(unsigned long key[])
 {
 	assert(key);
+	
 	return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
 }
@@ -253,4 +283,7 @@
 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
 {
+	assert(key);
+	assert(item);
+	
 	client_t *client = hash_table_get_instance(item, client_t, link);
 	return (key[0] == client->in_task_hash);
@@ -278,4 +311,5 @@
 {
 	assert(key);
+	
 	return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
 }
@@ -292,4 +326,7 @@
 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
 {
+	assert(key);
+	assert(item);
+	
 	connection_t *conn = hash_table_get_instance(item, connection_t, link);
 	return (key[0] == conn->in_phone_hash);
@@ -314,4 +351,6 @@
 void async_insert_timeout(awaiter_t *wd)
 {
+	assert(wd);
+	
 	wd->to_event.occurred = false;
 	wd->to_event.inlist = true;
@@ -346,4 +385,6 @@
 static bool route_call(ipc_callid_t callid, ipc_call_t *call)
 {
+	assert(call);
+	
 	futex_down(&async_futex);
 	
@@ -400,4 +441,6 @@
 static int notification_fibril(void *arg)
 {
+	assert(arg);
+	
 	msg_t *msg = (msg_t *) arg;
 	interrupt_received(msg->callid, &msg->call);
@@ -420,4 +463,6 @@
 static bool process_notification(ipc_callid_t callid, ipc_call_t *call)
 {
+	assert(call);
+	
 	futex_down(&async_futex);
 	
@@ -458,13 +503,14 @@
 ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
 {
-	assert(FIBRIL_connection);
+	assert(call);
+	assert(fibril_connection);
 	
 	/* Why doing this?
-	 * GCC 4.1.0 coughs on FIBRIL_connection-> dereference.
+	 * GCC 4.1.0 coughs on fibril_connection-> dereference.
 	 * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot.
 	 *           I would never expect to find so many errors in
 	 *           a compiler.
 	 */
-	connection_t *conn = FIBRIL_connection;
+	connection_t *conn = fibril_connection;
 	
 	futex_down(&async_futex);
@@ -541,8 +587,10 @@
 static int connection_fibril(void *arg)
 {
+	assert(arg);
+	
 	/*
 	 * Setup fibril-local connection pointer.
 	 */
-	FIBRIL_connection = (connection_t *) arg;
+	fibril_connection = (connection_t *) arg;
 	
 	futex_down(&async_futex);
@@ -554,5 +602,5 @@
 	 */
 	
-	unsigned long key = FIBRIL_connection->in_task_hash;
+	unsigned long key = fibril_connection->in_task_hash;
 	link_t *lnk = hash_table_find(&client_hash_table, &key);
 	
@@ -561,20 +609,17 @@
 	if (lnk) {
 		client = hash_table_get_instance(lnk, client_t, link);
-		client->refcnt++;
+		atomic_inc(&client->refcnt);
 	} else {
 		client = malloc(sizeof(client_t));
 		if (!client) {
-			ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
+			ipc_answer_0(fibril_connection->callid, ENOMEM);
 			futex_up(&async_futex);
 			return 0;
 		}
 		
-		client->in_task_hash = FIBRIL_connection->in_task_hash;
-		
-		async_serialize_start();
+		client->in_task_hash = fibril_connection->in_task_hash;
 		client->data = async_client_data_create();
-		async_serialize_end();
-		
-		client->refcnt = 1;
+		
+		atomic_set(&client->refcnt, 1);
 		hash_table_insert(&client_hash_table, &key, &client->link);
 	}
@@ -582,11 +627,11 @@
 	futex_up(&async_futex);
 	
-	FIBRIL_connection->client = client;
+	fibril_connection->client = client;
 	
 	/*
 	 * Call the connection handler function.
 	 */
-	FIBRIL_connection->cfibril(FIBRIL_connection->callid,
-	    &FIBRIL_connection->call);
+	fibril_connection->cfibril(fibril_connection->callid,
+	    &fibril_connection->call);
 	
 	/*
@@ -597,5 +642,5 @@
 	futex_down(&async_futex);
 	
-	if (--client->refcnt == 0) {
+	if (atomic_predec(&client->refcnt) == 0) {
 		hash_table_remove(&client_hash_table, &key, 1);
 		destroy = true;
@@ -616,5 +661,5 @@
 	 */
 	futex_down(&async_futex);
-	key = FIBRIL_connection->in_phone_hash;
+	key = fibril_connection->in_phone_hash;
 	hash_table_remove(&conn_hash_table, &key, 1);
 	futex_up(&async_futex);
@@ -623,7 +668,7 @@
 	 * Answer all remaining messages with EHANGUP.
 	 */
-	while (!list_empty(&FIBRIL_connection->msg_queue)) {
+	while (!list_empty(&fibril_connection->msg_queue)) {
 		msg_t *msg =
-		    list_get_instance(FIBRIL_connection->msg_queue.next, msg_t,
+		    list_get_instance(fibril_connection->msg_queue.next, msg_t,
 		    link);
 		
@@ -637,8 +682,8 @@
 	 * i.e. IPC_M_PHONE_HUNGUP.
 	 */
-	if (FIBRIL_connection->close_callid)
-		ipc_answer_0(FIBRIL_connection->close_callid, EOK);
-	
-	free(FIBRIL_connection);
+	if (fibril_connection->close_callid)
+		ipc_answer_0(fibril_connection->close_callid, EOK);
+	
+	free(fibril_connection);
 	return 0;
 }
@@ -646,5 +691,5 @@
 /** Create a new fibril for a new connection.
  *
- * Create new fibril for connection, fill in connection structures and inserts
+ * Create new fibril for connection, fill in connection structures and insert
  * it into the hash table, so that later we can easily do routing of messages to
  * particular fibrils.
@@ -665,5 +710,5 @@
 fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash,
     ipc_callid_t callid, ipc_call_t *call,
-    void (*cfibril)(ipc_callid_t, ipc_call_t *))
+    async_client_conn_t cfibril)
 {
 	connection_t *conn = malloc(sizeof(*conn));
@@ -721,4 +766,6 @@
 static void handle_call(ipc_callid_t callid, ipc_call_t *call)
 {
+	assert(call);
+	
 	/* Unrouted call - take some default action */
 	if ((callid & IPC_CALLID_NOTIFICATION)) {
@@ -878,11 +925,25 @@
 void __async_init(void)
 {
-	if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,
-	    &client_hash_table_ops))
+	if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS,
+	    1, &client_hash_table_ops))
 		abort();
 	
-	if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1,
-	    &conn_hash_table_ops))
+	if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS,
+	    1, &conn_hash_table_ops))
 		abort();
+	
+	session_ns = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (session_ns == NULL)
+		abort();
+	
+	session_ns->mgmt = EXCHANGE_ATOMIC;
+	session_ns->phone = PHONE_NS;
+	session_ns->arg1 = 0;
+	session_ns->arg2 = 0;
+	session_ns->arg3 = 0;
+	
+	list_initialize(&session_ns->exch_list);
+	fibril_mutex_initialize(&session_ns->mutex);
+	atomic_set(&session_ns->refcnt, 0);
 }
 
@@ -899,6 +960,8 @@
  *
  */
-static void reply_received(void *arg, int retval, ipc_call_t *data)
-{
+void reply_received(void *arg, int retval, ipc_call_t *data)
+{
+	assert(arg);
+	
 	futex_down(&async_futex);
 	
@@ -930,6 +993,6 @@
  * completion.
  *
- * @param phoneid Handle of the phone that will be used for the send.
- * @param method  Service-defined method.
+ * @param exch    Exchange for sending the message.
+ * @param imethod Service-defined interface and method.
  * @param arg1    Service-defined payload argument.
  * @param arg2    Service-defined payload argument.
@@ -942,10 +1005,12 @@
  *
  */
-aid_t async_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+aid_t async_send_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
 {
+	if (exch == NULL)
+		return 0;
+	
 	amsg_t *msg = malloc(sizeof(amsg_t));
-	
-	if (!msg)
+	if (msg == NULL)
 		return 0;
 	
@@ -961,5 +1026,5 @@
 	msg->wdata.active = true;
 	
-	ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg,
+	ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, msg,
 	    reply_received, true);
 	
@@ -972,6 +1037,6 @@
  * completion.
  *
- * @param phoneid Handle of the phone that will be used for the send.
- * @param method  Service-defined method.
+ * @param exch    Exchange for sending the message.
+ * @param imethod Service-defined interface and method.
  * @param arg1    Service-defined payload argument.
  * @param arg2    Service-defined payload argument.
@@ -985,11 +1050,14 @@
  *
  */
-aid_t async_send_slow(int phoneid, sysarg_t method, sysarg_t arg1,
+aid_t async_send_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
     ipc_call_t *dataptr)
 {
+	if (exch == NULL)
+		return 0;
+	
 	amsg_t *msg = malloc(sizeof(amsg_t));
 	
-	if (!msg)
+	if (msg == NULL)
 		return 0;
 	
@@ -1005,6 +1073,6 @@
 	msg->wdata.active = true;
 	
-	ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,
-	    reply_received, true);
+	ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, arg5,
+	    msg, reply_received, true);
 	
 	return (aid_t) msg;
@@ -1020,4 +1088,6 @@
 void async_wait_for(aid_t amsgid, sysarg_t *retval)
 {
+	assert(amsgid);
+	
 	amsg_t *msg = (amsg_t *) amsgid;
 	
@@ -1056,4 +1126,6 @@
 int async_wait_timeout(aid_t amsgid, sysarg_t *retval, suseconds_t timeout)
 {
+	assert(amsgid);
+	
 	amsg_t *msg = (amsg_t *) amsgid;
 	
@@ -1124,24 +1196,4 @@
 }
 
-/** Setter for client_connection function pointer.
- *
- * @param conn Function that will implement a new connection fibril.
- *
- */
-void async_set_client_connection(async_client_conn_t conn)
-{
-	client_connection = conn;
-}
-
-/** Setter for interrupt_received function pointer.
- *
- * @param intr Function that will implement a new interrupt
- *             notification fibril.
- */
-void async_set_interrupt_received(async_client_conn_t intr)
-{
-	interrupt_received = intr;
-}
-
 /** Pseudo-synchronous message sending - fast version.
  *
@@ -1151,6 +1203,6 @@
  * transferring more arguments, see the slower async_req_slow().
  *
- * @param phoneid Hash of the phone through which to make the call.
- * @param method  Method of the call.
+ * @param exch    Exchange for sending the message.
+ * @param imethod Interface and method of the call.
  * @param arg1    Service-defined payload argument.
  * @param arg2    Service-defined payload argument.
@@ -1166,14 +1218,17 @@
  *
  */
-sysarg_t async_req_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+sysarg_t async_req_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
     sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
 {
+	if (exch == NULL)
+		return ENOENT;
+	
 	ipc_call_t result;
-	aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4,
+	aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4,
 	    &result);
 	
 	sysarg_t rc;
-	async_wait_for(eid, &rc);
+	async_wait_for(aid, &rc);
 	
 	if (r1)
@@ -1199,6 +1254,6 @@
  * Send message asynchronously and return only after the reply arrives.
  *
- * @param phoneid Hash of the phone through which to make the call.
- * @param method  Method of the call.
+ * @param exch    Exchange for sending the message.
+ * @param imethod Interface and method of the call.
  * @param arg1    Service-defined payload argument.
  * @param arg2    Service-defined payload argument.
@@ -1215,14 +1270,17 @@
  *
  */
-sysarg_t async_req_slow(int phoneid, sysarg_t method, sysarg_t arg1,
+sysarg_t async_req_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
     sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
 {
+	if (exch == NULL)
+		return ENOENT;
+	
 	ipc_call_t result;
-	aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5,
+	aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5,
 	    &result);
 	
 	sysarg_t rc;
-	async_wait_for(eid, &rc);
+	async_wait_for(aid, &rc);
 	
 	if (r1)
@@ -1244,37 +1302,46 @@
 }
 
-void async_msg_0(int phone, sysarg_t imethod)
-{
-	ipc_call_async_0(phone, imethod, NULL, NULL, true);
-}
-
-void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1)
-{
-	ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true);
-}
-
-void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2)
-{
-	ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true);
-}
-
-void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3)
-{
-	ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true);
-}
-
-void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3, sysarg_t arg4)
-{
-	ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL,
-	    true);
-}
-
-void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
-{
-	ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL,
-	    NULL, true);
+void async_msg_0(async_exch_t *exch, sysarg_t imethod)
+{
+	if (exch != NULL)
+		ipc_call_async_0(exch->phone, imethod, NULL, NULL, true);
+}
+
+void async_msg_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1)
+{
+	if (exch != NULL)
+		ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL, true);
+}
+
+void async_msg_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
+    sysarg_t arg2)
+{
+	if (exch != NULL)
+		ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL,
+		    true);
+}
+
+void async_msg_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3)
+{
+	if (exch != NULL)
+		ipc_call_async_3(exch->phone, imethod, arg1, arg2, arg3, NULL,
+		    NULL, true);
+}
+
+void async_msg_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
+{
+	if (exch != NULL)
+		ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4,
+		    NULL, NULL, true);
+}
+
+void async_msg_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
+{
+	if (exch != NULL)
+		ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4,
+		    arg5, NULL, NULL, true);
 }
 
@@ -1313,16 +1380,22 @@
 }
 
-int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
-    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
-{
-	return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode);
-}
-
-int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
-    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
-    unsigned int mode)
-{
-	return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4,
-	    arg5, mode);
+int async_forward_fast(ipc_callid_t callid, async_exch_t *exch,
+    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
+	return ipc_forward_fast(callid, exch->phone, imethod, arg1, arg2, mode);
+}
+
+int async_forward_slow(ipc_callid_t callid, async_exch_t *exch,
+    sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
+    sysarg_t arg4, sysarg_t arg5, unsigned int mode)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
+	return ipc_forward_slow(callid, exch->phone, imethod, arg1, arg2, arg3,
+	    arg4, arg5, mode);
 }
 
@@ -1331,5 +1404,5 @@
  * Ask through phone for a new connection to some service.
  *
- * @param phone           Phone handle used for contacting the other side.
+ * @param exch            Exchange for sending the message.
  * @param arg1            User defined argument.
  * @param arg2            User defined argument.
@@ -1337,13 +1410,16 @@
  * @param client_receiver Connection handing routine.
  *
- * @return New phone handle on success or a negative error code.
- *
- */
-int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2,
+ * @return Zero on success or a negative error code.
+ *
+ */
+int async_connect_to_me(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,
     sysarg_t arg3, async_client_conn_t client_receiver)
 {
+	if (exch == NULL)
+		return ENOENT;
+	
 	sysarg_t task_hash;
 	sysarg_t phone_hash;
-	int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
+	int rc = async_req_3_5(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
 	    NULL, NULL, NULL, &task_hash, &phone_hash);
 	if (rc != EOK)
@@ -1357,27 +1433,159 @@
 }
 
-/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
- *
- * Ask through phone for a new connection to some service.
- *
- * @param phone Phone handle used for contacting the other side.
- * @param arg1  User defined argument.
- * @param arg2  User defined argument.
- * @param arg3  User defined argument.
- *
- * @return New phone handle on success or a negative error code.
- *
- */
-int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3)
-{
-	sysarg_t newphid;
-	int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
-	    NULL, NULL, NULL, NULL, &newphid);
+/** Wrapper for making IPC_M_CONNECT_ME calls using the async framework.
+ *
+ * Ask through for a cloned connection to some service.
+ *
+ * @param mgmt Exchange management style.
+ * @param exch Exchange for sending the message.
+ *
+ * @return New session on success or NULL on error.
+ *
+ */
+async_sess_t *async_connect_me(exch_mgmt_t mgmt, async_exch_t *exch)
+{
+	if (exch == NULL) {
+		errno = ENOENT;
+		return NULL;
+	}
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	ipc_call_t result;
+	
+	amsg_t *msg = malloc(sizeof(amsg_t));
+	if (msg == NULL) {
+		free(sess);
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	msg->done = false;
+	msg->dataptr = &result;
+	
+	msg->wdata.to_event.inlist = false;
+	
+	/*
+	 * We may sleep in the next method,
+	 * but it will use its own means
+	 */
+	msg->wdata.active = true;
+	
+	ipc_call_async_0(exch->phone, IPC_M_CONNECT_ME, msg,
+	    reply_received, true);
+	
+	sysarg_t rc;
+	async_wait_for((aid_t) msg, &rc);
+	
+	if (rc != EOK) {
+		errno = rc;
+		free(sess);
+		return NULL;
+	}
+	
+	int phone = (int) IPC_GET_ARG5(result);
+	
+	if (phone < 0) {
+		errno = phone;
+		free(sess);
+		return NULL;
+	}
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = 0;
+	sess->arg2 = 0;
+	sess->arg3 = 0;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	return sess;
+}
+
+static int async_connect_me_to_internal(int phone, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, sysarg_t arg4)
+{
+	ipc_call_t result;
+	
+	amsg_t *msg = malloc(sizeof(amsg_t));
+	if (msg == NULL)
+		return ENOENT;
+	
+	msg->done = false;
+	msg->dataptr = &result;
+	
+	msg->wdata.to_event.inlist = false;
+	
+	/*
+	 * We may sleep in the next method,
+	 * but it will use its own means
+	 */
+	msg->wdata.active = true;
+	
+	ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, arg4,
+	    msg, reply_received, true);
+	
+	sysarg_t rc;
+	async_wait_for((aid_t) msg, &rc);
 	
 	if (rc != EOK)
 		return rc;
 	
-	return newphid;
+	return (int) IPC_GET_ARG5(result);
+}
+
+/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
+ *
+ * Ask through for a new connection to some service.
+ *
+ * @param mgmt Exchange management style.
+ * @param exch Exchange for sending the message.
+ * @param arg1 User defined argument.
+ * @param arg2 User defined argument.
+ * @param arg3 User defined argument.
+ *
+ * @return New session on success or NULL on error.
+ *
+ */
+async_sess_t *async_connect_me_to(exch_mgmt_t mgmt, async_exch_t *exch,
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
+{
+	if (exch == NULL) {
+		errno = ENOENT;
+		return NULL;
+	}
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
+	    0);
+	
+	if (phone < 0) {
+		errno = phone;
+		free(sess);
+		return NULL;
+	}
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = arg1;
+	sess->arg2 = arg2;
+	sess->arg3 = arg3;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	return sess;
 }
 
@@ -1387,23 +1595,47 @@
  * success.
  *
- * @param phoneid Phone handle used for contacting the other side.
- * @param arg1    User defined argument.
- * @param arg2    User defined argument.
- * @param arg3    User defined argument.
- *
- * @return New phone handle on success or a negative error code.
- *
- */
-int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
-    sysarg_t arg3)
-{
-	sysarg_t newphid;
-	int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
-	    IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
-	
-	if (rc != EOK)
-		return rc;
-	
-	return newphid;
+ * @param mgmt Exchange management style.
+ * @param exch Exchange for sending the message.
+ * @param arg1 User defined argument.
+ * @param arg2 User defined argument.
+ * @param arg3 User defined argument.
+ *
+ * @return New session on success or NULL on error.
+ *
+ */
+async_sess_t *async_connect_me_to_blocking(exch_mgmt_t mgmt, async_exch_t *exch,
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
+{
+	if (exch == NULL) {
+		errno = ENOENT;
+		return NULL;
+	}
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,
+	    IPC_FLAG_BLOCKING);
+	
+	if (phone < 0) {
+		errno = phone;
+		free(sess);
+		return NULL;
+	}
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = arg1;
+	sess->arg2 = arg2;
+	sess->arg3 = arg3;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	return sess;
 }
 
@@ -1411,19 +1643,56 @@
  *
  */
-int async_connect_kbox(task_id_t id)
-{
-	return ipc_connect_kbox(id);
+async_sess_t *async_connect_kbox(task_id_t id)
+{
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	
+	int phone = ipc_connect_kbox(id);
+	if (phone < 0) {
+		errno = phone;
+		free(sess);
+		return NULL;
+	}
+	
+	sess->mgmt = EXCHANGE_ATOMIC;
+	sess->phone = phone;
+	sess->arg1 = 0;
+	sess->arg2 = 0;
+	sess->arg3 = 0;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	return sess;
+}
+
+static int async_hangup_internal(int phone)
+{
+	return ipc_hangup(phone);
 }
 
 /** Wrapper for ipc_hangup.
  *
- * @param phone Phone handle to hung up.
+ * @param sess Session to hung up.
  *
  * @return Zero on success or a negative error code.
  *
  */
-int async_hangup(int phone)
-{
-	return ipc_hangup(phone);
+int async_hangup(async_sess_t *sess)
+{
+	assert(sess);
+	
+	if (atomic_get(&sess->refcnt) > 0)
+		return EBUSY;
+	
+	int rc = async_hangup_internal(sess->phone);
+	if (rc == EOK)
+		free(sess);
+	
+	return rc;
 }
 
@@ -1434,20 +1703,140 @@
 }
 
+/** Start new exchange in a session.
+ *
+ * @param session Session.
+ *
+ * @return New exchange or NULL on error.
+ *
+ */
+async_exch_t *async_exchange_begin(async_sess_t *sess)
+{
+	if (sess == NULL)
+		return NULL;
+	
+	async_exch_t *exch;
+	
+	fibril_mutex_lock(&async_sess_mutex);
+	
+	if (!list_empty(&sess->exch_list)) {
+		/*
+		 * There are inactive exchanges in the session.
+		 */
+		exch = (async_exch_t *)
+		    list_get_instance(sess->exch_list.next, async_exch_t, sess_link);
+		list_remove(&exch->sess_link);
+		list_remove(&exch->global_link);
+	} else {
+		/*
+		 * There are no available exchanges in the session.
+		 */
+		
+		if ((sess->mgmt == EXCHANGE_ATOMIC) ||
+		    (sess->mgmt == EXCHANGE_SERIALIZE)) {
+			exch = (async_exch_t *) malloc(sizeof(async_exch_t));
+			if (exch != NULL) {
+				list_initialize(&exch->sess_link);
+				list_initialize(&exch->global_link);
+				exch->sess = sess;
+				exch->phone = sess->phone;
+			}
+		} else {  /* EXCHANGE_PARALLEL */
+			/*
+			 * Make a one-time attempt to connect a new data phone.
+			 */
+			
+			int phone;
+			
+retry:
+			phone = async_connect_me_to_internal(sess->phone, sess->arg1,
+			    sess->arg2, sess->arg3, 0);
+			if (phone >= 0) {
+				exch = (async_exch_t *) malloc(sizeof(async_exch_t));
+				if (exch != NULL) {
+					list_initialize(&exch->sess_link);
+					list_initialize(&exch->global_link);
+					exch->sess = sess;
+					exch->phone = phone;
+				} else
+					async_hangup_internal(phone);
+			} else if (!list_empty(&inactive_exch_list)) {
+				/*
+				 * We did not manage to connect a new phone. But we
+				 * can try to close some of the currently inactive
+				 * connections in other sessions and try again.
+				 */
+				exch = (async_exch_t *)
+				    list_get_instance(inactive_exch_list.next, async_exch_t,
+				    global_link);
+				list_remove(&exch->sess_link);
+				list_remove(&exch->global_link);
+				async_hangup_internal(exch->phone);
+				free(exch);
+				goto retry;
+			} else {
+				/*
+				 * Wait for a phone to become available.
+				 */
+				fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex);
+				goto retry;
+			}
+		}
+	}
+	
+	fibril_mutex_unlock(&async_sess_mutex);
+	
+	if (exch != NULL) {
+		atomic_inc(&sess->refcnt);
+		
+		if (sess->mgmt == EXCHANGE_SERIALIZE)
+			fibril_mutex_lock(&sess->mutex);
+	}
+	
+	return exch;
+}
+
+/** Finish an exchange.
+ *
+ * @param exch Exchange to finish.
+ *
+ */
+void async_exchange_end(async_exch_t *exch)
+{
+	if (exch == NULL)
+		return;
+	
+	async_sess_t *sess = exch->sess;
+	
+	if (sess->mgmt == EXCHANGE_SERIALIZE)
+		fibril_mutex_unlock(&sess->mutex);
+	
+	fibril_mutex_lock(&async_sess_mutex);
+	
+	list_append(&exch->sess_link, &sess->exch_list);
+	list_append(&exch->global_link, &inactive_exch_list);
+	fibril_condvar_signal(&avail_phone_cv);
+	
+	fibril_mutex_unlock(&async_sess_mutex);
+}
+
 /** Wrapper for IPC_M_SHARE_IN calls using the async framework.
  *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param dst     Destination address space area base.
- * @param size    Size of the destination address space area.
- * @param arg     User defined argument.
- * @param flags   Storage for the received flags. Can be NULL.
+ * @param exch  Exchange for sending the message.
+ * @param dst   Destination address space area base.
+ * @param size  Size of the destination address space area.
+ * @param arg   User defined argument.
+ * @param flags Storage for the received flags. Can be NULL.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
-    unsigned int *flags)
-{
+int async_share_in_start(async_exch_t *exch, void *dst, size_t size,
+    sysarg_t arg, unsigned int *flags)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
 	sysarg_t tmp_flags;
-	int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
+	int res = async_req_3_2(exch, IPC_M_SHARE_IN, (sysarg_t) dst,
 	    (sysarg_t) size, arg, NULL, &tmp_flags);
 	
@@ -1507,14 +1896,17 @@
 /** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
  *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param src     Source address space area base address.
- * @param flags   Flags to be used for sharing. Bits can be only cleared.
+ * @param exch  Exchange for sending the message.
+ * @param src   Source address space area base address.
+ * @param flags Flags to be used for sharing. Bits can be only cleared.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int async_share_out_start(int phoneid, void *src, unsigned int flags)
-{
-	return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
+int async_share_out_start(async_exch_t *exch, void *src, unsigned int flags)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
+	return async_req_3_0(exch, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
 	    (sysarg_t) flags);
 }
@@ -1571,13 +1963,16 @@
 /** Start IPC_M_DATA_READ using the async framework.
  *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param dst Address of the beginning of the destination buffer.
- * @param size Size of the destination buffer (in bytes).
+ * @param exch    Exchange for sending the message.
+ * @param dst     Address of the beginning of the destination buffer.
+ * @param size    Size of the destination buffer (in bytes).
  * @param dataptr Storage of call data (arg 2 holds actual data size).
+ *
  * @return Hash of the sent message or 0 on error.
- */
-aid_t async_data_read(int phoneid, void *dst, size_t size, ipc_call_t *dataptr)
-{
-	return async_send_2(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
+ *
+ */
+aid_t async_data_read(async_exch_t *exch, void *dst, size_t size,
+    ipc_call_t *dataptr)
+{
+	return async_send_2(exch, IPC_M_DATA_READ, (sysarg_t) dst,
 	    (sysarg_t) size, dataptr);
 }
@@ -1585,17 +1980,18 @@
 /** Wrapper for IPC_M_DATA_READ calls using the async framework.
  *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param dst     Address of the beginning of the destination buffer.
- * @param size    Size of the destination buffer.
- * @param flags   Flags to control the data transfer.
+ * @param exch Exchange for sending the message.
+ * @param dst  Address of the beginning of the destination buffer.
+ * @param size Size of the destination buffer.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int
-async_data_read_start_generic(int phoneid, void *dst, size_t size, int flags)
-{
-	return async_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
-	    (sysarg_t) size, (sysarg_t) flags);
+int async_data_read_start(async_exch_t *exch, void *dst, size_t size)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
+	return async_req_2_0(exch, IPC_M_DATA_READ, (sysarg_t) dst,
+	    (sysarg_t) size);
 }
 
@@ -1652,7 +2048,11 @@
  *
  */
-int async_data_read_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
-{
+int async_data_read_forward_fast(async_exch_t *exch, sysarg_t imethod,
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4,
+    ipc_call_t *dataptr)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
 	ipc_callid_t callid;
 	if (!async_data_read_receive(&callid, NULL)) {
@@ -1661,5 +2061,5 @@
 	}
 	
-	aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
+	aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4,
 	    dataptr);
 	if (msg == 0) {
@@ -1668,5 +2068,5 @@
 	}
 	
-	int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
+	int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
 	    IPC_FF_ROUTE_FROM_ME);
 	if (retval != EOK) {
@@ -1684,18 +2084,18 @@
 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
  *
- * @param phoneid Phone that will be used to contact the receiving side.
- * @param src     Address of the beginning of the source buffer.
- * @param size    Size of the source buffer.
- * @param flags   Flags to control the data transfer.
+ * @param exch Exchange for sending the message.
+ * @param src  Address of the beginning of the source buffer.
+ * @param size Size of the source buffer.
  *
  * @return Zero on success or a negative error code from errno.h.
  *
  */
-int
-async_data_write_start_generic(int phoneid, const void *src, size_t size,
-    int flags)
-{
-	return async_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
-	    (sysarg_t) size, (sysarg_t) flags);
+int async_data_write_start(async_exch_t *exch, const void *src, size_t size)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
+	return async_req_2_0(exch, IPC_M_DATA_WRITE, (sysarg_t) src,
+	    (sysarg_t) size);
 }
 
@@ -1773,4 +2173,6 @@
     size_t *received)
 {
+	assert(data);
+	
 	ipc_callid_t callid;
 	size_t size;
@@ -1840,7 +2242,11 @@
  *
  */
-int async_data_write_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
-    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
-{
+int async_data_write_forward_fast(async_exch_t *exch, sysarg_t imethod,
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4,
+    ipc_call_t *dataptr)
+{
+	if (exch == NULL)
+		return ENOENT;
+	
 	ipc_callid_t callid;
 	if (!async_data_write_receive(&callid, NULL)) {
@@ -1849,5 +2255,5 @@
 	}
 	
-	aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
+	aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4,
 	    dataptr);
 	if (msg == 0) {
@@ -1856,5 +2262,5 @@
 	}
 	
-	int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
+	int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,
 	    IPC_FF_ROUTE_FROM_ME);
 	if (retval != EOK) {
@@ -1870,4 +2276,105 @@
 }
 
+/** Wrapper for sending an exchange over different exchange for cloning
+ *
+ * @param exch       Exchange to be used for sending.
+ * @param clone_exch Exchange to be cloned.
+ *
+ */
+int async_exchange_clone(async_exch_t *exch, async_exch_t *clone_exch)
+{
+	return async_req_1_0(exch, IPC_M_CONNECTION_CLONE, clone_exch->phone);
+}
+
+/** Wrapper for receiving the IPC_M_CONNECTION_CLONE calls.
+ *
+ * If the current call is IPC_M_CONNECTION_CLONE then a new
+ * async session is created for the accepted phone.
+ *
+ * @param mgmt Exchange management style.
+ *
+ * @return New async session or NULL on failure.
+ *
+ */
+async_sess_t *async_clone_receive(exch_mgmt_t mgmt)
+{
+	/* Accept the phone */
+	ipc_call_t call;
+	ipc_callid_t callid = async_get_call(&call);
+	int phone = (int) IPC_GET_ARG1(call);
+	
+	if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECTION_CLONE) ||
+	    (phone < 0)) {
+		async_answer_0(callid, EINVAL);
+		return NULL;
+	}
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return NULL;
+	}
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = 0;
+	sess->arg2 = 0;
+	sess->arg3 = 0;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	/* Acknowledge the cloned phone */
+	async_answer_0(callid, EOK);
+	
+	return sess;
+}
+
+/** Wrapper for receiving the IPC_M_CONNECT_TO_ME calls.
+ *
+ * If the current call is IPC_M_CONNECT_TO_ME then a new
+ * async session is created for the accepted phone.
+ *
+ * @param mgmt Exchange management style.
+ *
+ * @return New async session or NULL on failure.
+ *
+ */
+async_sess_t *async_callback_receive(exch_mgmt_t mgmt)
+{
+	/* Accept the phone */
+	ipc_call_t call;
+	ipc_callid_t callid = async_get_call(&call);
+	int phone = (int) IPC_GET_ARG5(call);
+	
+	if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) ||
+	    (phone < 0)) {
+		async_answer_0(callid, EINVAL);
+		return NULL;
+	}
+	
+	async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));
+	if (sess == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return NULL;
+	}
+	
+	sess->mgmt = mgmt;
+	sess->phone = phone;
+	sess->arg1 = 0;
+	sess->arg2 = 0;
+	sess->arg3 = 0;
+	
+	list_initialize(&sess->exch_list);
+	fibril_mutex_initialize(&sess->mutex);
+	atomic_set(&sess->refcnt, 0);
+	
+	/* Acknowledge the connected phone */
+	async_answer_0(callid, EOK);
+	
+	return sess;
+}
+
 /** @}
  */
Index: uspace/lib/c/generic/async_obsolete.c
===================================================================
--- uspace/lib/c/generic/async_obsolete.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/generic/async_obsolete.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#define LIBC_ASYNC_C_
+#define LIBC_ASYNC_OBSOLETE_C_
+#include <ipc/ipc.h>
+#include <async.h>
+#include <async_obsolete.h>
+#undef LIBC_ASYNC_C_
+#undef LIBC_ASYNC_OBSOLETE_C_
+
+#include <fibril.h>
+#include <malloc.h>
+#include <errno.h>
+#include "private/async.h"
+
+/** Send message and return id of the sent message.
+ *
+ * The return value can be used as input for async_wait() to wait for
+ * completion.
+ *
+ * @param phoneid Handle of the phone that will be used for the send.
+ * @param method  Service-defined method.
+ * @param arg1    Service-defined payload argument.
+ * @param arg2    Service-defined payload argument.
+ * @param arg3    Service-defined payload argument.
+ * @param arg4    Service-defined payload argument.
+ * @param dataptr If non-NULL, storage where the reply data will be
+ *                stored.
+ *
+ * @return Hash of the sent message or 0 on error.
+ *
+ */
+aid_t async_obsolete_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
+{
+	amsg_t *msg = malloc(sizeof(amsg_t));
+	
+	if (!msg)
+		return 0;
+	
+	msg->done = false;
+	msg->dataptr = dataptr;
+	
+	msg->wdata.to_event.inlist = false;
+	
+	/*
+	 * We may sleep in the next method,
+	 * but it will use its own means
+	 */
+	msg->wdata.active = true;
+	
+	ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg,
+	    reply_received, true);
+	
+	return (aid_t) msg;
+}
+
+/** Pseudo-synchronous message sending - fast version.
+ *
+ * Send message asynchronously and return only after the reply arrives.
+ *
+ * This function can only transfer 4 register payload arguments. For
+ * transferring more arguments, see the slower async_req_slow().
+ *
+ * @param phoneid Hash of the phone through which to make the call.
+ * @param method  Method of the call.
+ * @param arg1    Service-defined payload argument.
+ * @param arg2    Service-defined payload argument.
+ * @param arg3    Service-defined payload argument.
+ * @param arg4    Service-defined payload argument.
+ * @param r1      If non-NULL, storage for the 1st reply argument.
+ * @param r2      If non-NULL, storage for the 2nd reply argument.
+ * @param r3      If non-NULL, storage for the 3rd reply argument.
+ * @param r4      If non-NULL, storage for the 4th reply argument.
+ * @param r5      If non-NULL, storage for the 5th reply argument.
+ *
+ * @return Return code of the reply or a negative error code.
+ *
+ */
+sysarg_t async_obsolete_req_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
+    sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)
+{
+	ipc_call_t result;
+	aid_t eid = async_obsolete_send_4(phoneid, method, arg1, arg2, arg3, arg4,
+	    &result);
+	
+	sysarg_t rc;
+	async_wait_for(eid, &rc);
+	
+	if (r1)
+		*r1 = IPC_GET_ARG1(result);
+	
+	if (r2)
+		*r2 = IPC_GET_ARG2(result);
+	
+	if (r3)
+		*r3 = IPC_GET_ARG3(result);
+	
+	if (r4)
+		*r4 = IPC_GET_ARG4(result);
+	
+	if (r5)
+		*r5 = IPC_GET_ARG5(result);
+	
+	return rc;
+}
+
+/** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param src     Source address space area base address.
+ * @param flags   Flags to be used for sharing. Bits can be only cleared.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
+ */
+int async_obsolete_share_out_start(int phoneid, void *src, unsigned int flags)
+{
+	return async_obsolete_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
+	    (sysarg_t) flags);
+}
+
+/** Wrapper for ipc_hangup.
+ *
+ * @param phone Phone handle to hung up.
+ *
+ * @return Zero on success or a negative error code.
+ *
+ */
+int async_obsolete_hangup(int phone)
+{
+	return ipc_hangup(phone);
+}
+
+void async_obsolete_serialize_start(void)
+{
+	fibril_inc_sercount();
+}
+
+void async_obsolete_serialize_end(void)
+{
+	fibril_dec_sercount();
+}
+
+/** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param src     Address of the beginning of the source buffer.
+ * @param size    Size of the source buffer.
+ * @param flags   Flags to control the data transfer.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
+ */
+int async_obsolete_data_write_start_generic(int phoneid, const void *src, size_t size,
+    int flags)
+{
+	return async_obsolete_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
+	    (sysarg_t) size, (sysarg_t) flags);
+}
+
+/** Start IPC_M_DATA_READ using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst     Address of the beginning of the destination buffer.
+ * @param size    Size of the destination buffer (in bytes).
+ * @param dataptr Storage of call data (arg 2 holds actual data size).
+ *
+ * @return Hash of the sent message or 0 on error.
+ *
+ */
+aid_t async_obsolete_data_read(int phone, void *dst, size_t size,
+    ipc_call_t *dataptr)
+{
+	return async_obsolete_send_2(phone, IPC_M_DATA_READ, (sysarg_t) dst,
+	    (sysarg_t) size, dataptr);
+}
+
+/** Wrapper for IPC_M_DATA_READ calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst     Address of the beginning of the destination buffer.
+ * @param size    Size of the destination buffer.
+ * @param flags   Flags to control the data transfer.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
+ */
+int async_obsolete_data_read_start_generic(int phoneid, void *dst, size_t size, int flags)
+{
+	return async_obsolete_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
+	    (sysarg_t) size, (sysarg_t) flags);
+}
+
+/** Wrapper for making IPC_M_CONNECT_TO_ME calls using the async framework.
+ *
+ * Ask through phone for a new connection to some service.
+ *
+ * @param phone           Phone handle used for contacting the other side.
+ * @param arg1            User defined argument.
+ * @param arg2            User defined argument.
+ * @param arg3            User defined argument.
+ * @param client_receiver Connection handing routine.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int async_obsolete_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, async_client_conn_t client_receiver)
+{
+	sysarg_t task_hash;
+	sysarg_t phone_hash;
+	int rc = async_obsolete_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
+	    NULL, NULL, NULL, &task_hash, &phone_hash);
+	if (rc != EOK)
+		return rc;
+	
+	if (client_receiver != NULL)
+		async_new_connection(task_hash, phone_hash, 0, NULL,
+		    client_receiver);
+	
+	return EOK;
+}
+
+/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
+ *
+ * Ask through phone for a new connection to some service.
+ *
+ * @param phone Phone handle used for contacting the other side.
+ * @param arg1  User defined argument.
+ * @param arg2  User defined argument.
+ * @param arg3  User defined argument.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int async_obsolete_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3)
+{
+	sysarg_t newphid;
+	int rc = async_obsolete_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
+	    NULL, NULL, NULL, NULL, &newphid);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return newphid;
+}
+
+/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
+ *
+ * Ask through phone for a new connection to some service and block until
+ * success.
+ *
+ * @param phoneid Phone handle used for contacting the other side.
+ * @param arg1    User defined argument.
+ * @param arg2    User defined argument.
+ * @param arg3    User defined argument.
+ *
+ * @return New phone handle on success or a negative error code.
+ *
+ */
+int async_obsolete_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3)
+{
+	sysarg_t newphid;
+	int rc = async_obsolete_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
+	    IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
+	
+	if (rc != EOK)
+		return rc;
+	
+	return newphid;
+}
+
+/** Send message and return id of the sent message
+ *
+ * The return value can be used as input for async_wait() to wait for
+ * completion.
+ *
+ * @param phoneid Handle of the phone that will be used for the send.
+ * @param method  Service-defined method.
+ * @param arg1    Service-defined payload argument.
+ * @param arg2    Service-defined payload argument.
+ * @param arg3    Service-defined payload argument.
+ * @param arg4    Service-defined payload argument.
+ * @param arg5    Service-defined payload argument.
+ * @param dataptr If non-NULL, storage where the reply data will be
+ *                stored.
+ *
+ * @return Hash of the sent message or 0 on error.
+ *
+ */
+aid_t async_obsolete_send_slow(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
+    ipc_call_t *dataptr)
+{
+	amsg_t *msg = malloc(sizeof(amsg_t));
+	
+	if (!msg)
+		return 0;
+	
+	msg->done = false;
+	msg->dataptr = dataptr;
+	
+	msg->wdata.to_event.inlist = false;
+	
+	/*
+	 * We may sleep in the next method,
+	 * but it will use its own means
+	 */
+	msg->wdata.active = true;
+	
+	ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,
+	    reply_received, true);
+	
+	return (aid_t) msg;
+}
+
+void async_obsolete_msg_0(int phone, sysarg_t imethod)
+{
+	ipc_call_async_0(phone, imethod, NULL, NULL, true);
+}
+
+void async_obsolete_msg_1(int phone, sysarg_t imethod, sysarg_t arg1)
+{
+	ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true);
+}
+
+void async_obsolete_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2)
+{
+	ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true);
+}
+
+void async_obsolete_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3)
+{
+	ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true);
+}
+
+void async_obsolete_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, sysarg_t arg4)
+{
+	ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL,
+	    true);
+}
+
+void async_obsolete_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
+    sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
+{
+	ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL,
+	    NULL, true);
+}
+
+/** Wrapper for IPC_M_SHARE_IN calls using the async framework.
+ *
+ * @param phoneid Phone that will be used to contact the receiving side.
+ * @param dst     Destination address space area base.
+ * @param size    Size of the destination address space area.
+ * @param arg     User defined argument.
+ * @param flags   Storage for the received flags. Can be NULL.
+ *
+ * @return Zero on success or a negative error code from errno.h.
+ *
+ */
+int async_obsolete_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
+    unsigned int *flags)
+{
+	sysarg_t tmp_flags;
+	int res = async_obsolete_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
+	    (sysarg_t) size, arg, NULL, &tmp_flags);
+	
+	if (flags)
+		*flags = (unsigned int) tmp_flags;
+	
+	return res;
+}
+
+int async_obsolete_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
+    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
+{
+	return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode);
+}
+
+int async_obsolete_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
+    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
+    unsigned int mode)
+{
+	return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4,
+	    arg5, mode);
+}
+
+/** Wrapper for forwarding any data that is about to be received
+ *
+ */
+int async_obsolete_data_write_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
+{
+	ipc_callid_t callid;
+	if (!async_data_write_receive(&callid, NULL)) {
+		ipc_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	aid_t msg = async_obsolete_send_fast(phoneid, method, arg1, arg2, arg3, arg4,
+	    dataptr);
+	if (msg == 0) {
+		ipc_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+	
+	int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,
+	    IPC_FF_ROUTE_FROM_ME);
+	if (retval != EOK) {
+		async_wait_for(msg, NULL);
+		ipc_answer_0(callid, retval);
+		return retval;
+	}
+	
+	sysarg_t rc;
+	async_wait_for(msg, &rc);
+	
+	return (int) rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/async_sess.c
===================================================================
--- uspace/lib/c/generic/async_sess.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ 	(revision )
@@ -1,309 +1,0 @@
-/*
- * Copyright (c) 2010 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-/**
- * This file implements simple session support for the async framework.
- *
- * By the term 'session', we mean a logical data path between a client and a
- * server over which the client can perform multiple concurrent exchanges.
- * Each exchange consists of one or more requests (IPC calls) which can
- * be potentially blocking.
- *
- * Clients and servers are naturally connected using IPC phones, thus an IPC
- * phone represents a session between a client and a server. In one
- * session, there can be many outstanding exchanges. In the current
- * implementation each concurrent exchanges takes place over a different
- * connection (there can be at most one active exchage per connection).
- *
- * Sessions make it useful for a client or client API to support concurrent
- * requests, independent of the actual implementation. Sessions provide
- * an abstract interface to concurrent IPC communication. This is especially
- * useful for client API stubs that aim to be reentrant (i.e. that allow
- * themselves to be called from different fibrils and threads concurrently).
- *
- * There are several possible implementations of sessions. This implementation
- * uses additional phones to represent sessions. Using phones both for the
- * session and also for its exchages/connections has several advantages:
- *
- * - to make a series of exchanges over a session, the client can continue to
- *   use the existing async framework APIs
- * - the server supports sessions by the virtue of spawning a new connection
- *   fibril, just as it does for every new connection even without sessions
- * - the implementation is pretty straightforward; a very naive implementation
- *   would be to make each exchage using a fresh phone (that is what we
- *   have done in the past); a slightly better approach would be to cache
- *   connections so that they can be reused by a later exchange within
- *   the same session (that is what this implementation does)
- *
- * The main disadvantages of using phones to represent sessions are:
- *
- * - if there are too many exchanges (even cached ones), the task may hit its
- *   limit on the maximum number of connected phones, which could prevent the
- *   task from making new IPC connections to other tasks
- * - if there are too many IPC connections already, it may be impossible to
- *   create an exchange by connecting a new phone thanks to the task's limit on
- *   the maximum number of connected phones
- *
- * These problems can be alleviated by increasing the limit on the maximum
- * number of connected phones to some reasonable value and by limiting the number
- * of cached connections to some fraction of this limit.
- *
- * The cache itself has a mechanism to close some number of unused phones if a
- * new phone cannot be connected, but the outer world currently does not have a
- * way to ask the phone cache to shrink.
- *
- * To minimize the confusion stemming from the fact that we use phones for two
- * things (the session itself and also one for each data connection), this file
- * makes the distinction by using the term 'session phone' for the former and
- * 'data phone' for the latter. Under the hood, all phones remain equal,
- * of course.
- *
- * There is a small inefficiency in that the cache repeatedly allocates and
- * deallocates the conn_node_t structures when in fact it could keep the
- * allocated structures around and reuse them later. But such a solution would
- * be effectively implementing a poor man's slab allocator while it would be
- * better to have the slab allocator ported to uspace so that everyone could
- * benefit from it.
- */
-
-#include <async_sess.h>
-#include <fibril_synch.h>
-#include <adt/list.h>
-#include <adt/hash_table.h>
-#include <malloc.h>
-#include <errno.h>
-#include <assert.h>
-#include <async.h>
-#include "private/async_sess.h"
-
-/** An inactive open connection. */
-typedef struct {
-	link_t sess_link;	/**< Link for the session list of inactive connections. */
-	link_t global_link;	/**< Link for the global list of inactive connections. */
-	int data_phone;		/**< Connected data phone. */
-} conn_node_t;
-
-/**
- * Mutex protecting the inactive_conn_head list, the session list and the
- * avail_phone condition variable.
- */
-static fibril_mutex_t async_sess_mutex;
-
-/**
- * List of all currently inactive connections.
- */
-static LIST_INITIALIZE(inactive_conn_head);
-
-/**
- * List of all open sessions.
- */
-static LIST_INITIALIZE(session_list_head);
-
-/**
- * Condition variable used to wait for a phone to become available.
- */
-static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);
-
-/** Initialize the async_sess subsystem.
- *
- * Needs to be called prior to any other interface in this file.
- *
- */
-void __async_sess_init(void)
-{
-	fibril_mutex_initialize(&async_sess_mutex);
-	list_initialize(&inactive_conn_head);
-	list_initialize(&session_list_head);
-}
-
-/** Create a session.
- *
- * Session is a logical datapath from a client task to a server task.
- * One session can accomodate multiple concurrent exchanges. Here
- * @a phone is a phone connected to the desired server task.
- *
- * This function always succeeds.
- *
- * @param sess	Session structure provided by caller, will be filled in.
- * @param phone	Phone connected to the desired server task.
- * @param arg1	Value to pass as first argument upon creating a new
- *		connection. Typical use is to identify a resource within
- *		the server that the caller wants to access (port ID,
- *		interface ID, device ID, etc.).
- */
-void async_session_create(async_sess_t *sess, int phone, sysarg_t arg1)
-{
-	sess->sess_phone = phone;
-	sess->connect_arg1 = arg1;
-	list_initialize(&sess->conn_head);
-	
-	/* Add to list of sessions. */
-	fibril_mutex_lock(&async_sess_mutex);
-	list_append(&sess->sess_link, &session_list_head);
-	fibril_mutex_unlock(&async_sess_mutex);
-}
-
-/** Destroy a session.
- *
- * Dismantle session structure @a sess and release any resources (connections)
- * held by the session.
- *
- * @param sess	Session to destroy.
- */
-void async_session_destroy(async_sess_t *sess)
-{
-	conn_node_t *conn;
-
-	/* Remove from list of sessions. */
-	fibril_mutex_lock(&async_sess_mutex);
-	list_remove(&sess->sess_link);
-	fibril_mutex_unlock(&async_sess_mutex);
-
-	/* We did not connect the phone so we do not hang it up either. */
-	sess->sess_phone = -1;
-
-	/* Tear down all data connections. */
-	while (!list_empty(&sess->conn_head)) {
-		conn = list_get_instance(sess->conn_head.next, conn_node_t,
-		    sess_link);
-
-		list_remove(&conn->sess_link);
-		list_remove(&conn->global_link);
-		
-		async_hangup(conn->data_phone);
-		free(conn);
-	}
-	
-	fibril_condvar_broadcast(&avail_phone_cv);
-}
-
-static void conn_node_initialize(conn_node_t *conn)
-{
-	link_initialize(&conn->sess_link);
-	link_initialize(&conn->global_link);
-	conn->data_phone = -1;
-}
-
-/** Start new exchange in a session.
- *
- * @param sess_phone	Session.
- * @return		Phone representing the new exchange or a negative error
- *			code.
- */
-int async_exchange_begin(async_sess_t *sess)
-{
-	conn_node_t *conn;
-	int data_phone;
-
-	fibril_mutex_lock(&async_sess_mutex);
-
-	if (!list_empty(&sess->conn_head)) {
-		/*
-		 * There are inactive connections in the session.
-		 */
-		conn = list_get_instance(sess->conn_head.next, conn_node_t,
-		    sess_link);
-		list_remove(&conn->sess_link);
-		list_remove(&conn->global_link);
-		
-		data_phone = conn->data_phone;
-		free(conn);
-	} else {
-		/*
-		 * There are no available connections in the session.
-		 * Make a one-time attempt to connect a new data phone.
-		 */
-retry:
-		data_phone = async_connect_me_to(sess->sess_phone,
-		    sess->connect_arg1, 0, 0);
-		if (data_phone >= 0) {
-			/* success, do nothing */
-		} else if (!list_empty(&inactive_conn_head)) {
-			/*
-			 * We did not manage to connect a new phone. But we can
-			 * try to close some of the currently inactive
-			 * connections in other sessions and try again.
-			 */
-			conn = list_get_instance(inactive_conn_head.next,
-			    conn_node_t, global_link);
-			list_remove(&conn->global_link);
-			list_remove(&conn->sess_link);
-			data_phone = conn->data_phone;
-			free(conn);
-			async_hangup(data_phone);
-			goto retry;
-		} else {
-			/*
-			 * Wait for a phone to become available.
-			 */
-			fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex);
-			goto retry;
-		}
-	}
-
-	fibril_mutex_unlock(&async_sess_mutex);
-	return data_phone;
-}
-
-/** Finish an exchange.
- *
- * @param sess		Session.
- * @param data_phone	Phone representing the exchange within the session.
- */
-void async_exchange_end(async_sess_t *sess, int data_phone)
-{
-	conn_node_t *conn;
-
-	fibril_mutex_lock(&async_sess_mutex);
-	fibril_condvar_signal(&avail_phone_cv);
-	conn = (conn_node_t *) malloc(sizeof(conn_node_t));
-	if (!conn) {
-		/*
-		 * Being unable to remember the connected data phone here
-		 * means that we simply hang up.
-		 */
-		async_hangup(data_phone);
-		fibril_mutex_unlock(&async_sess_mutex);
-		return;
-	}
-
-	conn_node_initialize(conn);
-	conn->data_phone = data_phone;
-	list_append(&conn->sess_link, &sess->conn_head);
-	list_append(&conn->global_link, &inactive_conn_head);
-	fibril_mutex_unlock(&async_sess_mutex);
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/clipboard.c
===================================================================
--- uspace/lib/c/generic/clipboard.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/clipboard.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -39,7 +39,8 @@
 
 #include <clipboard.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <ipc/services.h>
 #include <ipc/clipboard.h>
+#include <fibril_synch.h>
 #include <async.h>
 #include <str.h>
@@ -47,13 +48,33 @@
 #include <malloc.h>
 
-static int clip_phone = -1;
-
-/** Connect to clipboard server
- *
- */
-static void clip_connect(void)
-{
-	while (clip_phone < 0)
-		clip_phone = service_connect_blocking(SERVICE_CLIPBOARD, 0, 0);
+static FIBRIL_MUTEX_INITIALIZE(clip_mutex);
+static async_sess_t *clip_sess = NULL;
+
+/** Start an async exchange on the clipboard session.
+ *
+ * @return New exchange.
+ *
+ */
+static async_exch_t *clip_exchange_begin(void)
+{
+	fibril_mutex_lock(&clip_mutex);
+	
+	while (clip_sess == NULL)
+		clip_sess = service_connect_blocking(EXCHANGE_SERIALIZE,
+		    SERVICE_CLIPBOARD, 0, 0);
+	
+	fibril_mutex_unlock(&clip_mutex);
+	
+	return async_exchange_begin(clip_sess);
+}
+
+/** Finish an async exchange on the clipboard session.
+ *
+ * @param exch Exchange to be finished.
+ *
+ */
+static void clip_exchange_end(async_exch_t *exch)
+{
+	async_exchange_end(exch);
 }
 
@@ -73,22 +94,20 @@
 	
 	if (size == 0) {
-		async_serialize_start();
-		clip_connect();
-		
-		sysarg_t rc = async_req_1_0(clip_phone, CLIPBOARD_PUT_DATA, CLIPBOARD_TAG_NONE);
-		
-		async_serialize_end();
+		async_exch_t *exch = clip_exchange_begin();
+		sysarg_t rc = async_req_1_0(exch, CLIPBOARD_PUT_DATA,
+		    CLIPBOARD_TAG_NONE);
+		clip_exchange_end(exch);
 		
 		return (int) rc;
 	} else {
-		async_serialize_start();
-		clip_connect();
-		
-		aid_t req = async_send_1(clip_phone, CLIPBOARD_PUT_DATA, CLIPBOARD_TAG_DATA, NULL);
-		sysarg_t rc = async_data_write_start(clip_phone, (void *) str, size);
+		async_exch_t *exch = clip_exchange_begin();
+		aid_t req = async_send_1(exch, CLIPBOARD_PUT_DATA, CLIPBOARD_TAG_DATA,
+		    NULL);
+		sysarg_t rc = async_data_write_start(exch, (void *) str, size);
+		clip_exchange_end(exch);
+		
 		if (rc != EOK) {
 			sysarg_t rc_orig;
 			async_wait_for(req, &rc_orig);
-			async_serialize_end();
 			if (rc_orig == EOK)
 				return (int) rc;
@@ -98,5 +117,4 @@
 		
 		async_wait_for(req, &rc);
-		async_serialize_end();
 		
 		return (int) rc;
@@ -117,12 +135,11 @@
 	/* Loop until clipboard read succesful */
 	while (true) {
-		async_serialize_start();
-		clip_connect();
+		async_exch_t *exch = clip_exchange_begin();
 		
 		sysarg_t size;
 		sysarg_t tag;
-		sysarg_t rc = async_req_0_2(clip_phone, CLIPBOARD_CONTENT, &size, &tag);
-		
-		async_serialize_end();
+		sysarg_t rc = async_req_0_2(exch, CLIPBOARD_CONTENT, &size, &tag);
+		
+		clip_exchange_end(exch);
 		
 		if (rc != EOK)
@@ -145,8 +162,9 @@
 				return ENOMEM;
 			
-			async_serialize_start();
-			
-			aid_t req = async_send_1(clip_phone, CLIPBOARD_GET_DATA, tag, NULL);
-			rc = async_data_read_start(clip_phone, (void *) sbuf, size);
+			exch = clip_exchange_begin();
+			aid_t req = async_send_1(exch, CLIPBOARD_GET_DATA, tag, NULL);
+			rc = async_data_read_start(exch, (void *) sbuf, size);
+			clip_exchange_end(exch);
+			
 			if ((int) rc == EOVERFLOW) {
 				/*
@@ -154,5 +172,4 @@
 				 * the last call of CLIPBOARD_CONTENT
 				 */
-				async_serialize_end();
 				break;
 			}
@@ -161,5 +178,4 @@
 				sysarg_t rc_orig;
 				async_wait_for(req, &rc_orig);
-				async_serialize_end();
 				if (rc_orig == EOK)
 					return (int) rc;
@@ -169,5 +185,4 @@
 			
 			async_wait_for(req, &rc);
-			async_serialize_end();
 			
 			if (rc == EOK) {
Index: uspace/lib/c/generic/device/char_dev.c
===================================================================
--- uspace/lib/c/generic/device/char_dev.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/device/char_dev.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -45,35 +45,37 @@
  * using its character interface.
  *
- * @param dev_phone	Phone to the device.
- * @param buf		Buffer for the data read from or written to the device.
- * @param size		Maximum size of data (in bytes) to be read or written.
- * @param read		Read from the device if true, write to it otherwise.
+ * @param sess Session to the device.
+ * @param buf  Buffer for the data read from or written to the device.
+ * @param size Maximum size of data (in bytes) to be read or written.
+ * @param read Read from the device if true, write to it otherwise.
  *
- * @return		Non-negative number of bytes actually read from or
- *			written to the device on success, negative error number
- *			otherwise.
+ * @return Non-negative number of bytes actually read from or
+ *         written to the device on success, negative error number
+ *         otherwise.
+ *
  */
-static ssize_t char_dev_rw(int dev_phone, void *buf, size_t size, bool read)
+static ssize_t char_dev_rw(async_sess_t *sess, void *buf, size_t size, bool read)
 {
-	async_serialize_start();
-	
 	ipc_call_t answer;
 	aid_t req;
 	int ret;
 	
+	async_exch_t *exch = async_exchange_begin(sess);
+	
 	if (read) {
-		req = async_send_1(dev_phone, DEV_IFACE_ID(CHAR_DEV_IFACE),
+		req = async_send_1(exch, DEV_IFACE_ID(CHAR_DEV_IFACE),
 		    CHAR_DEV_READ, &answer);
-		ret = async_data_read_start(dev_phone, buf, size);
+		ret = async_data_read_start(exch, buf, size);
 	} else {
-		req = async_send_1(dev_phone, DEV_IFACE_ID(CHAR_DEV_IFACE),
+		req = async_send_1(exch, DEV_IFACE_ID(CHAR_DEV_IFACE),
 		    CHAR_DEV_WRITE, &answer);
-		ret = async_data_write_start(dev_phone, buf, size);
+		ret = async_data_write_start(exch, buf, size);
 	}
+	
+	async_exchange_end(exch);
 	
 	sysarg_t rc;
 	if (ret != EOK) {
 		async_wait_for(req, &rc);
-		async_serialize_end();
 		if (rc == EOK)
 			return (ssize_t) ret;
@@ -83,5 +85,4 @@
 	
 	async_wait_for(req, &rc);
-	async_serialize_end();
 	
 	ret = (int) rc;
@@ -94,29 +95,31 @@
 /** Read from character device.
  *
- * @param dev_phone	Phone to the device.
- * @param buf		Output buffer for the data read from the device.
- * @param size		Maximum size (in bytes) of the data to be read.
+ * @param sess Session to the device.
+ * @param buf  Output buffer for the data read from the device.
+ * @param size Maximum size (in bytes) of the data to be read.
  *
- * @return		Non-negative number of bytes actually read from the
- *			device on success, negative error number otherwise.
+ * @return Non-negative number of bytes actually read from the
+ *         device on success, negative error number otherwise.
+ *
  */
-ssize_t char_dev_read(int dev_phone, void *buf, size_t size)
+ssize_t char_dev_read(async_sess_t *sess, void *buf, size_t size)
 {
-	return char_dev_rw(dev_phone, buf, size, true);
+	return char_dev_rw(sess, buf, size, true);
 }
 
 /** Write to character device.
  *
- * @param dev_phone	Phone to the device.
- * @param buf		Input buffer containg the data to be written to the
- *			device.
- * @param size		Maximum size (in bytes) of the data to be written.
+ * @param sess Session to the device.
+ * @param buf  Input buffer containg the data to be written to the
+ *             device.
+ * @param size Maximum size (in bytes) of the data to be written.
  *
- * @return		Non-negative number of bytes actually written to the
- *			device on success, negative error number otherwise.
+ * @return Non-negative number of bytes actually written to the
+ *         device on success, negative error number otherwise.
+ *
  */
-ssize_t char_dev_write(int dev_phone, void *buf, size_t size)
+ssize_t char_dev_write(async_sess_t *sess, void *buf, size_t size)
 {
-	return char_dev_rw(dev_phone, buf, size, false);
+	return char_dev_rw(sess, buf, size, false);
 }
 
Index: uspace/lib/c/generic/device/hw_res.c
===================================================================
--- uspace/lib/c/generic/device/hw_res.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/device/hw_res.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -38,36 +38,48 @@
 #include <malloc.h>
 
-int hw_res_get_resource_list(int dev_phone, hw_resource_list_t *hw_resources)
+int hw_res_get_resource_list(async_sess_t *sess,
+    hw_resource_list_t *hw_resources)
 {
 	sysarg_t count = 0;
-
-	int rc = async_req_1_1(dev_phone, DEV_IFACE_ID(HW_RES_DEV_IFACE),
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_1_1(exch, DEV_IFACE_ID(HW_RES_DEV_IFACE),
 	    HW_RES_GET_RESOURCE_LIST, &count);
-
-	hw_resources->count = count;
-	if (rc != EOK)
+	
+	if (rc != EOK) {
+		async_exchange_end(exch);
 		return rc;
+	}
 	
 	size_t size = count * sizeof(hw_resource_t);
-	hw_resources->resources = (hw_resource_t *)malloc(size);
-	if (!hw_resources->resources)
+	hw_resource_t *resources = (hw_resource_t *) malloc(size);
+	if (resources == NULL) {
+		// FIXME: This is protocol violation
+		async_exchange_end(exch);
 		return ENOMEM;
+	}
 	
-	rc = async_data_read_start(dev_phone, hw_resources->resources, size);
+	rc = async_data_read_start(exch, resources, size);
+	async_exchange_end(exch);
+	
 	if (rc != EOK) {
-		free(hw_resources->resources);
-		hw_resources->resources = NULL;
+		free(resources);
 		return rc;
 	}
+	
+	hw_resources->resources = resources;
+	hw_resources->count = count;
 	
 	return EOK;
 }
 
-bool hw_res_enable_interrupt(int dev_phone)
+bool hw_res_enable_interrupt(async_sess_t *sess)
 {
-	int rc = async_req_1_0(dev_phone, DEV_IFACE_ID(HW_RES_DEV_IFACE),
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_1_0(exch, DEV_IFACE_ID(HW_RES_DEV_IFACE),
 	    HW_RES_ENABLE_INTERRUPT);
-
-	return rc == EOK;
+	async_exchange_end(exch);
+	
+	return (rc == EOK);
 }
 
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/devman.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -36,59 +36,141 @@
 
 #include <str.h>
-#include <stdio.h>
 #include <ipc/services.h>
+#include <ns.h>
 #include <ipc/devman.h>
 #include <devman.h>
+#include <fibril_synch.h>
 #include <async.h>
-#include <fibril_synch.h>
 #include <errno.h>
 #include <malloc.h>
 #include <bool.h>
-#include <adt/list.h>
-
-static int devman_phone_driver = -1;
-static int devman_phone_client = -1;
-
-static FIBRIL_MUTEX_INITIALIZE(devman_phone_mutex);
-
-int devman_get_phone(devman_interface_t iface, unsigned int flags)
+
+static FIBRIL_MUTEX_INITIALIZE(devman_driver_block_mutex);
+static FIBRIL_MUTEX_INITIALIZE(devman_client_block_mutex);
+
+static FIBRIL_MUTEX_INITIALIZE(devman_driver_mutex);
+static FIBRIL_MUTEX_INITIALIZE(devman_client_mutex);
+
+static async_sess_t *devman_driver_block_sess = NULL;
+static async_sess_t *devman_client_block_sess = NULL;
+
+static async_sess_t *devman_driver_sess = NULL;
+static async_sess_t *devman_client_sess = NULL;
+
+static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
+    async_sess_t **dst)
+{
+	fibril_mutex_lock(mtx);
+	
+	if ((*dst == NULL) && (src != NULL))
+		*dst = src;
+	
+	fibril_mutex_unlock(mtx);
+}
+
+/** Start an async exchange on the devman session (blocking).
+ *
+ * @param iface Device manager interface to choose
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *devman_exchange_begin_blocking(devman_interface_t iface)
 {
 	switch (iface) {
 	case DEVMAN_DRIVER:
-		fibril_mutex_lock(&devman_phone_mutex);
-		if (devman_phone_driver >= 0) {
-			fibril_mutex_unlock(&devman_phone_mutex);
-			return devman_phone_driver;
+		fibril_mutex_lock(&devman_driver_block_mutex);
+		
+		while (devman_driver_block_sess == NULL) {
+			clone_session(&devman_driver_mutex, devman_driver_sess,
+			    &devman_driver_block_sess);
+			
+			if (devman_driver_block_sess == NULL)
+				devman_driver_block_sess =
+				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
 		}
 		
-		if (flags & IPC_FLAG_BLOCKING)
-			devman_phone_driver = async_connect_me_to_blocking(
-			    PHONE_NS, SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
-		else
-			devman_phone_driver = async_connect_me_to(PHONE_NS,
-			    SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
-		
-		fibril_mutex_unlock(&devman_phone_mutex);
-		return devman_phone_driver;
+		fibril_mutex_unlock(&devman_driver_block_mutex);
+		
+		clone_session(&devman_driver_mutex, devman_driver_block_sess,
+		    &devman_driver_sess);
+		
+		return async_exchange_begin(devman_driver_block_sess);
 	case DEVMAN_CLIENT:
-		fibril_mutex_lock(&devman_phone_mutex);
-		if (devman_phone_client >= 0) {
-			fibril_mutex_unlock(&devman_phone_mutex);
-			return devman_phone_client;
+		fibril_mutex_lock(&devman_client_block_mutex);
+		
+		while (devman_client_block_sess == NULL) {
+			clone_session(&devman_client_mutex, devman_client_sess,
+			    &devman_client_block_sess);
+			
+			if (devman_client_block_sess == NULL)
+				devman_client_block_sess =
+				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
 		}
 		
-		if (flags & IPC_FLAG_BLOCKING) {
-			devman_phone_client = async_connect_me_to_blocking(
-			    PHONE_NS, SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
-		} else {
-			devman_phone_client = async_connect_me_to(PHONE_NS,
-			    SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
-		}
-		
-		fibril_mutex_unlock(&devman_phone_mutex);
-		return devman_phone_client;
+		fibril_mutex_unlock(&devman_client_block_mutex);
+		
+		clone_session(&devman_client_mutex, devman_client_block_sess,
+		    &devman_client_sess);
+		
+		return async_exchange_begin(devman_client_block_sess);
 	default:
-		return -1;
-	}
+		return NULL;
+	}
+}
+
+/** Start an async exchange on the devman session.
+ *
+ * @param iface Device manager interface to choose
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *devman_exchange_begin(devman_interface_t iface)
+{
+	switch (iface) {
+	case DEVMAN_DRIVER:
+		fibril_mutex_lock(&devman_driver_mutex);
+		
+		if (devman_driver_sess == NULL)
+			devman_driver_sess =
+			    service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAN,
+			    DEVMAN_DRIVER, 0);
+		
+		fibril_mutex_unlock(&devman_driver_mutex);
+		
+		if (devman_driver_sess == NULL)
+			return NULL;
+		
+		return async_exchange_begin(devman_driver_sess);
+	case DEVMAN_CLIENT:
+		fibril_mutex_lock(&devman_client_mutex);
+		
+		if (devman_client_sess == NULL)
+			devman_client_sess =
+			    service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAN,
+			    DEVMAN_CLIENT, 0);
+		
+		fibril_mutex_unlock(&devman_client_mutex);
+		
+		if (devman_client_sess == NULL)
+			return NULL;
+		
+		return async_exchange_begin(devman_client_sess);
+	default:
+		return NULL;
+	}
+}
+
+/** Finish an async exchange on the devman session.
+ *
+ * @param exch Exchange to be finished.
+ *
+ */
+void devman_exchange_end(async_exch_t *exch)
+{
+	async_exchange_end(exch);
 }
 
@@ -96,120 +178,98 @@
 int devman_driver_register(const char *name, async_client_conn_t conn)
 {
-	int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, name, str_size(name));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		return -1;
+	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, DEVMAN_DRIVER_REGISTER, 0, 0, &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	
+	devman_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
 	}
 	
 	async_set_client_connection(conn);
 	
-	async_connect_to_me(phone, 0, 0, 0, NULL);
+	exch = devman_exchange_begin(DEVMAN_DRIVER);
+	async_connect_to_me(exch, 0, 0, 0, NULL);
+	devman_exchange_end(exch);
+	
 	async_wait_for(req, &retval);
-	
-	async_serialize_end();
-	
 	return retval;
 }
 
-static int devman_send_match_id(int phone, match_id_t *match_id)
-{
-	ipc_call_t answer;
-
-	aid_t req = async_send_1(phone, DEVMAN_ADD_MATCH_ID, match_id->score,
-	    &answer);
-	int retval = async_data_write_start(phone, match_id->id,
-	    str_size(match_id->id));
-
-	async_wait_for(req, NULL);
-	return retval;
-}
-
-
-static int devman_send_match_ids(int phone, match_id_list_t *match_ids)
-{
+/** Add function to a device.
+ *
+ * Request devman to add a new function to the specified device owned by
+ * this driver task.
+ *
+ * @param name      Name of the new function
+ * @param ftype     Function type, fun_inner or fun_exposed
+ * @param match_ids Match IDs (should be empty for fun_exposed)
+ * @param devh      Devman handle of the device
+ * @param funh      Place to store handle of the new function
+ *
+ * @return EOK on success or negative error code.
+ *
+ */
+int devman_add_function(const char *name, fun_type_t ftype,
+    match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
+{
+	int match_count = list_count(&match_ids->ids);
+	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_3(exch, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
+	    devh, match_count, &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	if (retval != EOK) {
+		devman_exchange_end(exch);
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	if (retval != EOK) {
+		devman_exchange_end(exch);
+		
+		if (funh != NULL)
+			*funh = -1;
+		
+		return retval;
+	}
+	
+	if (funh != NULL)
+		*funh = (int) IPC_GET_ARG1(answer);
+	
 	link_t *link = match_ids->ids.next;
 	match_id_t *match_id = NULL;
-	int ret = EOK;
-
+	
 	while (link != &match_ids->ids) {
-		match_id = list_get_instance(link, match_id_t, link); 
-		ret = devman_send_match_id(phone, match_id);
-		if (ret != EOK) {
-			return ret;
+		match_id = list_get_instance(link, match_id_t, link);
+		
+		ipc_call_t answer;
+		aid_t req = async_send_1(exch, DEVMAN_ADD_MATCH_ID,
+		    match_id->score, &answer);
+		retval = async_data_write_start(exch, match_id->id,
+		    str_size(match_id->id));
+		if (retval != EOK) {
+			devman_exchange_end(exch);
+			async_wait_for(req, NULL);
+			return retval;
 		}
-
+		
+		async_wait_for(req, &retval);
+		if (retval != EOK) {
+			devman_exchange_end(exch);
+			return retval;
+		}
+		
 		link = link->next;
 	}
-
-	return ret;
-}
-
-/** Add function to a device.
- *
- * Request devman to add a new function to the specified device owned by
- * this driver task.
- *
- * @param name		Name of the new function
- * @param ftype		Function type, fun_inner or fun_exposed
- * @param match_ids	Match IDs (should be empty for fun_exposed)
- * @param devh		Devman handle of the device
- * @param funh		Place to store handle of the new function
- *
- * @return		EOK on success or negative error code.
- */
-int devman_add_function(const char *name, fun_type_t ftype,
-    match_id_list_t *match_ids, devman_handle_t devh, devman_handle_t *funh)
-{
-	int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
-	int fun_handle;
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	
-	int match_count = list_count(&match_ids->ids);
-	ipc_call_t answer;
-
-	aid_t req = async_send_3(phone, DEVMAN_ADD_FUNCTION, (sysarg_t) ftype,
-	    devh, match_count, &answer);
-
-	sysarg_t retval = async_data_write_start(phone, name, str_size(name));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		return retval;
-	}
-	
-	int match_ids_rc = devman_send_match_ids(phone, match_ids);
-	
-	async_wait_for(req, &retval);
-	
-	async_serialize_end();
-	
-	/* Prefer the answer to DEVMAN_ADD_FUNCTION in case of errors. */
-	if ((match_ids_rc != EOK) && (retval == EOK)) {
-		retval = match_ids_rc;
-	}
-
-	if (retval == EOK)
-		fun_handle = (int) IPC_GET_ARG1(answer);
-	else
-		fun_handle = -1;
-	
-	*funh = fun_handle;
-
-	return retval;
+	
+	devman_exchange_end(exch);
+	return EOK;
 }
 
@@ -217,76 +277,51 @@
     const char *class_name)
 {
-	int phone = devman_get_phone(DEVMAN_DRIVER, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	ipc_call_t answer;
-	aid_t req = async_send_1(phone, DEVMAN_ADD_DEVICE_TO_CLASS,
+	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_DRIVER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, DEVMAN_ADD_DEVICE_TO_CLASS,
 	    devman_handle, &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, class_name,
+	sysarg_t retval = async_data_write_start(exch, class_name,
 	    str_size(class_name));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
+	
+	devman_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
 		return retval;
 	}
 	
 	async_wait_for(req, &retval);
-	async_serialize_end();
-	
 	return retval;
 }
 
-void devman_hangup_phone(devman_interface_t iface)
-{
-	switch (iface) {
-	case DEVMAN_DRIVER:
-		if (devman_phone_driver >= 0) {
-			async_hangup(devman_phone_driver);
-			devman_phone_driver = -1;
-		}
-		break;
-	case DEVMAN_CLIENT:
-		if (devman_phone_client >= 0) {
-			async_hangup(devman_phone_client);
-			devman_phone_client = -1;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-int devman_device_connect(devman_handle_t handle, unsigned int flags)
-{
-	int phone;
-	
-	if (flags & IPC_FLAG_BLOCKING) {
-		phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
-		    DEVMAN_CONNECT_TO_DEVICE, handle);
-	} else {
-		phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
-		    DEVMAN_CONNECT_TO_DEVICE, handle);
-	}
-	
-	return phone;
-}
-
-int devman_parent_device_connect(devman_handle_t handle, unsigned int flags)
-{
-	int phone;
-	
-	if (flags & IPC_FLAG_BLOCKING) {
-		phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAN,
-		    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
-	} else {
-		phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAN,
-		    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
-	}
-	
-	return phone;
+async_sess_t *devman_device_connect(exch_mgmt_t mgmt, devman_handle_t handle,
+    unsigned int flags)
+{
+	async_sess_t *sess;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		sess = service_connect_blocking(mgmt, SERVICE_DEVMAN,
+			    DEVMAN_CONNECT_TO_DEVICE, handle);
+	else
+		sess = service_connect(mgmt, SERVICE_DEVMAN,
+			    DEVMAN_CONNECT_TO_DEVICE, handle);
+	
+	return sess;
+}
+
+async_sess_t *devman_parent_device_connect(exch_mgmt_t mgmt,
+    devman_handle_t handle, unsigned int flags)
+{
+	async_sess_t *sess;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		sess = service_connect_blocking(mgmt, SERVICE_DEVMAN,
+			    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
+	else
+		sess = service_connect(mgmt, SERVICE_DEVMAN,
+			    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
+	
+	return sess;
 }
 
@@ -294,30 +329,33 @@
     unsigned int flags)
 {
-	int phone = devman_get_phone(DEVMAN_CLIENT, flags);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
+	else {
+		exch = devman_exchange_begin(DEVMAN_CLIENT);
+		if (exch == NULL)
+			return errno;
+	}
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(exch, DEVMAN_DEVICE_GET_HANDLE, flags, 0,
 	    &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, pathname,
+	sysarg_t retval = async_data_write_start(exch, pathname,
 	    str_size(pathname));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
+	
+	devman_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
 		return retval;
 	}
 	
 	async_wait_for(req, &retval);
-	
-	async_serialize_end();
 	
 	if (retval != EOK) {
 		if (handle != NULL)
 			*handle = (devman_handle_t) -1;
+		
 		return retval;
 	}
@@ -332,43 +370,48 @@
     const char *devname, devman_handle_t *handle, unsigned int flags)
 {
-	int phone = devman_get_phone(DEVMAN_CLIENT, flags);
-
-	if (phone < 0)
-		return phone;
-
-	async_serialize_start();
-
-	ipc_call_t answer;
-	aid_t req = async_send_1(phone, DEVMAN_DEVICE_GET_HANDLE_BY_CLASS,
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
+	else {
+		exch = devman_exchange_begin(DEVMAN_CLIENT);
+		if (exch == NULL)
+			return errno;
+	}
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, DEVMAN_DEVICE_GET_HANDLE_BY_CLASS,
 	    flags, &answer);
-
-	sysarg_t retval = async_data_write_start(phone, classname,
+	sysarg_t retval = async_data_write_start(exch, classname,
 	    str_size(classname));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		return retval;
-	}
-	retval = async_data_write_start(phone, devname,
+	
+	if (retval != EOK) {
+		devman_exchange_end(exch);
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
+	retval = async_data_write_start(exch, devname,
 	    str_size(devname));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		return retval;
-	}
-
+	
+	devman_exchange_end(exch);
+	
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		return retval;
+	}
+	
 	async_wait_for(req, &retval);
-
-	async_serialize_end();
-
+	
 	if (retval != EOK) {
 		if (handle != NULL)
 			*handle = (devman_handle_t) -1;
-		return retval;
-	}
-
+		
+		return retval;
+	}
+	
 	if (handle != NULL)
 		*handle = (devman_handle_t) IPC_GET_ARG1(answer);
-
+	
 	return retval;
 }
@@ -376,59 +419,51 @@
 int devman_get_device_path(devman_handle_t handle, char *path, size_t path_size)
 {
-	int phone = devman_get_phone(DEVMAN_CLIENT, 0);
-
-	if (phone < 0)
-		return phone;
-
-	async_serialize_start();
-
-	ipc_call_t answer;
-	aid_t req = async_send_1(phone, DEVMAN_DEVICE_GET_DEVICE_PATH,
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
+	if (exch == NULL)
+		return errno;
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, DEVMAN_DEVICE_GET_DEVICE_PATH,
 	    handle, &answer);
-
+	
 	ipc_call_t data_request_call;
-	aid_t data_request = async_data_read(phone, path, path_size,
+	aid_t data_request = async_data_read(exch, path, path_size,
 	    &data_request_call);
+	
+	devman_exchange_end(exch);
+	
 	if (data_request == 0) {
 		async_wait_for(req, NULL);
-		async_serialize_end();
 		return ENOMEM;
 	}
-
+	
 	sysarg_t data_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	
 	sysarg_t opening_request_rc;
-	async_wait_for(data_request, &data_request_rc);
 	async_wait_for(req, &opening_request_rc);
-
-	async_serialize_end();
-
+	
 	if (data_request_rc != EOK) {
 		/* Prefer the return code of the opening request. */
-		if (opening_request_rc != EOK) {
+		if (opening_request_rc != EOK)
 			return (int) opening_request_rc;
-		} else {
+		else
 			return (int) data_request_rc;
-		}
-	}
-	if (opening_request_rc != EOK) {
+	}
+	
+	if (opening_request_rc != EOK)
 		return (int) opening_request_rc;
-	}
-
+	
 	/* To be on the safe-side. */
 	path[path_size - 1] = 0;
-
 	size_t transferred_size = IPC_GET_ARG2(data_request_call);
-
-	if (transferred_size >= path_size) {
+	if (transferred_size >= path_size)
 		return ELIMIT;
-	}
-
+	
 	/* Terminate the string (trailing 0 not send over IPC). */
 	path[transferred_size] = 0;
-
 	return EOK;
 }
 
-
 /** @}
  */
Index: uspace/lib/c/generic/devman_obsolete.c
===================================================================
--- uspace/lib/c/generic/devman_obsolete.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/generic/devman_obsolete.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2007 Josef Cejka
+ * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2010 Lenka Trochtova
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <str.h>
+#include <stdio.h>
+#include <ipc/services.h>
+#include <ipc/devman.h>
+#include <devman_obsolete.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <ns.h>
+#include <ns_obsolete.h>
+#include <fibril_synch.h>
+#include <errno.h>
+#include <malloc.h>
+#include <bool.h>
+#include <adt/list.h>
+
+static int devman_phone_driver = -1;
+static int devman_phone_client = -1;
+
+static FIBRIL_MUTEX_INITIALIZE(devman_phone_mutex);
+
+int devman_obsolete_get_phone(devman_interface_t iface, unsigned int flags)
+{
+	switch (iface) {
+	case DEVMAN_DRIVER:
+		fibril_mutex_lock(&devman_phone_mutex);
+		if (devman_phone_driver >= 0) {
+			fibril_mutex_unlock(&devman_phone_mutex);
+			return devman_phone_driver;
+		}
+		
+		if (flags & IPC_FLAG_BLOCKING)
+			devman_phone_driver = service_obsolete_connect_blocking(
+			    SERVICE_DEVMAN, DEVMAN_DRIVER, 0);
+		else
+			devman_phone_driver = service_obsolete_connect(SERVICE_DEVMAN,
+			    DEVMAN_DRIVER, 0);
+		
+		fibril_mutex_unlock(&devman_phone_mutex);
+		return devman_phone_driver;
+	case DEVMAN_CLIENT:
+		fibril_mutex_lock(&devman_phone_mutex);
+		if (devman_phone_client >= 0) {
+			fibril_mutex_unlock(&devman_phone_mutex);
+			return devman_phone_client;
+		}
+		
+		if (flags & IPC_FLAG_BLOCKING) {
+			devman_phone_client = service_obsolete_connect_blocking(
+			    SERVICE_DEVMAN, DEVMAN_CLIENT, 0);
+		} else {
+			devman_phone_client = service_obsolete_connect(SERVICE_DEVMAN,
+			    DEVMAN_CLIENT, 0);
+		}
+		
+		fibril_mutex_unlock(&devman_phone_mutex);
+		return devman_phone_client;
+	default:
+		return -1;
+	}
+}
+
+void devman_obsolete_hangup_phone(devman_interface_t iface)
+{
+	switch (iface) {
+	case DEVMAN_DRIVER:
+		if (devman_phone_driver >= 0) {
+			async_obsolete_hangup(devman_phone_driver);
+			devman_phone_driver = -1;
+		}
+		break;
+	case DEVMAN_CLIENT:
+		if (devman_phone_client >= 0) {
+			async_obsolete_hangup(devman_phone_client);
+			devman_phone_client = -1;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+int devman_obsolete_device_connect(devman_handle_t handle, unsigned int flags)
+{
+	int phone;
+	
+	if (flags & IPC_FLAG_BLOCKING) {
+		phone = service_obsolete_connect_blocking(SERVICE_DEVMAN,
+		    DEVMAN_CONNECT_TO_DEVICE, handle);
+	} else {
+		phone = service_obsolete_connect(SERVICE_DEVMAN,
+		    DEVMAN_CONNECT_TO_DEVICE, handle);
+	}
+	
+	return phone;
+}
+
+int devman_obsolete_parent_device_connect(devman_handle_t handle, unsigned int flags)
+{
+	int phone;
+	
+	if (flags & IPC_FLAG_BLOCKING) {
+		phone = service_obsolete_connect_blocking(SERVICE_DEVMAN,
+		    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
+	} else {
+		phone = service_obsolete_connect(SERVICE_DEVMAN,
+		    DEVMAN_CONNECT_TO_PARENTS_DEVICE, handle);
+	}
+	
+	return phone;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/devmap.c
===================================================================
--- uspace/lib/c/generic/devmap.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/devmap.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -30,7 +30,8 @@
 #include <str.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <ipc/devmap.h>
 #include <devmap.h>
+#include <fibril_synch.h>
 #include <async.h>
 #include <errno.h>
@@ -38,58 +39,131 @@
 #include <bool.h>
 
-static int devmap_phone_driver = -1;
-static int devmap_phone_client = -1;
-
-/** Get phone to device mapper task. */
-int devmap_get_phone(devmap_interface_t iface, unsigned int flags)
+static FIBRIL_MUTEX_INITIALIZE(devmap_driver_block_mutex);
+static FIBRIL_MUTEX_INITIALIZE(devmap_client_block_mutex);
+
+static FIBRIL_MUTEX_INITIALIZE(devmap_driver_mutex);
+static FIBRIL_MUTEX_INITIALIZE(devmap_client_mutex);
+
+static async_sess_t *devmap_driver_block_sess = NULL;
+static async_sess_t *devmap_client_block_sess = NULL;
+
+static async_sess_t *devmap_driver_sess = NULL;
+static async_sess_t *devmap_client_sess = NULL;
+
+static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
+    async_sess_t **dst)
+{
+	fibril_mutex_lock(mtx);
+	
+	if ((*dst == NULL) && (src != NULL))
+		*dst = src;
+	
+	fibril_mutex_unlock(mtx);
+}
+
+/** Start an async exchange on the devmap session (blocking).
+ *
+ * @param iface Device mapper interface to choose
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *devmap_exchange_begin_blocking(devmap_interface_t iface)
 {
 	switch (iface) {
 	case DEVMAP_DRIVER:
-		if (devmap_phone_driver >= 0)
-			return devmap_phone_driver;
-		
-		if (flags & IPC_FLAG_BLOCKING)
-			devmap_phone_driver = service_connect_blocking(SERVICE_DEVMAP,
-			    DEVMAP_DRIVER, 0);
-		else
-			devmap_phone_driver = service_connect(SERVICE_DEVMAP,
-			    DEVMAP_DRIVER, 0);
-		
-		return devmap_phone_driver;
+		fibril_mutex_lock(&devmap_driver_block_mutex);
+		
+		while (devmap_driver_block_sess == NULL) {
+			clone_session(&devmap_driver_mutex, devmap_driver_sess,
+			    &devmap_driver_block_sess);
+			
+			if (devmap_driver_block_sess == NULL)
+				devmap_driver_block_sess =
+				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
+		}
+		
+		fibril_mutex_unlock(&devmap_driver_block_mutex);
+		
+		clone_session(&devmap_driver_mutex, devmap_driver_block_sess,
+		    &devmap_driver_sess);
+		
+		return async_exchange_begin(devmap_driver_block_sess);
 	case DEVMAP_CLIENT:
-		if (devmap_phone_client >= 0)
-			return devmap_phone_client;
-		
-		if (flags & IPC_FLAG_BLOCKING)
-			devmap_phone_client = service_connect_blocking(SERVICE_DEVMAP,
-			    DEVMAP_CLIENT, 0);
-		else
-			devmap_phone_client = service_connect(SERVICE_DEVMAP,
-			    DEVMAP_CLIENT, 0);
-		
-		return devmap_phone_client;
+		fibril_mutex_lock(&devmap_client_block_mutex);
+		
+		while (devmap_client_block_sess == NULL) {
+			clone_session(&devmap_client_mutex, devmap_client_sess,
+			    &devmap_client_block_sess);
+			
+			if (devmap_client_block_sess == NULL)
+				devmap_client_block_sess =
+				    service_connect_blocking(EXCHANGE_SERIALIZE,
+				    SERVICE_DEVMAP, DEVMAP_CLIENT, 0);
+		}
+		
+		fibril_mutex_unlock(&devmap_client_block_mutex);
+		
+		clone_session(&devmap_client_mutex, devmap_client_block_sess,
+		    &devmap_client_sess);
+		
+		return async_exchange_begin(devmap_client_block_sess);
 	default:
-		return -1;
-	}
-}
-
-void devmap_hangup_phone(devmap_interface_t iface)
+		return NULL;
+	}
+}
+
+/** Start an async exchange on the devmap session.
+ *
+ * @param iface Device mapper interface to choose
+ *
+ * @return New exchange.
+ *
+ */
+async_exch_t *devmap_exchange_begin(devmap_interface_t iface)
 {
 	switch (iface) {
 	case DEVMAP_DRIVER:
-		if (devmap_phone_driver >= 0) {
-			async_hangup(devmap_phone_driver);
-			devmap_phone_driver = -1;
-		}
-		break;
+		fibril_mutex_lock(&devmap_driver_mutex);
+		
+		if (devmap_driver_sess == NULL)
+			devmap_driver_sess =
+			    service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAP,
+			    DEVMAP_DRIVER, 0);
+		
+		fibril_mutex_unlock(&devmap_driver_mutex);
+		
+		if (devmap_driver_sess == NULL)
+			return NULL;
+		
+		return async_exchange_begin(devmap_driver_sess);
 	case DEVMAP_CLIENT:
-		if (devmap_phone_client >= 0) {
-			async_hangup(devmap_phone_client);
-			devmap_phone_client = -1;
-		}
-		break;
+		fibril_mutex_lock(&devmap_client_mutex);
+		
+		if (devmap_client_sess == NULL)
+			devmap_client_sess =
+			    service_connect(EXCHANGE_SERIALIZE, SERVICE_DEVMAP,
+			    DEVMAP_CLIENT, 0);
+		
+		fibril_mutex_unlock(&devmap_client_mutex);
+		
+		if (devmap_client_sess == NULL)
+			return NULL;
+		
+		return async_exchange_begin(devmap_client_sess);
 	default:
-		break;
-	}
+		return NULL;
+	}
+}
+
+/** Finish an async exchange on the devmap session.
+ *
+ * @param exch Exchange to be finished.
+ *
+ */
+void devmap_exchange_end(async_exch_t *exch)
+{
+	async_exchange_end(exch);
 }
 
@@ -97,28 +171,24 @@
 int devmap_driver_register(const char *name, async_client_conn_t conn)
 {
-	int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
+	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_DRIVER);
 	
 	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, name, str_size(name));
+	aid_t req = async_send_2(exch, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	
+	devmap_exchange_end(exch);
+	
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
-		async_serialize_end();
-		return -1;
+		return retval;
 	}
 	
 	async_set_client_connection(conn);
 	
-	async_connect_to_me(phone, 0, 0, 0, NULL);
+	exch = devmap_exchange_begin(DEVMAP_DRIVER);
+	async_connect_to_me(exch, 0, 0, 0, NULL);
+	devmap_exchange_end(exch);
+	
 	async_wait_for(req, &retval);
-	
-	async_serialize_end();
-	
 	return retval;
 }
@@ -129,10 +199,11 @@
  * If not 0, the first argument is the interface and the second argument
  * is the devmap handle of the device.
+ *
  * When the interface is zero (default), the first argument is directly
  * the handle (to ensure backward compatibility).
  *
- * @param fqdn Fully qualified device name.
- * @param[out] handle Handle to the created instance of device.
- * @param interface Interface when forwarding.
+ * @param      fqdn      Fully qualified device name.
+ * @param[out] handle    Handle to the created instance of device.
+ * @param      interface Interface when forwarding.
  *
  */
@@ -140,29 +211,24 @@
     devmap_handle_t *handle, sysarg_t interface)
 {
-	int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
+	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_DRIVER);
 	
 	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, interface, 0,
+	aid_t req = async_send_2(exch, DEVMAP_DEVICE_REGISTER, interface, 0,
 	    &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
+	sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
+	
+	devmap_exchange_end(exch);
+	
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
-		async_serialize_end();
 		return retval;
 	}
 	
 	async_wait_for(req, &retval);
-	
-	async_serialize_end();
 	
 	if (retval != EOK) {
 		if (handle != NULL)
 			*handle = -1;
+		
 		return retval;
 	}
@@ -176,6 +242,6 @@
 /** Register new device.
  *
- * @param fqdn      Fully qualified device name.
- * @param handle    Output: Handle to the created instance of device.
+ * @param fqdn   Fully qualified device name.
+ * @param handle Output: Handle to the created instance of device.
  *
  */
@@ -185,32 +251,35 @@
 }
 
-
-int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle, unsigned int flags)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
+int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle,
+    unsigned int flags)
+{
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
+	else {
+		exch = devmap_exchange_begin(DEVMAP_CLIENT);
+		if (exch == NULL)
+			return errno;
+	}
 	
 	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
+	aid_t req = async_send_2(exch, DEVMAP_DEVICE_GET_HANDLE, flags, 0,
 	    &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
+	sysarg_t retval = async_data_write_start(exch, fqdn, str_size(fqdn));
+	
+	devmap_exchange_end(exch);
+	
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
-		async_serialize_end();
 		return retval;
 	}
 	
 	async_wait_for(req, &retval);
-	
-	async_serialize_end();
 	
 	if (retval != EOK) {
 		if (handle != NULL)
 			*handle = (devmap_handle_t) -1;
+		
 		return retval;
 	}
@@ -222,31 +291,35 @@
 }
 
-int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle, unsigned int flags)
-{
-	int phone = devmap_get_phone(DEVMAP_CLIENT, flags);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
+int devmap_namespace_get_handle(const char *name, devmap_handle_t *handle,
+    unsigned int flags)
+{
+	async_exch_t *exch;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
+	else {
+		exch = devmap_exchange_begin(DEVMAP_CLIENT);
+		if (exch == NULL)
+			return errno;
+	}
 	
 	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
+	aid_t req = async_send_2(exch, DEVMAP_NAMESPACE_GET_HANDLE, flags, 0,
 	    &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, name, str_size(name));
+	sysarg_t retval = async_data_write_start(exch, name, str_size(name));
+	
+	devmap_exchange_end(exch);
+	
 	if (retval != EOK) {
 		async_wait_for(req, NULL);
-		async_serialize_end();
 		return retval;
 	}
 	
 	async_wait_for(req, &retval);
-	
-	async_serialize_end();
 	
 	if (retval != EOK) {
 		if (handle != NULL)
 			*handle = (devmap_handle_t) -1;
+		
 		return retval;
 	}
@@ -260,11 +333,11 @@
 devmap_handle_type_t devmap_handle_probe(devmap_handle_t handle)
 {
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
+	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
 	
 	sysarg_t type;
-	int retval = async_req_1_1(phone, DEVMAP_HANDLE_PROBE, handle, &type);
+	int retval = async_req_1_1(exch, DEVMAP_HANDLE_PROBE, handle, &type);
+	
+	devmap_exchange_end(exch);
+	
 	if (retval != EOK)
 		return DEV_HANDLE_NONE;
@@ -273,28 +346,28 @@
 }
 
-int devmap_device_connect(devmap_handle_t handle, unsigned int flags)
-{
-	int phone;
-	
-	if (flags & IPC_FLAG_BLOCKING) {
-		phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP,
+async_sess_t *devmap_device_connect(exch_mgmt_t mgmt, devmap_handle_t handle,
+    unsigned int flags)
+{
+	async_sess_t *sess;
+	
+	if (flags & IPC_FLAG_BLOCKING)
+		sess = service_connect_blocking(mgmt, SERVICE_DEVMAP,
 		    DEVMAP_CONNECT_TO_DEVICE, handle);
-	} else {
-		phone = async_connect_me_to(PHONE_NS, SERVICE_DEVMAP,
+	else
+		sess = service_connect(mgmt, SERVICE_DEVMAP,
 		    DEVMAP_CONNECT_TO_DEVICE, handle);
-	}
-	
-	return phone;
+	
+	return sess;
 }
 
 int devmap_null_create(void)
 {
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return -1;
+	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
 	
 	sysarg_t null_id;
-	int retval = async_req_0_1(phone, DEVMAP_NULL_CREATE, &null_id);
+	int retval = async_req_0_1(exch, DEVMAP_NULL_CREATE, &null_id);
+	
+	devmap_exchange_end(exch);
+	
 	if (retval != EOK)
 		return -1;
@@ -305,16 +378,13 @@
 void devmap_null_destroy(int null_id)
 {
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return;
-	
-	async_req_1_0(phone, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
-}
-
-static size_t devmap_count_namespaces_internal(int phone)
+	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
+	async_req_1_0(exch, DEVMAP_NULL_DESTROY, (sysarg_t) null_id);
+	devmap_exchange_end(exch);
+}
+
+static size_t devmap_count_namespaces_internal(async_exch_t *exch)
 {
 	sysarg_t count;
-	int retval = async_req_0_1(phone, DEVMAP_GET_NAMESPACE_COUNT, &count);
+	int retval = async_req_0_1(exch, DEVMAP_GET_NAMESPACE_COUNT, &count);
 	if (retval != EOK)
 		return 0;
@@ -323,8 +393,10 @@
 }
 
-static size_t devmap_count_devices_internal(int phone, devmap_handle_t ns_handle)
+static size_t devmap_count_devices_internal(async_exch_t *exch,
+    devmap_handle_t ns_handle)
 {
 	sysarg_t count;
-	int retval = async_req_1_1(phone, DEVMAP_GET_DEVICE_COUNT, ns_handle, &count);
+	int retval = async_req_1_1(exch, DEVMAP_GET_DEVICE_COUNT, ns_handle,
+	    &count);
 	if (retval != EOK)
 		return 0;
@@ -335,32 +407,28 @@
 size_t devmap_count_namespaces(void)
 {
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return 0;
-	
-	return devmap_count_namespaces_internal(phone);
+	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
+	size_t size = devmap_count_namespaces_internal(exch);
+	devmap_exchange_end(exch);
+	
+	return size;
 }
 
 size_t devmap_count_devices(devmap_handle_t ns_handle)
 {
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return 0;
-	
-	return devmap_count_devices_internal(phone, ns_handle);
+	async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
+	size_t size = devmap_count_devices_internal(exch, ns_handle);
+	devmap_exchange_end(exch);
+	
+	return size;
 }
 
 size_t devmap_get_namespaces(dev_desc_t **data)
 {
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return 0;
-	
 	/* Loop until namespaces read succesful */
 	while (true) {
-		size_t count = devmap_count_namespaces_internal(phone);
+		async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
+		size_t count = devmap_count_namespaces_internal(exch);
+		devmap_exchange_end(exch);
+		
 		if (count == 0)
 			return 0;
@@ -370,10 +438,12 @@
 			return 0;
 		
-		async_serialize_start();
+		exch = devmap_exchange_begin(DEVMAP_CLIENT);
 		
 		ipc_call_t answer;
-		aid_t req = async_send_0(phone, DEVMAP_GET_NAMESPACES, &answer);
-		
-		int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
+		aid_t req = async_send_0(exch, DEVMAP_GET_NAMESPACES, &answer);
+		int rc = async_data_read_start(exch, devs, count * sizeof(dev_desc_t));
+		
+		devmap_exchange_end(exch);
+		
 		if (rc == EOVERFLOW) {
 			/*
@@ -381,5 +451,4 @@
 			 * the last call of DEVMAP_DEVICE_GET_NAMESPACE_COUNT
 			 */
-			async_serialize_end();
 			free(devs);
 			continue;
@@ -388,5 +457,4 @@
 		if (rc != EOK) {
 			async_wait_for(req, NULL);
-			async_serialize_end();
 			free(devs);
 			return 0;
@@ -395,5 +463,4 @@
 		sysarg_t retval;
 		async_wait_for(req, &retval);
-		async_serialize_end();
 		
 		if (retval != EOK)
@@ -407,12 +474,10 @@
 size_t devmap_get_devices(devmap_handle_t ns_handle, dev_desc_t **data)
 {
-	int phone = devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return 0;
-	
-	/* Loop until namespaces read succesful */
+	/* Loop until devices read succesful */
 	while (true) {
-		size_t count = devmap_count_devices_internal(phone, ns_handle);
+		async_exch_t *exch = devmap_exchange_begin_blocking(DEVMAP_CLIENT);
+		size_t count = devmap_count_devices_internal(exch, ns_handle);
+		devmap_exchange_end(exch);
+		
 		if (count == 0)
 			return 0;
@@ -422,10 +487,12 @@
 			return 0;
 		
-		async_serialize_start();
+		exch = devmap_exchange_begin(DEVMAP_CLIENT);
 		
 		ipc_call_t answer;
-		aid_t req = async_send_1(phone, DEVMAP_GET_DEVICES, ns_handle, &answer);
-		
-		int rc = async_data_read_start(phone, devs, count * sizeof(dev_desc_t));
+		aid_t req = async_send_1(exch, DEVMAP_GET_DEVICES, ns_handle, &answer);
+		int rc = async_data_read_start(exch, devs, count * sizeof(dev_desc_t));
+		
+		devmap_exchange_end(exch);
+		
 		if (rc == EOVERFLOW) {
 			/*
@@ -433,5 +500,4 @@
 			 * the last call of DEVMAP_DEVICE_GET_DEVICE_COUNT
 			 */
-			async_serialize_end();
 			free(devs);
 			continue;
@@ -440,5 +506,4 @@
 		if (rc != EOK) {
 			async_wait_for(req, NULL);
-			async_serialize_end();
 			free(devs);
 			return 0;
@@ -447,5 +512,4 @@
 		sysarg_t retval;
 		async_wait_for(req, &retval);
-		async_serialize_end();
 		
 		if (retval != EOK)
Index: uspace/lib/c/generic/devmap_obsolete.c
===================================================================
--- uspace/lib/c/generic/devmap_obsolete.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/generic/devmap_obsolete.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2007 Josef Cejka
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <str.h>
+#include <ipc/services.h>
+#include <ns.h>
+#include <ns_obsolete.h>
+#include <ipc/devmap.h>
+#include <devmap_obsolete.h>
+#include <async.h>
+#include <async_obsolete.h>
+#include <errno.h>
+#include <malloc.h>
+#include <bool.h>
+
+static int devmap_phone_driver = -1;
+static int devmap_phone_client = -1;
+
+/** Get phone to device mapper task. */
+int devmap_obsolete_get_phone(devmap_interface_t iface, unsigned int flags)
+{
+	switch (iface) {
+	case DEVMAP_DRIVER:
+		if (devmap_phone_driver >= 0)
+			return devmap_phone_driver;
+		
+		if (flags & IPC_FLAG_BLOCKING)
+			devmap_phone_driver = service_obsolete_connect_blocking(SERVICE_DEVMAP,
+			    DEVMAP_DRIVER, 0);
+		else
+			devmap_phone_driver = service_obsolete_connect(SERVICE_DEVMAP,
+			    DEVMAP_DRIVER, 0);
+		
+		return devmap_phone_driver;
+	case DEVMAP_CLIENT:
+		if (devmap_phone_client >= 0)
+			return devmap_phone_client;
+		
+		if (flags & IPC_FLAG_BLOCKING)
+			devmap_phone_client = service_obsolete_connect_blocking(SERVICE_DEVMAP,
+			    DEVMAP_CLIENT, 0);
+		else
+			devmap_phone_client = service_obsolete_connect(SERVICE_DEVMAP,
+			    DEVMAP_CLIENT, 0);
+		
+		return devmap_phone_client;
+	default:
+		return -1;
+	}
+}
+
+void devmap_obsolete_hangup_phone(devmap_interface_t iface)
+{
+	switch (iface) {
+	case DEVMAP_DRIVER:
+		if (devmap_phone_driver >= 0) {
+			async_obsolete_hangup(devmap_phone_driver);
+			devmap_phone_driver = -1;
+		}
+		break;
+	case DEVMAP_CLIENT:
+		if (devmap_phone_client >= 0) {
+			async_obsolete_hangup(devmap_phone_client);
+			devmap_phone_client = -1;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+int devmap_obsolete_device_connect(devmap_handle_t handle, unsigned int flags)
+{
+	int phone;
+	
+	if (flags & IPC_FLAG_BLOCKING) {
+		phone = service_obsolete_connect_blocking(SERVICE_DEVMAP,
+		    DEVMAP_CONNECT_TO_DEVICE, handle);
+	} else {
+		phone = service_obsolete_connect(SERVICE_DEVMAP,
+		    DEVMAP_CONNECT_TO_DEVICE, handle);
+	}
+	
+	return phone;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/io/console.c
===================================================================
--- uspace/lib/c/generic/io/console.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/io/console.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -37,73 +37,204 @@
 #include <libc.h>
 #include <async.h>
+#include <errno.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <vfs/vfs_sess.h>
 #include <io/console.h>
 #include <ipc/console.h>
 
-void console_clear(int phone)
-{
-	async_msg_0(phone, CONSOLE_CLEAR);
-}
-
-int console_get_size(int phone, sysarg_t *cols, sysarg_t *rows)
-{
-	return async_req_0_2(phone, CONSOLE_GET_SIZE, cols, rows);
-}
-
-void console_set_style(int phone, uint8_t style)
-{
-	async_msg_1(phone, CONSOLE_SET_STYLE, style);
-}
-
-void console_set_color(int phone, uint8_t fg_color, uint8_t bg_color,
+console_ctrl_t *console_init(FILE *ifile, FILE *ofile)
+{
+	console_ctrl_t *ctrl = malloc(sizeof(console_ctrl_t));
+	if (!ctrl)
+		return NULL;
+	
+	ctrl->input_sess = fsession(EXCHANGE_SERIALIZE, ifile);
+	if (!ctrl->input_sess) {
+		free(ctrl);
+		return NULL;
+	}
+	
+	ctrl->output_sess = fsession(EXCHANGE_SERIALIZE, ofile);
+	if (!ctrl->output_sess) {
+		free(ctrl);
+		return NULL;
+	}
+	
+	ctrl->input = ifile;
+	ctrl->output = ofile;
+	ctrl->input_aid = 0;
+	
+	return ctrl;
+}
+
+void console_done(console_ctrl_t *ctrl)
+{
+	free(ctrl);
+}
+
+bool console_kcon(void)
+{
+#if 0
+	return __SYSCALL0(SYS_DEBUG_ACTIVATE_CONSOLE);
+#endif
+	
+	return false;
+}
+
+void console_flush(console_ctrl_t *ctrl)
+{
+	fflush(ctrl->output);
+}
+
+void console_clear(console_ctrl_t *ctrl)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_0(exch, CONSOLE_CLEAR);
+	async_exchange_end(exch);
+}
+
+int console_get_size(console_ctrl_t *ctrl, sysarg_t *cols, sysarg_t *rows)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	int rc = async_req_0_2(exch, CONSOLE_GET_SIZE, cols, rows);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+void console_set_style(console_ctrl_t *ctrl, uint8_t style)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_1(exch, CONSOLE_SET_STYLE, style);
+	async_exchange_end(exch);
+}
+
+void console_set_color(console_ctrl_t *ctrl, uint8_t fg_color, uint8_t bg_color,
     uint8_t flags)
 {
-	async_msg_3(phone, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
-}
-
-void console_set_rgb_color(int phone, uint32_t fg_color, uint32_t bg_color)
-{
-	async_msg_2(phone, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
-}
-
-void console_cursor_visibility(int phone, bool show)
-{
-	async_msg_1(phone, CONSOLE_CURSOR_VISIBILITY, (show != false));
-}
-
-int console_get_color_cap(int phone, sysarg_t *ccap)
-{
-	return async_req_0_1(phone, CONSOLE_GET_COLOR_CAP, ccap);
-}
-
-void console_kcon_enable(int phone)
-{
-	async_msg_0(phone, CONSOLE_KCON_ENABLE);
-}
-
-int console_get_pos(int phone, sysarg_t *col, sysarg_t *row)
-{
-	return async_req_0_2(phone, CONSOLE_GET_POS, col, row);
-}
-
-void console_set_pos(int phone, sysarg_t col, sysarg_t row)
-{
-	async_msg_2(phone, CONSOLE_GOTO, col, row);
-}
-
-bool console_get_event(int phone, console_event_t *event)
-{
-	sysarg_t type;
-	sysarg_t key;
-	sysarg_t mods;
-	sysarg_t c;
-	
-	int rc = async_req_0_4(phone, CONSOLE_GET_EVENT, &type, &key, &mods, &c);
-	if (rc < 0)
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_3(exch, CONSOLE_SET_COLOR, fg_color, bg_color, flags);
+	async_exchange_end(exch);
+}
+
+void console_set_rgb_color(console_ctrl_t *ctrl, uint32_t fg_color,
+    uint32_t bg_color)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_2(exch, CONSOLE_SET_RGB_COLOR, fg_color, bg_color);
+	async_exchange_end(exch);
+}
+
+void console_cursor_visibility(console_ctrl_t *ctrl, bool show)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_1(exch, CONSOLE_CURSOR_VISIBILITY, (show != false));
+	async_exchange_end(exch);
+}
+
+int console_get_color_cap(console_ctrl_t *ctrl, sysarg_t *ccap)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	int rc = async_req_0_1(exch, CONSOLE_GET_COLOR_CAP, ccap);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+int console_get_pos(console_ctrl_t *ctrl, sysarg_t *col, sysarg_t *row)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	int rc = async_req_0_2(exch, CONSOLE_GET_POS, col, row);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+void console_set_pos(console_ctrl_t *ctrl, sysarg_t col, sysarg_t row)
+{
+	async_exch_t *exch = async_exchange_begin(ctrl->output_sess);
+	async_msg_2(exch, CONSOLE_GOTO, col, row);
+	async_exchange_end(exch);
+}
+
+bool console_get_kbd_event(console_ctrl_t *ctrl, kbd_event_t *event)
+{
+	if (ctrl->input_aid == 0) {
+		sysarg_t type;
+		sysarg_t key;
+		sysarg_t mods;
+		sysarg_t c;
+		
+		async_exch_t *exch = async_exchange_begin(ctrl->input_sess);
+		int rc = async_req_0_4(exch, CONSOLE_GET_EVENT, &type, &key, &mods, &c);
+		async_exchange_end(exch);
+		
+		if (rc != EOK) {
+			errno = rc;
+			return false;
+		}
+		
+		event->type = type;
+		event->key = key;
+		event->mods = mods;
+		event->c = c;
+	} else {
+		sysarg_t retval;
+		async_wait_for(ctrl->input_aid, &retval);
+		
+		ctrl->input_aid = 0;
+		
+		if (retval != EOK) {
+			errno = (int) retval;
+			return false;
+		}
+		
+		event->type = IPC_GET_ARG1(ctrl->input_call);
+		event->key = IPC_GET_ARG2(ctrl->input_call);
+		event->mods = IPC_GET_ARG3(ctrl->input_call);
+		event->c = IPC_GET_ARG4(ctrl->input_call);
+	}
+	
+	return true;
+}
+
+bool console_get_kbd_event_timeout(console_ctrl_t *ctrl, kbd_event_t *event,
+    suseconds_t *timeout)
+{
+	struct timeval t0;
+	gettimeofday(&t0, NULL);
+	
+	if (ctrl->input_aid == 0) {
+		async_exch_t *exch = async_exchange_begin(ctrl->input_sess);
+		ctrl->input_aid = async_send_0(exch, CONSOLE_GET_EVENT,
+		    &ctrl->input_call);
+		async_exchange_end(exch);
+	}
+	
+	sysarg_t retval;
+	int rc = async_wait_timeout(ctrl->input_aid, &retval, *timeout);
+	if (rc != EOK) {
+		*timeout = 0;
+		errno = rc;
 		return false;
-	
-	event->type = type;
-	event->key = key;
-	event->mods = mods;
-	event->c = c;
+	}
+	
+	ctrl->input_aid = 0;
+	
+	if (retval != EOK) {
+		errno = (int) retval;
+		return false;
+	}
+	
+	event->type = IPC_GET_ARG1(ctrl->input_call);
+	event->key = IPC_GET_ARG2(ctrl->input_call);
+	event->mods = IPC_GET_ARG3(ctrl->input_call);
+	event->c = IPC_GET_ARG4(ctrl->input_call);
+	
+	/* Update timeout */
+	struct timeval t1;
+	gettimeofday(&t1, NULL);
+	*timeout -= tv_sub(&t1, &t0);
 	
 	return true;
Index: uspace/lib/c/generic/io/io.c
===================================================================
--- uspace/lib/c/generic/io/io.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/io/io.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -44,7 +44,9 @@
 #include <io/klog.h>
 #include <vfs/vfs.h>
+#include <vfs/vfs_sess.h>
 #include <ipc/devmap.h>
 #include <adt/list.h>
 #include "../private/io.h"
+#include "../private/stdio.h"
 
 static void _ffillbuf(FILE *stream);
@@ -56,5 +58,5 @@
 	.eof = true,
 	.klog = false,
-	.phone = -1,
+	.sess = NULL,
 	.btype = _IONBF,
 	.buf = NULL,
@@ -70,5 +72,5 @@
 	.eof = false,
 	.klog = true,
-	.phone = -1,
+	.sess = NULL,
 	.btype = _IOLBF,
 	.buf = NULL,
@@ -84,5 +86,5 @@
 	.eof = false,
 	.klog = true,
-	.phone = -1,
+	.sess = NULL,
 	.btype = _IONBF,
 	.buf = NULL,
@@ -255,5 +257,5 @@
 	stream->eof = false;
 	stream->klog = false;
-	stream->phone = -1;
+	stream->sess = NULL;
 	stream->need_sync = false;
 	_setvbuf(stream);
@@ -277,5 +279,5 @@
 	stream->eof = false;
 	stream->klog = false;
-	stream->phone = -1;
+	stream->sess = NULL;
 	stream->need_sync = false;
 	_setvbuf(stream);
@@ -309,5 +311,5 @@
 	stream->eof = false;
 	stream->klog = false;
-	stream->phone = -1;
+	stream->sess = NULL;
 	stream->need_sync = false;
 	_setvbuf(stream);
@@ -324,6 +326,6 @@
 	fflush(stream);
 	
-	if (stream->phone >= 0)
-		async_hangup(stream->phone);
+	if (stream->sess != NULL)
+		async_hangup(stream->sess);
 	
 	if (stream->fd >= 0)
@@ -732,5 +734,5 @@
 	}
 	
-	if (stream->fd >= 0 && stream->need_sync) {
+	if ((stream->fd >= 0) && (stream->need_sync)) {
 		/**
 		 * Better than syncing always, but probably still not the
@@ -770,14 +772,14 @@
 }
 
-int fphone(FILE *stream)
+async_sess_t *fsession(exch_mgmt_t mgmt, FILE *stream)
 {
 	if (stream->fd >= 0) {
-		if (stream->phone < 0)
-			stream->phone = fd_phone(stream->fd);
-		
-		return stream->phone;
-	}
-	
-	return -1;
+		if (stream->sess == NULL)
+			stream->sess = fd_session(mgmt, stream->fd);
+		
+		return stream->sess;
+	}
+	
+	return NULL;
 }
 
Index: uspace/lib/c/generic/ipc.c
===================================================================
--- uspace/lib/c/generic/ipc.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/ipc.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -632,4 +632,22 @@
 }
 
+/** Request cloned connection.
+ *
+ * @param phoneid Phone handle used for contacting the other side.
+ *
+ * @return Cloned phone handle on success or a negative error code.
+ *
+ */
+int ipc_connect_me(int phoneid)
+{
+	sysarg_t newphid;
+	int res = ipc_call_sync_0_5(phoneid, IPC_M_CONNECT_ME, NULL, NULL,
+	    NULL, NULL, &newphid);
+	if (res)
+		return res;
+	
+	return newphid;
+}
+
 /** Request new connection.
  *
Index: uspace/lib/c/generic/ipc/ns.c
===================================================================
--- uspace/lib/c/generic/ipc/ns.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#include <async.h>
-#include <ipc/ns.h>
-
-int service_register(sysarg_t service)
-{
-	return async_connect_to_me(PHONE_NS, service, 0, 0, NULL);
-}
-
-int service_connect(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
-{
-	return async_connect_me_to(PHONE_NS, service, arg2, arg3);
-}
-
-int service_connect_blocking(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
-{
-	return async_connect_me_to_blocking(PHONE_NS, service, arg2, arg3);
-}
-
-/** @}
- */
Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/libc.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -49,5 +49,4 @@
 #include "private/libc.h"
 #include "private/async.h"
-#include "private/async_sess.h"
 #include "private/malloc.h"
 #include "private/io.h"
@@ -64,5 +63,4 @@
 	__malloc_init();
 	__async_init();
-	__async_sess_init();
 	
 	fibril_t *fibril = fibril_setup();
Index: uspace/lib/c/generic/loader.c
===================================================================
--- uspace/lib/c/generic/loader.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/loader.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -35,5 +35,5 @@
 #include <ipc/loader.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <libc.h>
 #include <task.h>
@@ -44,4 +44,5 @@
 #include <vfs/vfs.h>
 #include <loader/loader.h>
+#include "private/loader.h"
 
 /** Connect to a new program loader.
@@ -63,13 +64,16 @@
 loader_t *loader_connect(void)
 {
-	int phone_id = service_connect_blocking(SERVICE_LOAD, 0, 0);
-	if (phone_id < 0)
-		return NULL;
-	
 	loader_t *ldr = malloc(sizeof(loader_t));
 	if (ldr == NULL)
 		return NULL;
 	
-	ldr->phone_id = phone_id;
+	async_sess_t *sess =
+	    service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOAD, 0, 0);
+	if (sess == NULL) {
+		free(ldr);
+		return NULL;
+	}
+	
+	ldr->sess = sess;
 	return ldr;
 }
@@ -88,15 +92,19 @@
 {
 	/* Get task ID. */
-	ipc_call_t answer;
-	aid_t req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
-	int rc = async_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	
-	sysarg_t retval;
-	async_wait_for(req, &retval);
-	return (int) retval;
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOADER_GET_TASKID, &answer);
+	sysarg_t rc = async_data_read_start(exch, task_id, sizeof(task_id_t));
+	
+	async_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return (int) rc;
+	}
+	
+	async_wait_for(req, &rc);
+	return (int) rc;
 }
 
@@ -112,26 +120,29 @@
 int loader_set_cwd(loader_t *ldr)
 {
-	char *cwd;
-	size_t len;
-
-	cwd = (char *) malloc(MAX_PATH_LEN + 1);
+	char *cwd = (char *) malloc(MAX_PATH_LEN + 1);
 	if (!cwd)
 		return ENOMEM;
+	
 	if (!getcwd(cwd, MAX_PATH_LEN + 1))
-		str_cpy(cwd, MAX_PATH_LEN + 1, "/"); 
-	len = str_length(cwd);
-	
-	ipc_call_t answer;
-	aid_t req = async_send_0(ldr->phone_id, LOADER_SET_CWD, &answer);
-	int rc = async_data_write_start(ldr->phone_id, cwd, len);
+		str_cpy(cwd, MAX_PATH_LEN + 1, "/");
+	
+	size_t len = str_length(cwd);
+	
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOADER_SET_CWD, &answer);
+	sysarg_t rc = async_data_write_start(exch, cwd, len);
+	
+	async_exchange_end(exch);
 	free(cwd);
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	
-	sysarg_t retval;
-	async_wait_for(req, &retval);
-	return (int) retval;
+	
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return (int) rc;
+	}
+	
+	async_wait_for(req, &rc);
+	return (int) rc;
 }
 
@@ -153,21 +164,23 @@
 	char *pa = absolutize(path, &pa_len);
 	if (!pa)
-		return 0;
+		return ENOMEM;
 	
 	/* Send program pathname */
-	ipc_call_t answer;
-	aid_t req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
-	int rc = async_data_write_start(ldr->phone_id, (void *) pa, pa_len);
-	if (rc != EOK) {
-		free(pa);
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOADER_SET_PATHNAME, &answer);
+	sysarg_t rc = async_data_write_start(exch, (void *) pa, pa_len);
+	
+	async_exchange_end(exch);
 	free(pa);
 	
-	sysarg_t retval;
-	async_wait_for(req, &retval);
-	return (int) retval;
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return (int) rc;
+	}
+	
+	async_wait_for(req, &rc);
+	return (int) rc;
 }
 
@@ -212,20 +225,21 @@
 	
 	/* Send serialized arguments to the loader */
-	ipc_call_t answer;
-	aid_t req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
-	sysarg_t rc = async_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	
-	async_wait_for(req, &rc);
-	if (rc != EOK)
-		return rc;
-	
-	/* Free temporary buffer */
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOADER_SET_ARGS, &answer);
+	sysarg_t rc = async_data_write_start(exch, (void *) arg_buf,
+	    buffer_size);
+	
+	async_exchange_end(exch);
 	free(arg_buf);
 	
-	return EOK;
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return (int) rc;
+	}
+	
+	async_wait_for(req, &rc);
+	return (int) rc;
 }
 
@@ -266,21 +280,21 @@
 	
 	/* Send serialized files to the loader */
-	ipc_call_t answer;
-	aid_t req = async_send_0(ldr->phone_id, LOADER_SET_FILES, &answer);
-	sysarg_t rc = async_data_write_start(ldr->phone_id, (void *) files_buf,
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_0(exch, LOADER_SET_FILES, &answer);
+	sysarg_t rc = async_data_write_start(exch, (void *) files_buf,
 	    count * sizeof(fdi_node_t));
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-	
-	async_wait_for(req, &rc);
-	if (rc != EOK)
-		return rc;
-	
-	/* Free temporary buffer */
+	
+	async_exchange_end(exch);
 	free(files_buf);
 	
-	return EOK;
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return (int) rc;
+	}
+	
+	async_wait_for(req, &rc);
+	return (int) rc;
 }
 
@@ -297,5 +311,9 @@
 int loader_load_program(loader_t *ldr)
 {
-	return (int) async_req_0_0(ldr->phone_id, LOADER_LOAD);
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	int rc = async_req_0_0(exch, LOADER_LOAD);
+	async_exchange_end(exch);
+	
+	return rc;
 }
 
@@ -306,6 +324,6 @@
  * the task and its thread is stopped.
  *
- * After using this function, no further operations must be performed
- * on the loader structure. It should be de-allocated using free().
+ * After using this function, no further operations can be performed
+ * on the loader structure and it is deallocated.
  *
  * @param ldr Loader connection structure.
@@ -316,10 +334,14 @@
 int loader_run(loader_t *ldr)
 {
-	int rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
+	async_exch_t *exch = async_exchange_begin(ldr->sess);
+	int rc = async_req_0_0(exch, LOADER_RUN);
+	async_exchange_end(exch);
+	
 	if (rc != EOK)
 		return rc;
 	
-	async_hangup(ldr->phone_id);
-	ldr->phone_id = 0;
+	async_hangup(ldr->sess);
+	free(ldr);
+	
 	return EOK;
 }
@@ -327,7 +349,7 @@
 /** Cancel the loader session.
  *
- * Tells the loader not to load any program and terminate.
- * After using this function, no further operations must be performed
- * on the loader structure. It should be de-allocated using free().
+ * Tell the loader not to load any program and terminate.
+ * After using this function, no further operations can be performed
+ * on the loader structure and it is deallocated.
  *
  * @param ldr Loader connection structure.
@@ -338,6 +360,6 @@
 void loader_abort(loader_t *ldr)
 {
-	async_hangup(ldr->phone_id);
-	ldr->phone_id = 0;
+	async_hangup(ldr->sess);
+	free(ldr);
 }
 
Index: uspace/lib/c/generic/net/icmp_api.c
===================================================================
--- uspace/lib/c/generic/net/icmp_api.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/net/icmp_api.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -42,4 +42,5 @@
 #include <net/ip_codes.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <sys/types.h>
 #include <sys/time.h>
@@ -83,9 +84,9 @@
 		return EINVAL;
 
-	message_id = async_send_5(icmp_phone, NET_ICMP_ECHO, size, timeout, ttl,
+	message_id = async_obsolete_send_5(icmp_phone, NET_ICMP_ECHO, size, timeout, ttl,
 	    tos, (sysarg_t) dont_fragment, NULL);
 
 	/* Send the address */
-	async_data_write_start(icmp_phone, addr, (size_t) addrlen);
+	async_obsolete_data_write_start(icmp_phone, addr, (size_t) addrlen);
 
 	async_wait_for(message_id, &result);
Index: uspace/lib/c/generic/net/modules.c
===================================================================
--- uspace/lib/c/generic/net/modules.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/net/modules.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -40,4 +40,5 @@
 
 #include <async.h>
+#include <async_obsolete.h>
 #include <malloc.h>
 #include <errno.h>
@@ -45,7 +46,9 @@
 #include <ipc/services.h>
 #include <net/modules.h>
+#include <ns.h>
+#include <ns_obsolete.h>
 
 /** The time between connect requests in microseconds. */
-#define MODULE_WAIT_TIME	(10 * 1000)
+#define MODULE_WAIT_TIME  (10 * 1000)
 
 /** Answer a call.
@@ -138,7 +141,7 @@
 	if (phone >= 0) {
 		/* Request the bidirectional connection */
-		int rc = async_connect_to_me(phone, arg1, arg2, arg3, client_receiver);
+		int rc = async_obsolete_connect_to_me(phone, arg1, arg2, arg3, client_receiver);
 		if (rc != EOK) {
-			async_hangup(phone);
+			async_obsolete_hangup(phone);
 			return rc;
 		}
@@ -172,8 +175,8 @@
 	/* If no timeout is set */
 	if (timeout <= 0)
-		return async_connect_me_to_blocking(PHONE_NS, need, 0, 0);
-
+		return service_obsolete_connect_blocking(need, 0, 0);
+	
 	while (true) {
-		phone = async_connect_me_to(PHONE_NS, need, 0, 0);
+		phone = service_obsolete_connect(need, 0, 0);
 		if ((phone >= 0) || (phone != ENOENT))
 			return phone;
Index: uspace/lib/c/generic/net/socket_client.c
===================================================================
--- uspace/lib/c/generic/net/socket_client.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/net/socket_client.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -39,4 +39,5 @@
 #include <assert.h>
 #include <async.h>
+#include <async_obsolete.h>
 #include <fibril_synch.h>
 #include <stdint.h>
@@ -472,5 +473,5 @@
 	}
 
-	rc = (int) async_req_3_3(phone, NET_SOCKET, socket_id, 0, service, NULL,
+	rc = (int) async_obsolete_req_3_3(phone, NET_SOCKET, socket_id, 0, service, NULL,
 	    &fragment_size, &header_size);
 	if (rc != EOK) {
@@ -493,5 +494,5 @@
 		dyn_fifo_destroy(&socket->accepted);
 		free(socket);
-		async_msg_3(phone, NET_SOCKET_CLOSE, (sysarg_t) socket_id, 0,
+		async_obsolete_msg_3(phone, NET_SOCKET_CLOSE, (sysarg_t) socket_id, 0,
 		    service);
 		return rc;
@@ -538,8 +539,8 @@
 
 	/* Request the message */
-	message_id = async_send_3(socket->phone, message,
+	message_id = async_obsolete_send_3(socket->phone, message,
 	    (sysarg_t) socket->socket_id, arg2, socket->service, NULL);
 	/* Send the address */
-	async_data_write_start(socket->phone, data, datalength);
+	async_obsolete_data_write_start(socket->phone, data, datalength);
 
 	fibril_rwlock_read_unlock(&socket_globals.lock);
@@ -598,5 +599,5 @@
 
 	/* Request listen backlog change */
-	result = (int) async_req_3_0(socket->phone, NET_SOCKET_LISTEN,
+	result = (int) async_obsolete_req_3_0(socket->phone, NET_SOCKET_LISTEN,
 	    (sysarg_t) socket->socket_id, (sysarg_t) backlog, socket->service);
 
@@ -681,10 +682,10 @@
 
 	/* Request accept */
-	message_id = async_send_5(socket->phone, NET_SOCKET_ACCEPT,
+	message_id = async_obsolete_send_5(socket->phone, NET_SOCKET_ACCEPT,
 	    (sysarg_t) socket->socket_id, 0, socket->service, 0,
 	    new_socket->socket_id, &answer);
 
 	/* Read address */
-	async_data_read_start(socket->phone, cliaddr, *addrlen);
+	async_obsolete_data_read_start(socket->phone, cliaddr, *addrlen);
 	fibril_rwlock_write_unlock(&socket_globals.lock);
 	async_wait_for(message_id, &ipc_result);
@@ -780,5 +781,5 @@
 
 	/* Request close */
-	rc = (int) async_req_3_0(socket->phone, NET_SOCKET_CLOSE,
+	rc = (int) async_obsolete_req_3_0(socket->phone, NET_SOCKET_CLOSE,
 	    (sysarg_t) socket->socket_id, 0, socket->service);
 	if (rc != EOK) {
@@ -853,5 +854,5 @@
 
 	/* Request send */
-	message_id = async_send_5(socket->phone, message,
+	message_id = async_obsolete_send_5(socket->phone, message,
 	    (sysarg_t) socket->socket_id,
 	    (fragments == 1 ? datalength : socket->data_fragment_size),
@@ -860,11 +861,11 @@
 	/* Send the address if given */
 	if (!toaddr ||
-	    (async_data_write_start(socket->phone, toaddr, addrlen) == EOK)) {
+	    (async_obsolete_data_write_start(socket->phone, toaddr, addrlen) == EOK)) {
 		if (fragments == 1) {
 			/* Send all if only one fragment */
-			async_data_write_start(socket->phone, data, datalength);
+			async_obsolete_data_write_start(socket->phone, data, datalength);
 		} else {
 			/* Send the first fragment */
-			async_data_write_start(socket->phone, data,
+			async_obsolete_data_write_start(socket->phone, data,
 			    socket->data_fragment_size - socket->header_size);
 			data = ((const uint8_t *) data) +
@@ -873,5 +874,5 @@
 			/* Send the middle fragments */
 			while (--fragments > 1) {
-				async_data_write_start(socket->phone, data,
+				async_obsolete_data_write_start(socket->phone, data,
 				    socket->data_fragment_size);
 				data = ((const uint8_t *) data) +
@@ -880,5 +881,5 @@
 
 			/* Send the last fragment */
-			async_data_write_start(socket->phone, data,
+			async_obsolete_data_write_start(socket->phone, data,
 			    (datalength + socket->header_size) %
 			    socket->data_fragment_size);
@@ -1038,5 +1039,5 @@
 
 		/* Request packet data */
-		message_id = async_send_4(socket->phone, message,
+		message_id = async_obsolete_send_4(socket->phone, message,
 		    (sysarg_t) socket->socket_id, 0, socket->service,
 		    (sysarg_t) flags, &answer);
@@ -1044,8 +1045,8 @@
 		/* Read the address if desired */
 		if(!fromaddr ||
-		    (async_data_read_start(socket->phone, fromaddr,
+		    (async_obsolete_data_read_start(socket->phone, fromaddr,
 		    *addrlen) == EOK)) {
 			/* Read the fragment lengths */
-			if (async_data_read_start(socket->phone, lengths,
+			if (async_obsolete_data_read_start(socket->phone, lengths,
 			    sizeof(int) * (fragments + 1)) == EOK) {
 				if (lengths[fragments] <= datalength) {
@@ -1054,5 +1055,5 @@
 					for (index = 0; index < fragments;
 					    ++index) {
-						async_data_read_start(
+						async_obsolete_data_read_start(
 						    socket->phone, data,
 						    lengths[index]);
@@ -1067,5 +1068,5 @@
 	} else { /* fragments == 1 */
 		/* Request packet data */
-		message_id = async_send_4(socket->phone, message,
+		message_id = async_obsolete_send_4(socket->phone, message,
 		    (sysarg_t) socket->socket_id, 0, socket->service,
 		    (sysarg_t) flags, &answer);
@@ -1073,8 +1074,8 @@
 		/* Read the address if desired */
 		if (!fromaddr ||
-		    (async_data_read_start(socket->phone, fromaddr,
+		    (async_obsolete_data_read_start(socket->phone, fromaddr,
 		        *addrlen) == EOK)) {
 			/* Read all if only one fragment */
-			async_data_read_start(socket->phone, data, datalength);
+			async_obsolete_data_read_start(socket->phone, data, datalength);
 		}
 	}
@@ -1190,13 +1191,13 @@
 
 	/* Request option value */
-	message_id = async_send_3(socket->phone, NET_SOCKET_GETSOCKOPT,
+	message_id = async_obsolete_send_3(socket->phone, NET_SOCKET_GETSOCKOPT,
 	    (sysarg_t) socket->socket_id, (sysarg_t) optname, socket->service,
 	    NULL);
 
 	/* Read the length */
-	if (async_data_read_start(socket->phone, optlen,
+	if (async_obsolete_data_read_start(socket->phone, optlen,
 	    sizeof(*optlen)) == EOK) {
 		/* Read the value */
-		async_data_read_start(socket->phone, value, *optlen);
+		async_obsolete_data_read_start(socket->phone, value, *optlen);
 	}
 
Index: uspace/lib/c/generic/ns.c
===================================================================
--- uspace/lib/c/generic/ns.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/generic/ns.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <ns.h>
+#include <ipc/ns.h>
+#include <async.h>
+#include <macros.h>
+#include "private/ns.h"
+
+int service_register(sysarg_t service)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	int rc = async_connect_to_me(exch, service, 0, 0, NULL);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+async_sess_t *service_connect(exch_mgmt_t mgmt, sysarg_t service, sysarg_t arg2,
+    sysarg_t arg3)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	async_sess_t *sess =
+	    async_connect_me_to(mgmt, exch, service, arg2, arg3);
+	async_exchange_end(exch);
+	
+	return sess;
+}
+
+async_sess_t *service_connect_blocking(exch_mgmt_t mgmt, sysarg_t service,
+    sysarg_t arg2, sysarg_t arg3)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	async_sess_t *sess =
+	    async_connect_me_to_blocking(mgmt, exch, service, arg2, arg3);
+	async_exchange_end(exch);
+	
+	return sess;
+}
+
+int ns_ping(void)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	int rc = async_req_0_0(exch, NS_PING);
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+int ns_intro(task_id_t id)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	int rc = async_req_2_0(exch, NS_ID_INTRO, LOWER32(id), UPPER32(id));
+	async_exchange_end(exch);
+	
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/ns_obsolete.c
===================================================================
--- uspace/lib/c/generic/ns_obsolete.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/generic/ns_obsolete.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <async_obsolete.h>
+#include <ns_obsolete.h>
+#include <kernel/ipc/ipc_methods.h>
+
+int service_obsolete_connect(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
+{
+	return async_obsolete_connect_me_to(PHONE_NS, service, arg2, arg3);
+}
+
+int service_obsolete_connect_blocking(sysarg_t service, sysarg_t arg2, sysarg_t arg3)
+{
+	return async_obsolete_connect_me_to_blocking(PHONE_NS, service, arg2, arg3);
+}
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/async.h
===================================================================
--- uspace/lib/c/generic/private/async.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/private/async.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -79,6 +79,20 @@
 } awaiter_t;
 
+/** Message data */
+typedef struct {
+	awaiter_t wdata;
+	
+	/** If reply was received. */
+	bool done;
+	
+	/** Pointer to where the answer data is stored. */
+	ipc_call_t *dataptr;
+	
+	sysarg_t retval;
+} amsg_t;
+
 extern void __async_init(void);
 extern void async_insert_timeout(awaiter_t *);
+extern void reply_received(void *, int, ipc_call_t *);
 
 #endif
Index: uspace/lib/c/generic/private/async_sess.h
===================================================================
--- uspace/lib/c/generic/private/async_sess.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ 	(revision )
@@ -1,43 +1,0 @@
-/*
- * Copyright (c) 2011 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_PRIVATE_ASYNC_SESS_H_
-#define LIBC_PRIVATE_ASYNC_SESS_H_
-
-extern void __async_sess_init(void);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/generic/private/loader.h
===================================================================
--- uspace/lib/c/generic/private/loader.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/generic/private/loader.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_LOADER_H_
+#define LIBC_PRIVATE_LOADER_H_
+
+#include <loader/loader.h>
+
+/** Abstraction of a loader connection */
+struct loader {
+	/** Session to the loader. */
+	async_sess_t *sess;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/ns.h
===================================================================
--- uspace/lib/c/generic/private/ns.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/generic/private/ns.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_NS_H_
+#define LIBC_PRIVATE_NS_H_
+
+#include <async.h>
+
+extern async_sess_t *session_ns;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/private/stdio.h
===================================================================
--- uspace/lib/c/generic/private/stdio.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/generic/private/stdio.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_STDIO_H_
+#define LIBC_PRIVATE_STDIO_H_
+
+#include <adt/list.h>
+#include <stdio.h>
+#include <async.h>
+
+struct _IO_FILE {
+	/** Linked list pointer. */
+	link_t link;
+	
+	/** Underlying file descriptor. */
+	int fd;
+	
+	/** Error indicator. */
+	int error;
+	
+	/** End-of-file indicator. */
+	int eof;
+	
+	/** Klog indicator */
+	int klog;
+	
+	/** Session to the file provider */
+	async_sess_t *sess;
+	
+	/**
+	 * Non-zero if the stream needs sync on fflush(). XXX change
+	 * console semantics so that sync is not needed.
+	 */
+	int need_sync;
+	
+	/** Buffering type */
+	enum _buffer_type btype;
+	
+	/** Buffer */
+	uint8_t *buf;
+	
+	/** Buffer size */
+	size_t buf_size;
+	
+	/** Buffer state */
+	enum _buffer_state buf_state;
+	
+	/** Buffer I/O pointer */
+	uint8_t *buf_head;
+	
+	/** Points to end of occupied space when in read mode. */
+	uint8_t *buf_tail;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/str_error.c
===================================================================
--- uspace/lib/c/generic/str_error.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/str_error.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -70,4 +70,5 @@
 	
 	/* Ad hoc descriptions of error codes interesting for USB. */
+	// FIXME: integrate these as first-class error values
 	switch (e) {
 		case EBADCHECKSUM:
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/task.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -35,7 +35,4 @@
 
 #include <task.h>
-#include <libc.h>
-#include <stdlib.h>
-#include <errno.h>
 #include <loader/loader.h>
 #include <stdarg.h>
@@ -43,5 +40,10 @@
 #include <ipc/ns.h>
 #include <macros.h>
+#include <assert.h>
 #include <async.h>
+#include <errno.h>
+#include <malloc.h>
+#include <libc.h>
+#include "private/ns.h"
 
 task_id_t task_get_id(void)
@@ -68,4 +70,6 @@
 int task_set_name(const char *name)
 {
+	assert(name);
+	
 	return __SYSCALL2(SYS_TASK_SET_NAME, (sysarg_t) name, str_size(name));
 }
@@ -88,23 +92,21 @@
  * loader API. Arguments are passed as a null-terminated array of strings.
  *
- * @param id 	If not NULL, the ID of the task is stored here on success.
- * @param path	Pathname of the binary to execute.
- * @param argv	Command-line arguments.
- *
- * @return	Zero on success or negative error code.
+ * @param id   If not NULL, the ID of the task is stored here on success.
+ * @param path Pathname of the binary to execute.
+ * @param argv Command-line arguments.
+ *
+ * @return Zero on success or negative error code.
+ *
  */
 int task_spawnv(task_id_t *id, const char *path, const char *const args[])
 {
-	loader_t *ldr;
-	task_id_t task_id;
-	int rc;
-
 	/* Connect to a program loader. */
-	ldr = loader_connect();
+	loader_t *ldr = loader_connect();
 	if (ldr == NULL)
 		return EREFUSED;
 	
 	/* Get task ID. */
-	rc = loader_get_task_id(ldr, &task_id);
+	task_id_t task_id;
+	int rc = loader_get_task_id(ldr, &task_id);
 	if (rc != EOK)
 		goto error;
@@ -163,6 +165,4 @@
 	
 	/* Success */
-	free(ldr);
-	
 	if (id != NULL)
 		*id = task_id;
@@ -182,19 +182,20 @@
  * loader API. Arguments are passed as a null-terminated list of arguments.
  *
- * @param id 	If not NULL, the ID of the task is stored here on success.
- * @param path	Pathname of the binary to execute.
- * @param ...	Command-line arguments.
- *
- * @return	Zero on success or negative error code.
+ * @param id   If not NULL, the ID of the task is stored here on success.
+ * @param path Pathname of the binary to execute.
+ * @param ...  Command-line arguments.
+ *
+ * @return Zero on success or negative error code.
+ *
  */
 int task_spawnl(task_id_t *task_id, const char *path, ...)
 {
+	/* Count the number of arguments. */
+	
 	va_list ap;
-	int rc, cnt;
 	const char *arg;
 	const char **arglist;
-
-	/* Count the number of arguments. */
-	cnt = 0;
+	int cnt = 0;
+	
 	va_start(ap, path);
 	do {
@@ -203,10 +204,10 @@
 	} while (arg != NULL);
 	va_end(ap);
-
+	
 	/* Allocate argument list. */
 	arglist = malloc(cnt * sizeof(const char *));
 	if (arglist == NULL)
 		return ENOMEM;
-
+	
 	/* Fill in arguments. */
 	cnt = 0;
@@ -217,8 +218,8 @@
 	} while (arg != NULL);
 	va_end(ap);
-
+	
 	/* Spawn task. */
-	rc = task_spawnv(task_id, path, arglist);
-
+	int rc = task_spawnv(task_id, path, arglist);
+	
 	/* Free argument list. */
 	free(arglist);
@@ -228,12 +229,16 @@
 int task_wait(task_id_t id, task_exit_t *texit, int *retval)
 {
+	assert(texit);
+	assert(retval);
+	
+	async_exch_t *exch = async_exchange_begin(session_ns);
 	sysarg_t te, rv;
-	int rc;
-
-	rc = (int) async_req_2_2(PHONE_NS, NS_TASK_WAIT, LOWER32(id),
+	int rc = (int) async_req_2_2(exch, NS_TASK_WAIT, LOWER32(id),
 	    UPPER32(id), &te, &rv);
+	async_exchange_end(exch);
+	
 	*texit = te;
 	*retval = rv;
-
+	
 	return rc;
 }
@@ -241,5 +246,9 @@
 int task_retval(int val)
 {
-	return (int) async_req_1_0(PHONE_NS, NS_RETVAL, val);
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	int rc = (int) async_req_1_0(exch, NS_RETVAL, val);
+	async_exchange_end(exch);
+	
+	return rc;
 }
 
Index: uspace/lib/c/generic/udebug.c
===================================================================
--- uspace/lib/c/generic/udebug.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/udebug.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -35,102 +35,108 @@
 #include <udebug.h>
 #include <sys/types.h>
+#include <kernel/ipc/ipc_methods.h>
 #include <async.h>
 
-int udebug_begin(int phoneid)
+int udebug_begin(async_sess_t *sess)
 {
-	return async_req_1_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_BEGIN);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_1_0(exch, IPC_M_DEBUG, UDEBUG_M_BEGIN);
 }
 
-int udebug_end(int phoneid)
+int udebug_end(async_sess_t *sess)
 {
-	return async_req_1_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_END);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_1_0(exch, IPC_M_DEBUG, UDEBUG_M_END);
 }
 
-int udebug_set_evmask(int phoneid, udebug_evmask_t mask)
+int udebug_set_evmask(async_sess_t *sess, udebug_evmask_t mask)
 {
-	return async_req_2_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_SET_EVMASK,
-		mask);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_2_0(exch, IPC_M_DEBUG, UDEBUG_M_SET_EVMASK, mask);
 }
 
-int udebug_thread_read(int phoneid, void *buffer, size_t n,
-	size_t *copied, size_t *needed)
+int udebug_thread_read(async_sess_t *sess, void *buffer, size_t n,
+    size_t *copied, size_t *needed)
 {
 	sysarg_t a_copied, a_needed;
-	int rc;
-
-	rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_THREAD_READ,
-		(sysarg_t)buffer, n, NULL, &a_copied, &a_needed);
-
-	*copied = (size_t)a_copied;
-	*needed = (size_t)a_needed;
-
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_3_3(exch, IPC_M_DEBUG, UDEBUG_M_THREAD_READ,
+	    (sysarg_t) buffer, n, NULL, &a_copied, &a_needed);
+	
+	*copied = (size_t) a_copied;
+	*needed = (size_t) a_needed;
+	
 	return rc;
 }
 
-int udebug_name_read(int phoneid, void *buffer, size_t n,
-	size_t *copied, size_t *needed)
+int udebug_name_read(async_sess_t *sess, void *buffer, size_t n,
+    size_t *copied, size_t *needed)
 {
 	sysarg_t a_copied, a_needed;
-	int rc;
-
-	rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_NAME_READ,
-		(sysarg_t)buffer, n, NULL, &a_copied, &a_needed);
-
-	*copied = (size_t)a_copied;
-	*needed = (size_t)a_needed;
-
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_3_3(exch, IPC_M_DEBUG, UDEBUG_M_NAME_READ,
+	    (sysarg_t) buffer, n, NULL, &a_copied, &a_needed);
+	
+	*copied = (size_t) a_copied;
+	*needed = (size_t) a_needed;
+	
 	return rc;
 }
 
-int udebug_areas_read(int phoneid, void *buffer, size_t n,
-	size_t *copied, size_t *needed)
+int udebug_areas_read(async_sess_t *sess, void *buffer, size_t n,
+    size_t *copied, size_t *needed)
 {
 	sysarg_t a_copied, a_needed;
-	int rc;
-
-	rc = async_req_3_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_AREAS_READ,
-		(sysarg_t)buffer, n, NULL, &a_copied, &a_needed);
-
-	*copied = (size_t)a_copied;
-	*needed = (size_t)a_needed;
-
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_3_3(exch, IPC_M_DEBUG, UDEBUG_M_AREAS_READ,
+	    (sysarg_t) buffer, n, NULL, &a_copied, &a_needed);
+	
+	*copied = (size_t) a_copied;
+	*needed = (size_t) a_needed;
+	
 	return rc;
 }
 
-int udebug_mem_read(int phoneid, void *buffer, uintptr_t addr, size_t n)
+int udebug_mem_read(async_sess_t *sess, void *buffer, uintptr_t addr, size_t n)
 {
-	return async_req_4_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_MEM_READ,
-	    (sysarg_t)buffer, addr, n);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_4_0(exch, IPC_M_DEBUG, UDEBUG_M_MEM_READ,
+	    (sysarg_t) buffer, addr, n);
 }
 
-int udebug_args_read(int phoneid, thash_t tid, sysarg_t *buffer)
+int udebug_args_read(async_sess_t *sess, thash_t tid, sysarg_t *buffer)
 {
-	return async_req_3_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_ARGS_READ,
-	    tid, (sysarg_t)buffer);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_3_0(exch, IPC_M_DEBUG, UDEBUG_M_ARGS_READ,
+	    tid, (sysarg_t) buffer);
 }
 
-int udebug_regs_read(int phoneid, thash_t tid, void *buffer)
+int udebug_regs_read(async_sess_t *sess, thash_t tid, void *buffer)
 {
-	return async_req_3_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_REGS_READ,
-	    tid, (sysarg_t)buffer);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_3_0(exch, IPC_M_DEBUG, UDEBUG_M_REGS_READ,
+	    tid, (sysarg_t) buffer);
 }
 
-int udebug_go(int phoneid, thash_t tid, udebug_event_t *ev_type,
+int udebug_go(async_sess_t *sess, thash_t tid, udebug_event_t *ev_type,
     sysarg_t *val0, sysarg_t *val1)
 {
 	sysarg_t a_ev_type;
-	int rc;
-
-	rc =  async_req_2_3(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_GO,
+	
+	async_exch_t *exch = async_exchange_begin(sess);
+	int rc = async_req_2_3(exch, IPC_M_DEBUG, UDEBUG_M_GO,
 	    tid, &a_ev_type, val0, val1);
-
+	
 	*ev_type = a_ev_type;
 	return rc;
 }
 
-int udebug_stop(int phoneid, thash_t tid)
+int udebug_stop(async_sess_t *sess, thash_t tid)
 {
-	return async_req_2_0(phoneid, IPC_M_DEBUG_ALL, UDEBUG_M_STOP,
-	    tid);
+	async_exch_t *exch = async_exchange_begin(sess);
+	return async_req_2_0(exch, IPC_M_DEBUG, UDEBUG_M_STOP, tid);
 }
 
Index: uspace/lib/c/generic/vfs/vfs.c
===================================================================
--- uspace/lib/c/generic/vfs/vfs.c	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/generic/vfs/vfs.c	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -33,6 +33,7 @@
  */
 
+#include <vfs/canonify.h>
 #include <vfs/vfs.h>
-#include <vfs/canonify.h>
+#include <vfs/vfs_sess.h>
 #include <macros.h>
 #include <stdlib.h>
@@ -44,5 +45,5 @@
 #include <sys/types.h>
 #include <ipc/services.h>
-#include <ipc/ns.h>
+#include <ns.h>
 #include <async.h>
 #include <fibril_synch.h>
@@ -54,8 +55,6 @@
 #include <ipc/devmap.h>
 
-static async_sess_t vfs_session;
-
-static FIBRIL_MUTEX_INITIALIZE(vfs_phone_mutex);
-static int vfs_phone = -1;
+static FIBRIL_MUTEX_INITIALIZE(vfs_mutex);
+static async_sess_t *vfs_sess = NULL;
 
 static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
@@ -65,9 +64,36 @@
 static size_t cwd_size = 0;
 
+/** Start an async exchange on the VFS session.
+ *
+ * @return New exchange.
+ *
+ */
+static async_exch_t *vfs_exchange_begin(void)
+{
+	fibril_mutex_lock(&vfs_mutex);
+	
+	while (vfs_sess == NULL)
+		vfs_sess = service_connect_blocking(EXCHANGE_PARALLEL, SERVICE_VFS,
+		    0, 0);
+	
+	fibril_mutex_unlock(&vfs_mutex);
+	
+	return async_exchange_begin(vfs_sess);
+}
+
+/** Finish an async exchange on the VFS session.
+ *
+ * @param exch Exchange to be finished.
+ *
+ */
+static void vfs_exchange_end(async_exch_t *exch)
+{
+	async_exchange_end(exch);
+}
+
 char *absolutize(const char *path, size_t *retlen)
 {
 	char *ncwd_path;
 	char *ncwd_path_nc;
-	size_t total_size; 
 
 	fibril_mutex_lock(&cwd_mutex);
@@ -78,16 +104,14 @@
 			return NULL;
 		}
-		total_size = cwd_size + 1 + size + 1;
-		ncwd_path_nc = malloc(total_size);
+		ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
 		if (!ncwd_path_nc) {
 			fibril_mutex_unlock(&cwd_mutex);
 			return NULL;
 		}
-		str_cpy(ncwd_path_nc, total_size, cwd_path);
+		str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
 		ncwd_path_nc[cwd_size] = '/';
 		ncwd_path_nc[cwd_size + 1] = '\0';
 	} else {
-		total_size = size + 1;
-		ncwd_path_nc = malloc(total_size);
+		ncwd_path_nc = malloc(size + 1);
 		if (!ncwd_path_nc) {
 			fibril_mutex_unlock(&cwd_mutex);
@@ -96,5 +120,5 @@
 		ncwd_path_nc[0] = '\0';
 	}
-	str_append(ncwd_path_nc, total_size, path);
+	str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
 	ncwd_path = canonify(ncwd_path_nc, retlen);
 	if (!ncwd_path) {
@@ -118,36 +142,4 @@
 }
 
-/** Connect to VFS service and create session. */
-static void vfs_connect(void)
-{
-	while (vfs_phone < 0)
-		vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0);
-	
-	async_session_create(&vfs_session, vfs_phone, 0);
-}
-
-/** Start an async exchange on the VFS session.
- *
- * @return		New phone to be used during the exchange.
- */
-static int vfs_exchange_begin(void)
-{
-	fibril_mutex_lock(&vfs_phone_mutex);
-	if (vfs_phone < 0)
-		vfs_connect();
-	fibril_mutex_unlock(&vfs_phone_mutex);
-
-	return async_exchange_begin(&vfs_session);
-}
-
-/** End an async exchange on the VFS session.
- *
- * @param phone		Phone used during the exchange.
- */
-static void vfs_exchange_end(int phone)
-{
-	async_exchange_end(&vfs_session, phone);
-}
-
 int mount(const char *fs_name, const char *mp, const char *fqdn,
     const char *opts, unsigned int flags)
@@ -186,11 +178,11 @@
 	}
 	
-	int vfs_phone = vfs_exchange_begin();
+	async_exch_t *exch = vfs_exchange_begin();
 
 	sysarg_t rc_orig;
-	aid_t req = async_send_2(vfs_phone, VFS_IN_MOUNT, devmap_handle, flags, NULL);
-	sysarg_t rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	aid_t req = async_send_2(exch, VFS_IN_MOUNT, devmap_handle, flags, NULL);
+	sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(mpa);
 		async_wait_for(req, &rc_orig);
@@ -205,7 +197,7 @@
 	}
 	
-	rc = async_data_write_start(vfs_phone, (void *) opts, str_size(opts));
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	rc = async_data_write_start(exch, (void *) opts, str_size(opts));
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(mpa);
 		async_wait_for(req, &rc_orig);
@@ -220,7 +212,7 @@
 	}
 	
-	rc = async_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	rc = async_data_write_start(exch, (void *) fs_name, str_size(fs_name));
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(mpa);
 		async_wait_for(req, &rc_orig);
@@ -236,7 +228,7 @@
 	
 	/* Ask VFS whether it likes fs_name. */
-	rc = async_req_0_0(vfs_phone, IPC_M_PING);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	rc = async_req_0_0(exch, VFS_IN_PING);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(mpa);
 		async_wait_for(req, &rc_orig);
@@ -251,5 +243,5 @@
 	}
 	
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(mpa);
 	async_wait_for(req, &rc);
@@ -273,10 +265,10 @@
 		return ENOMEM;
 	
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_0(vfs_phone, VFS_IN_UNMOUNT, NULL);
-	rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_0(exch, VFS_IN_UNMOUNT, NULL);
+	rc = async_data_write_start(exch, (void *) mpa, mpa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(mpa);
 		async_wait_for(req, &rc_orig);
@@ -288,5 +280,5 @@
 	
 
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(mpa);
 	async_wait_for(req, &rc);
@@ -297,12 +289,12 @@
 static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
 {
-	int vfs_phone = vfs_exchange_begin();
+	async_exch_t *exch = vfs_exchange_begin();
 	
 	ipc_call_t answer;
-	aid_t req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
-	sysarg_t rc = async_data_write_start(vfs_phone, abs, abs_size);
-	
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	aid_t req = async_send_3(exch, VFS_IN_OPEN, lflag, oflag, 0, &answer);
+	sysarg_t rc = async_data_write_start(exch, abs, abs_size);
+	
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 
 		sysarg_t rc_orig;
@@ -315,5 +307,5 @@
 	}
 	
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
 	
@@ -339,11 +331,11 @@
 int open_node(fdi_node_t *node, int oflag)
 {
-	int vfs_phone = vfs_exchange_begin();
+	async_exch_t *exch = vfs_exchange_begin();
 	
 	ipc_call_t answer;
-	aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle,
+	aid_t req = async_send_4(exch, VFS_IN_OPEN_NODE, node->fs_handle,
 	    node->devmap_handle, node->index, oflag, &answer);
 	
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 
 	sysarg_t rc;
@@ -360,11 +352,9 @@
 	sysarg_t rc;
 	
-	int vfs_phone = vfs_exchange_begin();
-	
-	rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
-	
-	vfs_exchange_end(vfs_phone);
-	
-	return (int)rc;
+	async_exch_t *exch = vfs_exchange_begin();
+	rc = async_req_1_0(exch, VFS_IN_CLOSE, fildes);
+	vfs_exchange_end(exch);
+	
+	return (int) rc;
 }
 
@@ -374,12 +364,11 @@
 	ipc_call_t answer;
 	aid_t req;
-
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
-	rc = async_data_read_start_generic(vfs_phone, (void *) buf, nbyte,
-	    IPC_XF_RESTRICT);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_1(exch, VFS_IN_READ, fildes, &answer);
+	rc = async_data_read_start(exch, (void *)buf, nbyte);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 
 		sysarg_t rc_orig;
@@ -391,5 +380,5 @@
 			return (ssize_t) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
 	if (rc == EOK)
@@ -404,12 +393,11 @@
 	ipc_call_t answer;
 	aid_t req;
-
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
-	rc = async_data_write_start_generic(vfs_phone, (void *) buf, nbyte,
-	    IPC_XF_RESTRICT);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer);
+	rc = async_data_write_start(exch, (void *)buf, nbyte);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 
 		sysarg_t rc_orig;
@@ -421,5 +409,5 @@
 			return (ssize_t) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
 	if (rc == EOK)
@@ -431,9 +419,7 @@
 int fsync(int fildes)
 {
-	int vfs_phone = vfs_exchange_begin();
-	
-	sysarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
-	
-	vfs_exchange_end(vfs_phone);
+	async_exch_t *exch = vfs_exchange_begin();
+	sysarg_t rc = async_req_1_0(exch, VFS_IN_SYNC, fildes);
+	vfs_exchange_end(exch);
 	
 	return (int) rc;
@@ -442,13 +428,13 @@
 off64_t lseek(int fildes, off64_t offset, int whence)
 {
-	int vfs_phone = vfs_exchange_begin();
+	async_exch_t *exch = vfs_exchange_begin();
 	
 	sysarg_t newoff_lo;
 	sysarg_t newoff_hi;
-	sysarg_t rc = async_req_4_2(vfs_phone, VFS_IN_SEEK, fildes,
+	sysarg_t rc = async_req_4_2(exch, VFS_IN_SEEK, fildes,
 	    LOWER32(offset), UPPER32(offset), whence,
 	    &newoff_lo, &newoff_hi);
 	
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	
 	if (rc != EOK)
@@ -462,9 +448,8 @@
 	sysarg_t rc;
 	
-	int vfs_phone = vfs_exchange_begin();
-	
-	rc = async_req_3_0(vfs_phone, VFS_IN_TRUNCATE, fildes,
+	async_exch_t *exch = vfs_exchange_begin();
+	rc = async_req_3_0(exch, VFS_IN_TRUNCATE, fildes,
 	    LOWER32(length), UPPER32(length));
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	
 	return (int) rc;
@@ -475,11 +460,11 @@
 	sysarg_t rc;
 	aid_t req;
-
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL);
-	rc = async_data_read_start(vfs_phone, (void *) stat, sizeof(struct stat));
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_1(exch, VFS_IN_FSTAT, fildes, NULL);
+	rc = async_data_read_start(exch, (void *) stat, sizeof(struct stat));
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 
 		sysarg_t rc_orig;
@@ -491,5 +476,5 @@
 			return (ssize_t) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	async_wait_for(req, &rc);
 
@@ -508,10 +493,10 @@
 		return ENOMEM;
 	
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
-	rc = async_data_write_start(vfs_phone, pa, pa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_0(exch, VFS_IN_STAT, NULL);
+	rc = async_data_write_start(exch, pa, pa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(pa);
 		async_wait_for(req, &rc_orig);
@@ -521,7 +506,7 @@
 			return (int) rc_orig;
 	}
-	rc = async_data_read_start(vfs_phone, stat, sizeof(struct stat));
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	rc = async_data_read_start(exch, stat, sizeof(struct stat));
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(pa);
 		async_wait_for(req, &rc_orig);
@@ -531,5 +516,5 @@
 			return (int) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(pa);
 	async_wait_for(req, &rc);
@@ -592,10 +577,10 @@
 		return ENOMEM;
 	
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
-	rc = async_data_write_start(vfs_phone, pa, pa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL);
+	rc = async_data_write_start(exch, pa, pa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(pa);
 
@@ -608,5 +593,5 @@
 			return (int) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(pa);
 	async_wait_for(req, &rc);
@@ -623,11 +608,11 @@
 	if (!pa)
 		return ENOMEM;
-
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
-	rc = async_data_write_start(vfs_phone, pa, pa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_0(exch, VFS_IN_UNLINK, NULL);
+	rc = async_data_write_start(exch, pa, pa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(pa);
 
@@ -640,5 +625,5 @@
 			return (int) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(pa);
 	async_wait_for(req, &rc);
@@ -673,11 +658,11 @@
 		return ENOMEM;
 	}
-
-	int vfs_phone = vfs_exchange_begin();
-	
-	req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
-	rc = async_data_write_start(vfs_phone, olda, olda_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	
+	async_exch_t *exch = vfs_exchange_begin();
+	
+	req = async_send_0(exch, VFS_IN_RENAME, NULL);
+	rc = async_data_write_start(exch, olda, olda_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(olda);
 		free(newa);
@@ -688,7 +673,7 @@
 			return (int) rc_orig;
 	}
-	rc = async_data_write_start(vfs_phone, newa, newa_size);
-	if (rc != EOK) {
-		vfs_exchange_end(vfs_phone);
+	rc = async_data_write_start(exch, newa, newa_size);
+	if (rc != EOK) {
+		vfs_exchange_end(exch);
 		free(olda);
 		free(newa);
@@ -699,5 +684,5 @@
 			return (int) rc_orig;
 	}
-	vfs_exchange_end(vfs_phone);
+	vfs_exchange_end(exch);
 	free(olda);
 	free(newa);
@@ -755,16 +740,19 @@
 }
 
-int fd_phone(int fildes)
+async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes)
 {
 	struct stat stat;
-	
 	int rc = fstat(fildes, &stat);
-	if (rc != 0)
-		return rc;
-	
-	if (!stat.device)
-		return -1;
-	
-	return devmap_device_connect(stat.device, 0);
+	if (rc != 0) {
+		errno = rc;
+		return NULL;
+	}
+	
+	if (!stat.device) {
+		errno = ENOENT;
+		return NULL;
+	}
+	
+	return devmap_device_connect(mgmt, stat.device, 0);
 }
 
@@ -772,7 +760,5 @@
 {
 	struct stat stat;
-	int rc;
-
-	rc = fstat(fildes, &stat);
+	int rc = fstat(fildes, &stat);
 	
 	if (rc == EOK) {
@@ -787,10 +773,10 @@
 int dup2(int oldfd, int newfd)
 {
-	int vfs_phone = vfs_exchange_begin();
+	async_exch_t *exch = vfs_exchange_begin();
 	
 	sysarg_t ret;
-	sysarg_t rc = async_req_2_1(vfs_phone, VFS_IN_DUP, oldfd, newfd, &ret);
-	
-	vfs_exchange_end(vfs_phone);
+	sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
+	
+	vfs_exchange_end(exch);
 	
 	if (rc == EOK)
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/async.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -41,6 +41,6 @@
 
 #include <ipc/common.h>
-#include <async_sess.h>
 #include <fibril.h>
+#include <fibril_synch.h>
 #include <sys/time.h>
 #include <atomic.h>
@@ -55,4 +55,76 @@
 typedef void (*async_client_conn_t)(ipc_callid_t, ipc_call_t *);
 
+/** Exchange management style
+ *
+ */
+typedef enum {
+	/** No explicit exchange management
+	 *
+	 * Suitable for protocols which use a single
+	 * IPC message per exchange only.
+	 *
+	 */
+	EXCHANGE_ATOMIC = 0,
+	
+	/** Exchange management via phone cloning
+	 *
+	 * Suitable for servers which support client
+	 * data tracking by task hashes and do not
+	 * mind cloned phones.
+	 *
+	 */
+	EXCHANGE_PARALLEL,
+	
+	/** Exchange management via mutual exclusion
+	 *
+	 * Suitable for any kind of client/server communication,
+	 * but can limit parallelism.
+	 *
+	 */
+	EXCHANGE_SERIALIZE
+} exch_mgmt_t;
+
+/** Session data */
+typedef struct {
+	/** List of inactive exchanges */
+	link_t exch_list;
+	
+	/** Exchange management style */
+	exch_mgmt_t mgmt;
+	
+	/** Session identification */
+	int phone;
+	
+	/** First clone connection argument */
+	sysarg_t arg1;
+	
+	/** Second clone connection argument */
+	sysarg_t arg2;
+	
+	/** Third clone connection argument */
+	sysarg_t arg3;
+	
+	/** Exchange mutex */
+	fibril_mutex_t mutex;
+	
+	/** Number of opened exchanges */
+	atomic_t refcnt;
+} async_sess_t;
+
+/** Exchange data */
+typedef struct {
+	/** Link into list of inactive exchanges */
+	link_t sess_link;
+	
+	/** Link into global list of inactive exchanges */
+	link_t global_link;
+	
+	/** Session pointer */
+	async_sess_t *sess;
+	
+	/** Exchange identification */
+	int phone;
+} async_exch_t;
+
 extern atomic_t threads_in_ipc_wait;
 
@@ -68,32 +140,32 @@
  * User-friendly wrappers for async_send_fast() and async_send_slow(). The
  * macros are in the form async_send_m(), where m denotes the number of payload
- * arguments.  Each macros chooses between the fast and the slow version based
+ * arguments. Each macros chooses between the fast and the slow version based
  * on m.
  */
 
-#define async_send_0(phoneid, method, dataptr) \
-	async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
-#define async_send_1(phoneid, method, arg1, dataptr) \
-	async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
-#define async_send_2(phoneid, method, arg1, arg2, dataptr) \
-	async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
-#define async_send_3(phoneid, method, arg1, arg2, arg3, dataptr) \
-	async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
-#define async_send_4(phoneid, method, arg1, arg2, arg3, arg4, dataptr) \
-	async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (dataptr))
-#define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
-	async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (dataptr))
-
-extern aid_t async_send_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, ipc_call_t *);
-extern aid_t async_send_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+#define async_send_0(exch, method, dataptr) \
+	async_send_fast(exch, method, 0, 0, 0, 0, dataptr)
+#define async_send_1(exch, method, arg1, dataptr) \
+	async_send_fast(exch, method, arg1, 0, 0, 0, dataptr)
+#define async_send_2(exch, method, arg1, arg2, dataptr) \
+	async_send_fast(exch, method, arg1, arg2, 0, 0, dataptr)
+#define async_send_3(exch, method, arg1, arg2, arg3, dataptr) \
+	async_send_fast(exch, method, arg1, arg2, arg3, 0, dataptr)
+#define async_send_4(exch, method, arg1, arg2, arg3, arg4, dataptr) \
+	async_send_fast(exch, method, arg1, arg2, arg3, arg4, dataptr)
+#define async_send_5(exch, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
+	async_send_slow(exch, method, arg1, arg2, arg3, arg4, arg5, dataptr)
+
+extern aid_t async_send_fast(async_exch_t *, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, ipc_call_t *);
+extern aid_t async_send_slow(async_exch_t *, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, ipc_call_t *);
+
 extern void async_wait_for(aid_t, sysarg_t *);
 extern int async_wait_timeout(aid_t, sysarg_t *, suseconds_t);
 
 extern fid_t async_new_connection(sysarg_t, sysarg_t, ipc_callid_t,
-    ipc_call_t *, void (*)(ipc_callid_t, ipc_call_t *));
+    ipc_call_t *, async_client_conn_t);
+
 extern void async_usleep(suseconds_t);
 extern void async_create_manager(void);
@@ -102,6 +174,5 @@
 extern void async_set_client_data_constructor(async_client_data_ctor_t);
 extern void async_set_client_data_destructor(async_client_data_dtor_t);
-
-extern void *async_client_data_get(void);
+extern void *async_get_client_data(void);
 
 extern void async_set_client_connection(async_client_conn_t);
@@ -112,11 +183,12 @@
  */
 
-extern void async_msg_0(int, sysarg_t);
-extern void async_msg_1(int, sysarg_t, sysarg_t);
-extern void async_msg_2(int, sysarg_t, sysarg_t, sysarg_t);
-extern void async_msg_3(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
-extern void async_msg_4(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
-extern void async_msg_5(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+extern void async_msg_0(async_exch_t *, sysarg_t);
+extern void async_msg_1(async_exch_t *, sysarg_t, sysarg_t);
+extern void async_msg_2(async_exch_t *, sysarg_t, sysarg_t, sysarg_t);
+extern void async_msg_3(async_exch_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern void async_msg_4(async_exch_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t);
+extern void async_msg_5(async_exch_t *, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t);
 
 /*
@@ -138,8 +210,8 @@
  */
 
-extern int async_forward_fast(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
-    unsigned int);
-extern int async_forward_slow(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, sysarg_t, unsigned int);
+extern int async_forward_fast(ipc_callid_t, async_exch_t *, sysarg_t, sysarg_t,
+    sysarg_t, unsigned int);
+extern int async_forward_slow(ipc_callid_t, async_exch_t *, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t, unsigned int);
 
 /*
@@ -150,161 +222,160 @@
  */
 
-#define async_req_0_0(phoneid, method) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
-	    NULL)
-#define async_req_0_1(phoneid, method, r1) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
-	    NULL)
-#define async_req_0_2(phoneid, method, r1, r2) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
-	    NULL)
-#define async_req_0_3(phoneid, method, r1, r2, r3) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
-	    NULL)
-#define async_req_0_4(phoneid, method, r1, r2, r3, r4) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
-	    NULL)
-#define async_req_0_5(phoneid, method, r1, r2, r3, r4, r5) \
-	async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
-	    (r5))
-#define async_req_1_0(phoneid, method, arg1) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
-	    NULL, NULL)
-#define async_req_1_1(phoneid, method, arg1, rc1) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
-	    NULL, NULL)
-#define async_req_1_2(phoneid, method, arg1, rc1, rc2) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
-	    NULL, NULL)
-#define async_req_1_3(phoneid, method, arg1, rc1, rc2, rc3) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
-	    NULL, NULL)
-#define async_req_1_4(phoneid, method, arg1, rc1, rc2, rc3, rc4) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
-	    (rc4), NULL)
-#define async_req_1_5(phoneid, method, arg1, rc1, rc2, rc3, rc4, rc5) \
-	async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
-	    (rc4), (rc5))
-#define async_req_2_0(phoneid, method, arg1, arg2) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
+#define async_req_0_0(exch, method) \
+	async_req_fast(exch, method, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)
+#define async_req_0_1(exch, method, r1) \
+	async_req_fast(exch, method, 0, 0, 0, 0, r1, NULL, NULL, NULL, NULL)
+#define async_req_0_2(exch, method, r1, r2) \
+	async_req_fast(exch, method, 0, 0, 0, 0, r1, r2, NULL, NULL, NULL)
+#define async_req_0_3(exch, method, r1, r2, r3) \
+	async_req_fast(exch, method, 0, 0, 0, 0, r1, r2, r3, NULL, NULL)
+#define async_req_0_4(exch, method, r1, r2, r3, r4) \
+	async_req_fast(exch, method, 0, 0, 0, 0, r1, r2, r3, r4, NULL)
+#define async_req_0_5(exch, method, r1, r2, r3, r4, r5) \
+	async_req_fast(exch, method, 0, 0, 0, 0, r1, r2, r3, r4, r5)
+
+#define async_req_1_0(exch, method, arg1) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, NULL, NULL, NULL, NULL, \
+	    NULL)
+#define async_req_1_1(exch, method, arg1, rc1) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, rc1, NULL, NULL, NULL, \
+	    NULL)
+#define async_req_1_2(exch, method, arg1, rc1, rc2) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, rc1, rc2, NULL, NULL, \
+	    NULL)
+#define async_req_1_3(exch, method, arg1, rc1, rc2, rc3) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, rc1, rc2, rc3, NULL, \
+	    NULL)
+#define async_req_1_4(exch, method, arg1, rc1, rc2, rc3, rc4) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, rc1, rc2, rc3, rc4, \
+	    NULL)
+#define async_req_1_5(exch, method, arg1, rc1, rc2, rc3, rc4, rc5) \
+	async_req_fast(exch, method, arg1, 0, 0, 0, rc1, rc2, rc3, rc4, \
+	    rc5)
+
+#define async_req_2_0(exch, method, arg1, arg2) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, NULL, NULL, NULL, \
+	    NULL, NULL)
+#define async_req_2_1(exch, method, arg1, arg2, rc1) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, rc1, NULL, NULL, \
+	    NULL, NULL)
+#define async_req_2_2(exch, method, arg1, arg2, rc1, rc2) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, rc1, rc2, NULL, NULL, \
+	    NULL)
+#define async_req_2_3(exch, method, arg1, arg2, rc1, rc2, rc3) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, rc1, rc2, rc3, NULL, \
+	    NULL)
+#define async_req_2_4(exch, method, arg1, arg2, rc1, rc2, rc3, rc4) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, rc1, rc2, rc3, rc4, \
+	    NULL)
+#define async_req_2_5(exch, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
+	async_req_fast(exch, method, arg1, arg2, 0, 0, rc1, rc2, rc3, rc4, \
+	    rc5)
+
+#define async_req_3_0(exch, method, arg1, arg2, arg3) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, NULL, NULL, NULL, \
+	    NULL, NULL)
+#define async_req_3_1(exch, method, arg1, arg2, arg3, rc1) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, rc1, NULL, NULL, \
+	    NULL, NULL)
+#define async_req_3_2(exch, method, arg1, arg2, arg3, rc1, rc2) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, rc1, rc2, NULL, \
+	    NULL, NULL)
+#define async_req_3_3(exch, method, arg1, arg2, arg3, rc1, rc2, rc3) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, rc1, rc2, rc3, \
+	    NULL, NULL)
+#define async_req_3_4(exch, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, rc1, rc2, rc3, \
+	    rc4, NULL)
+#define async_req_3_5(exch, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
+    rc5) \
+	async_req_fast(exch, method, arg1, arg2, arg3, 0, rc1, rc2, rc3, \
+	    rc4, rc5)
+
+#define async_req_4_0(exch, method, arg1, arg2, arg3, arg4) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, NULL, NULL, \
 	    NULL, NULL, NULL)
-#define async_req_2_1(phoneid, method, arg1, arg2, rc1) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
+#define async_req_4_1(exch, method, arg1, arg2, arg3, arg4, rc1) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, rc1, NULL, \
 	    NULL, NULL, NULL)
-#define async_req_2_2(phoneid, method, arg1, arg2, rc1, rc2) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
+#define async_req_4_2(exch, method, arg1, arg2, arg3, arg4, rc1, rc2) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, NULL, \
+	    NULL, NULL)
+#define async_req_4_3(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+	    NULL, NULL)
+#define async_req_4_4(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+    rc4) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+	    rc4, NULL)
+#define async_req_4_5(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+    rc4, rc5) \
+	async_req_fast(exch, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+	    rc4, rc5)
+
+#define async_req_5_0(exch, method, arg1, arg2, arg3, arg4, arg5) \
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, NULL, \
+	    NULL, NULL, NULL, NULL)
+#define async_req_5_1(exch, method, arg1, arg2, arg3, arg4, arg5, rc1) \
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, \
+	    NULL, NULL, NULL, NULL)
+#define async_req_5_2(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
 	    NULL, NULL, NULL)
-#define async_req_2_3(phoneid, method, arg1, arg2, rc1, rc2, rc3) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
-	    (rc3), NULL, NULL)
-#define async_req_2_4(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
-	    (rc3), (rc4), NULL)
-#define async_req_2_5(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
-	    (rc3), (rc4), (rc5))
-#define async_req_3_0(phoneid, method, arg1, arg2, arg3) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
-	    NULL, NULL, NULL)
-#define async_req_3_1(phoneid, method, arg1, arg2, arg3, rc1) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
-	    NULL, NULL, NULL, NULL)
-#define async_req_3_2(phoneid, method, arg1, arg2, arg3, rc1, rc2) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
-	    (rc2), NULL, NULL, NULL)
-#define async_req_3_3(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
-	    (rc2), (rc3), NULL, NULL)
-#define async_req_3_4(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
-	    (rc2), (rc3), (rc4), NULL)
-#define async_req_3_5(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
-    rc5) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
-	    (rc2), (rc3), (rc4), (rc5))
-#define async_req_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
-	    NULL, NULL, NULL, NULL)
-#define async_req_4_1(phoneid, method, arg1, arg2, arg3, arg4, rc1) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
-	    NULL, NULL, NULL, NULL)
-#define async_req_4_2(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
-	    (rc2), NULL, NULL, NULL)
-#define async_req_4_3(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
-	    (rc2), (rc3), NULL, NULL)
-#define async_req_4_4(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
-    rc4) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (rc1), (rc2), (rc3), (rc4), NULL)
-#define async_req_4_5(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
-    rc4, rc5) \
-	async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (rc1), (rc2), (rc3), (rc4), (rc5))
-#define async_req_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), NULL, NULL, NULL, NULL, NULL)
-#define async_req_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (rc1), NULL, NULL, NULL, NULL)
-#define async_req_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (rc1), (rc2), NULL, NULL, NULL)
-#define async_req_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+#define async_req_5_3(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
     rc3) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (rc1), (rc2), (rc3), NULL, NULL)
-#define async_req_5_4(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+	    rc3, NULL, NULL)
+#define async_req_5_4(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
     rc3, rc4) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (rc1), (rc2), (rc3), (rc4), NULL)
-#define async_req_5_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+	    rc3, rc4, NULL)
+#define async_req_5_5(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
     rc3, rc4, rc5) \
-	async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
-	    (arg5), (rc1), (rc2), (rc3), (rc4), (rc5))
-
-extern sysarg_t async_req_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *);
-extern sysarg_t async_req_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+	async_req_slow(exch, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+	    rc3, rc4, rc5)
+
+extern sysarg_t async_req_fast(async_exch_t *, sysarg_t, sysarg_t, sysarg_t,
     sysarg_t, sysarg_t, sysarg_t *, sysarg_t *, sysarg_t *, sysarg_t *,
     sysarg_t *);
-
-static inline void async_serialize_start(void)
-{
-	fibril_inc_sercount();
-}
-
-static inline void async_serialize_end(void)
-{
-	fibril_dec_sercount();
-}
-
-extern int async_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t,
+extern sysarg_t async_req_slow(async_exch_t *, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, sysarg_t *, sysarg_t *, sysarg_t *,
+    sysarg_t *, sysarg_t *);
+
+extern async_sess_t *async_connect_me(exch_mgmt_t, async_exch_t *);
+extern async_sess_t *async_connect_me_to(exch_mgmt_t, async_exch_t *, sysarg_t,
+    sysarg_t, sysarg_t);
+extern async_sess_t *async_connect_me_to_blocking(exch_mgmt_t, async_exch_t *,
+    sysarg_t, sysarg_t, sysarg_t);
+extern async_sess_t *async_connect_kbox(task_id_t);
+
+extern int async_connect_to_me(async_exch_t *, sysarg_t, sysarg_t, sysarg_t,
     async_client_conn_t);
-extern int async_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t);
-extern int async_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t);
-extern int async_connect_kbox(task_id_t);
-extern int async_hangup(int);
+
+extern int async_hangup(async_sess_t *);
 extern void async_poke(void);
 
+extern async_exch_t *async_exchange_begin(async_sess_t *);
+extern void async_exchange_end(async_exch_t *);
+
 /*
  * User-friendly wrappers for async_share_in_start().
  */
 
-#define async_share_in_start_0_0(phoneid, dst, size) \
-	async_share_in_start((phoneid), (dst), (size), 0, NULL)
-#define async_share_in_start_0_1(phoneid, dst, size, flags) \
-	async_share_in_start((phoneid), (dst), (size), 0, (flags))
-#define async_share_in_start_1_0(phoneid, dst, size, arg) \
-	async_share_in_start((phoneid), (dst), (size), (arg), NULL)
-#define async_share_in_start_1_1(phoneid, dst, size, arg, flags) \
-	async_share_in_start((phoneid), (dst), (size), (arg), (flags))
-
-extern int async_share_in_start(int, void *, size_t, sysarg_t, unsigned int *);
+#define async_share_in_start_0_0(exch, dst, size) \
+	async_share_in_start(exch, dst, size, 0, NULL)
+#define async_share_in_start_0_1(exch, dst, size, flags) \
+	async_share_in_start(exch, dst, size, 0, flags)
+#define async_share_in_start_1_0(exch, dst, size, arg) \
+	async_share_in_start(exch, dst, size, arg, NULL)
+#define async_share_in_start_1_1(exch, dst, size, arg, flags) \
+	async_share_in_start(exch, dst, size, arg, flags)
+
+extern int async_share_in_start(async_exch_t *, void *, size_t, sysarg_t,
+    unsigned int *);
 extern bool async_share_in_receive(ipc_callid_t *, size_t *);
 extern int async_share_in_finalize(ipc_callid_t, void *, unsigned int);
 
-extern int async_share_out_start(int, void *, unsigned int);
+extern int async_share_out_start(async_exch_t *, void *, unsigned int);
 extern bool async_share_out_receive(ipc_callid_t *, size_t *, unsigned int *);
 extern int async_share_out_finalize(ipc_callid_t, void *);
@@ -314,40 +385,37 @@
  */
 
-#define async_data_read_forward_0_0(phoneid, method, answer) \
-	async_data_read_forward_fast((phoneid), (method), 0, 0, 0, 0, NULL)
-#define async_data_read_forward_0_1(phoneid, method, answer) \
-	async_data_read_forward_fast((phoneid), (method), 0, 0, 0, 0, (answer))
-#define async_data_read_forward_1_0(phoneid, method, arg1, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), 0, 0, 0, NULL)
-#define async_data_read_forward_1_1(phoneid, method, arg1, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), 0, 0, 0, (answer))
-#define async_data_read_forward_2_0(phoneid, method, arg1, arg2, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL)
-#define async_data_read_forward_2_1(phoneid, method, arg1, arg2, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
-	    (answer))
-#define async_data_read_forward_3_0(phoneid, method, arg1, arg2, arg3, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, \
-	    NULL)
-#define async_data_read_forward_3_1(phoneid, method, arg1, arg2, arg3, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, \
-	    (answer))
-#define async_data_read_forward_4_0(phoneid, method, arg1, arg2, arg3, arg4, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), NULL)
-#define async_data_read_forward_4_1(phoneid, method, arg1, arg2, arg3, arg4, answer) \
-	async_data_read_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), (answer))
-
-extern aid_t async_data_read(int, void *, size_t, ipc_call_t *);
-#define async_data_read_start(p, buf, len) \
-	async_data_read_start_generic((p), (buf), (len), IPC_XF_NONE)
-
-extern int async_data_read_start_generic(int, void *, size_t, int);
+#define async_data_read_forward_0_0(exch, method, answer) \
+	async_data_read_forward_fast(exch, method, 0, 0, 0, 0, NULL)
+#define async_data_read_forward_0_1(exch, method, answer) \
+	async_data_read_forward_fast(exch, method, 0, 0, 0, 0, answer)
+#define async_data_read_forward_1_0(exch, method, arg1, answer) \
+	async_data_read_forward_fast(exch, method, arg1, 0, 0, 0, NULL)
+#define async_data_read_forward_1_1(exch, method, arg1, answer) \
+	async_data_read_forward_fast(exch, method, arg1, 0, 0, 0, answer)
+#define async_data_read_forward_2_0(exch, method, arg1, arg2, answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, 0, 0, NULL)
+#define async_data_read_forward_2_1(exch, method, arg1, arg2, answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, 0, 0, answer)
+#define async_data_read_forward_3_0(exch, method, arg1, arg2, arg3, answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, arg3, 0, NULL)
+#define async_data_read_forward_3_1(exch, method, arg1, arg2, arg3, answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, arg3, 0, \
+	    answer)
+#define async_data_read_forward_4_0(exch, method, arg1, arg2, arg3, arg4, \
+    answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, arg3, arg4, \
+	    NULL)
+#define async_data_read_forward_4_1(exch, method, arg1, arg2, arg3, arg4, \
+    answer) \
+	async_data_read_forward_fast(exch, method, arg1, arg2, arg3, arg4, \
+	    answer)
+
+extern aid_t async_data_read(async_exch_t *, void *, size_t, ipc_call_t *);
+extern int async_data_read_start(async_exch_t *, void *, size_t);
 extern bool async_data_read_receive(ipc_callid_t *, size_t *);
 extern int async_data_read_finalize(ipc_callid_t, const void *, size_t);
 
-extern int async_data_read_forward_fast(int, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, ipc_call_t *);
+extern int async_data_read_forward_fast(async_exch_t *, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, ipc_call_t *);
 
 /*
@@ -355,36 +423,32 @@
  */
 
-#define async_data_write_forward_0_0(phoneid, method, answer) \
-	async_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, NULL)
-#define async_data_write_forward_0_1(phoneid, method, answer) \
-	async_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, (answer))
-#define async_data_write_forward_1_0(phoneid, method, arg1, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), 0, 0, 0, NULL)
-#define async_data_write_forward_1_1(phoneid, method, arg1, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), 0, 0, 0, \
-	    (answer))
-#define async_data_write_forward_2_0(phoneid, method, arg1, arg2, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
-	    NULL)
-#define async_data_write_forward_2_1(phoneid, method, arg1, arg2, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
-	    (answer))
-#define async_data_write_forward_3_0(phoneid, method, arg1, arg2, arg3, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    0, NULL)
-#define async_data_write_forward_3_1(phoneid, method, arg1, arg2, arg3, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    0, (answer))
-#define async_data_write_forward_4_0(phoneid, method, arg1, arg2, arg3, arg4, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), NULL)
-#define async_data_write_forward_4_1(phoneid, method, arg1, arg2, arg3, arg4, answer) \
-	async_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
-	    (arg4), (answer))
-
-#define async_data_write_start(p, buf, len) \
-	async_data_write_start_generic((p), (buf), (len), IPC_XF_NONE)
-
-extern int async_data_write_start_generic(int, const void *, size_t, int);
+#define async_data_write_forward_0_0(exch, method, answer) \
+	async_data_write_forward_fast(exch, method, 0, 0, 0, 0, NULL)
+#define async_data_write_forward_0_1(exch, method, answer) \
+	async_data_write_forward_fast(exch, method, 0, 0, 0, 0, answer)
+#define async_data_write_forward_1_0(exch, method, arg1, answer) \
+	async_data_write_forward_fast(exch, method, arg1, 0, 0, 0, NULL)
+#define async_data_write_forward_1_1(exch, method, arg1, answer) \
+	async_data_write_forward_fast(exch, method, arg1, 0, 0, 0, answer)
+#define async_data_write_forward_2_0(exch, method, arg1, arg2, answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, 0, 0, NULL)
+#define async_data_write_forward_2_1(exch, method, arg1, arg2, answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, 0, 0, answer)
+#define async_data_write_forward_3_0(exch, method, arg1, arg2, arg3, answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, arg3, 0, \
+	    NULL)
+#define async_data_write_forward_3_1(exch, method, arg1, arg2, arg3, answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, arg3, 0, \
+	    answer)
+#define async_data_write_forward_4_0(exch, method, arg1, arg2, arg3, arg4, \
+    answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, arg3, arg4, \
+	    NULL)
+#define async_data_write_forward_4_1(exch, method, arg1, arg2, arg3, arg4, \
+    answer) \
+	async_data_write_forward_fast(exch, method, arg1, arg2, arg3, arg4, \
+	    answer)
+
+extern int async_data_write_start(async_exch_t *, const void *, size_t);
 extern bool async_data_write_receive(ipc_callid_t *, size_t *);
 extern int async_data_write_finalize(ipc_callid_t, void *, size_t);
@@ -394,6 +458,10 @@
 extern void async_data_write_void(sysarg_t);
 
-extern int async_data_write_forward_fast(int, sysarg_t, sysarg_t, sysarg_t,
-    sysarg_t, sysarg_t, ipc_call_t *);
+extern int async_data_write_forward_fast(async_exch_t *, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, ipc_call_t *);
+
+extern int async_exchange_clone(async_exch_t *, async_exch_t *);
+extern async_sess_t *async_clone_receive(exch_mgmt_t);
+extern async_sess_t *async_callback_receive(exch_mgmt_t);
 
 #endif
Index: uspace/lib/c/include/async_obsolete.h
===================================================================
--- uspace/lib/c/include/async_obsolete.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/include/async_obsolete.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#if ((defined(LIBC_IPC_H_)) && (!defined(LIBC_ASYNC_OBSOLETE_C_)))
+	#error Do not intermix low-level IPC interface and async framework
+#endif
+
+#ifndef LIBC_ASYNC_OBSOLETE_H_
+#define LIBC_ASYNC_OBSOLETE_H_
+
+extern void async_obsolete_serialize_start(void);
+extern void async_obsolete_serialize_end(void);
+
+#define async_obsolete_send_0(phoneid, method, dataptr) \
+	async_obsolete_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
+#define async_obsolete_send_1(phoneid, method, arg1, dataptr) \
+	async_obsolete_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
+#define async_obsolete_send_2(phoneid, method, arg1, arg2, dataptr) \
+	async_obsolete_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
+#define async_obsolete_send_3(phoneid, method, arg1, arg2, arg3, dataptr) \
+	async_obsolete_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
+#define async_obsolete_send_4(phoneid, method, arg1, arg2, arg3, arg4, dataptr) \
+	async_obsolete_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (dataptr))
+#define async_obsolete_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
+	async_obsolete_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (dataptr))
+
+extern aid_t async_obsolete_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr);
+extern aid_t async_obsolete_send_slow(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
+    ipc_call_t *dataptr);
+
+#define async_obsolete_req_0_0(phoneid, method) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
+	    NULL)
+#define async_obsolete_req_0_1(phoneid, method, r1) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
+	    NULL)
+#define async_obsolete_req_0_2(phoneid, method, r1, r2) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
+	    NULL)
+#define async_obsolete_req_0_3(phoneid, method, r1, r2, r3) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
+	    NULL)
+#define async_obsolete_req_0_4(phoneid, method, r1, r2, r3, r4) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
+	    NULL)
+#define async_obsolete_req_0_5(phoneid, method, r1, r2, r3, r4, r5) \
+	async_obsolete_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
+	    (r5))
+#define async_obsolete_req_1_0(phoneid, method, arg1) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
+	    NULL, NULL)
+#define async_obsolete_req_1_1(phoneid, method, arg1, rc1) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
+	    NULL, NULL)
+#define async_obsolete_req_1_2(phoneid, method, arg1, rc1, rc2) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
+	    NULL, NULL)
+#define async_obsolete_req_1_3(phoneid, method, arg1, rc1, rc2, rc3) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
+	    NULL, NULL)
+#define async_obsolete_req_1_4(phoneid, method, arg1, rc1, rc2, rc3, rc4) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
+	    (rc4), NULL)
+#define async_obsolete_req_1_5(phoneid, method, arg1, rc1, rc2, rc3, rc4, rc5) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
+	    (rc4), (rc5))
+#define async_obsolete_req_2_0(phoneid, method, arg1, arg2) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
+	    NULL, NULL, NULL)
+#define async_obsolete_req_2_1(phoneid, method, arg1, arg2, rc1) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
+	    NULL, NULL, NULL)
+#define async_obsolete_req_2_2(phoneid, method, arg1, arg2, rc1, rc2) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
+	    NULL, NULL, NULL)
+#define async_obsolete_req_2_3(phoneid, method, arg1, arg2, rc1, rc2, rc3) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
+	    (rc3), NULL, NULL)
+#define async_obsolete_req_2_4(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
+	    (rc3), (rc4), NULL)
+#define async_obsolete_req_2_5(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
+	    (rc3), (rc4), (rc5))
+#define async_obsolete_req_3_0(phoneid, method, arg1, arg2, arg3) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
+	    NULL, NULL, NULL)
+#define async_obsolete_req_3_1(phoneid, method, arg1, arg2, arg3, rc1) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
+	    NULL, NULL, NULL, NULL)
+#define async_obsolete_req_3_2(phoneid, method, arg1, arg2, arg3, rc1, rc2) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
+	    (rc2), NULL, NULL, NULL)
+#define async_obsolete_req_3_3(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
+	    (rc2), (rc3), NULL, NULL)
+#define async_obsolete_req_3_4(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
+	    (rc2), (rc3), (rc4), NULL)
+#define async_obsolete_req_3_5(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
+    rc5) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
+	    (rc2), (rc3), (rc4), (rc5))
+#define async_obsolete_req_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
+	    NULL, NULL, NULL, NULL)
+#define async_obsolete_req_4_1(phoneid, method, arg1, arg2, arg3, arg4, rc1) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
+	    NULL, NULL, NULL, NULL)
+#define async_obsolete_req_4_2(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
+	    (rc2), NULL, NULL, NULL)
+#define async_obsolete_req_4_3(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
+	    (rc2), (rc3), NULL, NULL)
+#define async_obsolete_req_4_4(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+    rc4) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (rc1), (rc2), (rc3), (rc4), NULL)
+#define async_obsolete_req_4_5(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
+    rc4, rc5) \
+	async_obsolete_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (rc1), (rc2), (rc3), (rc4), (rc5))
+#define async_obsolete_req_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), NULL, NULL, NULL, NULL, NULL)
+#define async_obsolete_req_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (rc1), NULL, NULL, NULL, NULL)
+#define async_obsolete_req_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (rc1), (rc2), NULL, NULL, NULL)
+#define async_obsolete_req_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+    rc3) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (rc1), (rc2), (rc3), NULL, NULL)
+#define async_obsolete_req_5_4(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+    rc3, rc4) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (rc1), (rc2), (rc3), (rc4), NULL)
+#define async_obsolete_req_5_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
+    rc3, rc4, rc5) \
+	async_obsolete_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
+	    (arg5), (rc1), (rc2), (rc3), (rc4), (rc5))
+
+extern sysarg_t async_obsolete_req_fast(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,
+    sysarg_t *r3, sysarg_t *r4, sysarg_t *r5);
+extern sysarg_t async_obsolete_req_slow(int phoneid, sysarg_t method, sysarg_t arg1,
+    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,
+    sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5);
+
+extern void async_obsolete_msg_0(int, sysarg_t);
+extern void async_obsolete_msg_1(int, sysarg_t, sysarg_t);
+extern void async_obsolete_msg_2(int, sysarg_t, sysarg_t, sysarg_t);
+extern void async_obsolete_msg_3(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern void async_obsolete_msg_4(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t);
+extern void async_obsolete_msg_5(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t);
+
+extern int async_obsolete_forward_slow(ipc_callid_t, int, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, sysarg_t, unsigned int);
+
+extern int async_obsolete_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t,
+    async_client_conn_t);
+extern int async_obsolete_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t);
+extern int async_obsolete_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t);
+extern int async_obsolete_hangup(int);
+
+#define async_obsolete_share_in_start_0_0(phoneid, dst, size) \
+	async_obsolete_share_in_start((phoneid), (dst), (size), 0, NULL)
+#define async_obsolete_share_in_start_0_1(phoneid, dst, size, flags) \
+	async_obsolete_share_in_start((phoneid), (dst), (size), 0, (flags))
+#define async_obsolete_share_in_start_1_0(phoneid, dst, size, arg) \
+	async_obsolete_share_in_start((phoneid), (dst), (size), (arg), NULL)
+#define async_obsolete_share_in_start_1_1(phoneid, dst, size, arg, flags) \
+	async_obsolete_share_in_start((phoneid), (dst), (size), (arg), (flags))
+
+extern int async_obsolete_share_in_start(int, void *, size_t, sysarg_t,
+    unsigned int *);
+extern int async_obsolete_share_out_start(int, void *, unsigned int);
+
+#define async_obsolete_data_write_start(p, buf, len) \
+	async_obsolete_data_write_start_generic((p), (buf), (len), IPC_XF_NONE)
+
+#define async_obsolete_data_read_start(p, buf, len) \
+	async_obsolete_data_read_start_generic((p), (buf), (len), IPC_XF_NONE)
+
+#define async_obsolete_data_write_forward_0_0(phoneid, method, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, NULL)
+#define async_obsolete_data_write_forward_0_1(phoneid, method, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), 0, 0, 0, 0, (answer))
+#define async_obsolete_data_write_forward_1_0(phoneid, method, arg1, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), 0, 0, 0, NULL)
+#define async_obsolete_data_write_forward_1_1(phoneid, method, arg1, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), 0, 0, 0, \
+	    (answer))
+#define async_obsolete_data_write_forward_2_0(phoneid, method, arg1, arg2, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
+	    NULL)
+#define async_obsolete_data_write_forward_2_1(phoneid, method, arg1, arg2, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
+	    (answer))
+#define async_obsolete_data_write_forward_3_0(phoneid, method, arg1, arg2, arg3, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    0, NULL)
+#define async_obsolete_data_write_forward_3_1(phoneid, method, arg1, arg2, arg3, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    0, (answer))
+#define async_obsolete_data_write_forward_4_0(phoneid, method, arg1, arg2, arg3, arg4, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    (arg4), NULL)
+#define async_obsolete_data_write_forward_4_1(phoneid, method, arg1, arg2, arg3, arg4, answer) \
+	async_obsolete_data_write_forward_fast((phoneid), (method), (arg1), (arg2), (arg3), \
+	    (arg4), (answer))
+
+extern aid_t async_obsolete_data_read(int, void *, size_t, ipc_call_t *);
+extern int async_obsolete_data_read_start_generic(int, void *, size_t, int);
+
+extern int async_obsolete_data_write_start_generic(int, const void *, size_t, int);
+extern void async_obsolete_data_write_void(const int);
+
+extern int async_obsolete_forward_fast(ipc_callid_t, int, sysarg_t, sysarg_t,
+    sysarg_t, unsigned int);
+
+extern int async_obsolete_data_write_forward_fast(int, sysarg_t, sysarg_t, sysarg_t,
+    sysarg_t, sysarg_t, ipc_call_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/async_sess.h
===================================================================
--- uspace/lib/c/include/async_sess.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ 	(revision )
@@ -1,55 +1,0 @@
-/*
- * Copyright (c) 2010 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ASYNC_SESS_H_
-#define LIBC_ASYNC_SESS_H_
-
-#include <adt/list.h>
-
-typedef struct {
-	int sess_phone;		/**< Phone for cloning off the connections. */
-	sysarg_t connect_arg1;  /**< Argument for CONNECT_ME_TO. */
-	link_t conn_head;	/**< List of open data connections. */
-	link_t sess_link;	/**< Link in global list of open sessions. */
-} async_sess_t;
-
-extern void async_session_create(async_sess_t *, int, sysarg_t);
-extern void async_session_destroy(async_sess_t *);
-extern int async_exchange_begin(async_sess_t *);
-extern void async_exchange_end(async_sess_t *, int);
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/device/char_dev.h
===================================================================
--- uspace/lib/c/include/device/char_dev.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/device/char_dev.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -36,4 +36,6 @@
 #define LIBC_DEVICE_CHAR_DEV_H_
 
+#include <async.h>
+
 typedef enum {
 	CHAR_DEV_READ = 0,
@@ -41,6 +43,6 @@
 } char_dev_method_t;
 
-ssize_t char_dev_read(int dev_phone, void *buf, size_t len);
-ssize_t char_dev_write(int dev_phone, void *buf, size_t len);
+extern ssize_t char_dev_read(async_sess_t *, void *, size_t);
+extern ssize_t char_dev_write(async_sess_t *, void *, size_t);
 
 #endif
Index: uspace/lib/c/include/device/hw_res.h
===================================================================
--- uspace/lib/c/include/device/hw_res.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/device/hw_res.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -26,5 +26,5 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
- 
+
 /** @addtogroup libc
  * @{
@@ -32,9 +32,10 @@
 /** @file
  */
- 
+
 #ifndef LIBC_DEVICE_HW_RES_H_
 #define LIBC_DEVICE_HW_RES_H_
 
 #include <ipc/dev_iface.h>
+#include <async.h>
 #include <bool.h>
 
@@ -48,5 +49,5 @@
 typedef enum {
 	INTERRUPT,
-	IO_RANGE, 
+	IO_RANGE,
 	MEM_RANGE
 } hw_res_type_t;
@@ -66,5 +67,5 @@
 			size_t size;
 		} mem_range;
-
+		
 		struct {
 			uint64_t address;
@@ -72,5 +73,5 @@
 			size_t size;
 		} io_range;
-
+		
 		struct {
 			int irq;
@@ -88,13 +89,12 @@
 	if (hw_res->resources != NULL) {
 		free(hw_res->resources);
-
 		hw_res->resources = NULL;
 	}
-
+	
 	hw_res->count = 0;
 }
 
-extern int hw_res_get_resource_list(int, hw_resource_list_t *);
-extern bool hw_res_enable_interrupt(int);
+extern int hw_res_get_resource_list(async_sess_t *, hw_resource_list_t *);
+extern bool hw_res_enable_interrupt(async_sess_t *);
 
 #endif
Index: uspace/lib/c/include/devman.h
===================================================================
--- uspace/lib/c/include/devman.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/devman.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -41,6 +41,7 @@
 #include <bool.h>
 
-extern int devman_get_phone(devman_interface_t, unsigned int);
-extern void devman_hangup_phone(devman_interface_t);
+extern async_exch_t *devman_exchange_begin_blocking(devman_interface_t);
+extern async_exch_t *devman_exchange_begin(devman_interface_t);
+extern void devman_exchange_end(async_exch_t *);
 
 extern int devman_driver_register(const char *, async_client_conn_t);
@@ -48,6 +49,8 @@
     devman_handle_t, devman_handle_t *);
 
-extern int devman_device_connect(devman_handle_t, unsigned int);
-extern int devman_parent_device_connect(devman_handle_t, unsigned int);
+extern async_sess_t *devman_device_connect(exch_mgmt_t, devman_handle_t,
+    unsigned int);
+extern async_sess_t *devman_parent_device_connect(exch_mgmt_t, devman_handle_t,
+    unsigned int);
 
 extern int devman_device_get_handle(const char *, devman_handle_t *,
Index: uspace/lib/c/include/devman_obsolete.h
===================================================================
--- uspace/lib/c/include/devman_obsolete.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/include/devman_obsolete.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2010 Lenka Trochtova 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_DEVMAN_OBSOLETE_H_
+#define LIBC_DEVMAN_OBSOLETE_H_
+
+#include <ipc/devman.h>
+#include <async.h>
+#include <bool.h>
+
+extern int devman_obsolete_get_phone(devman_interface_t, unsigned int);
+extern void devman_obsolete_hangup_phone(devman_interface_t);
+
+extern int devman_obsolete_device_connect(devman_handle_t, unsigned int);
+extern int devman_obsolete_parent_device_connect(devman_handle_t, unsigned int);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/devmap.h
===================================================================
--- uspace/lib/c/include/devmap.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/devmap.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -40,16 +40,21 @@
 #include <bool.h>
 
-extern int devmap_get_phone(devmap_interface_t, unsigned int);
-extern void devmap_hangup_phone(devmap_interface_t iface);
+extern async_exch_t *devmap_exchange_begin_blocking(devmap_interface_t);
+extern async_exch_t *devmap_exchange_begin(devmap_interface_t);
+extern void devmap_exchange_end(async_exch_t *);
 
 extern int devmap_driver_register(const char *, async_client_conn_t);
 extern int devmap_device_register(const char *, devmap_handle_t *);
-extern int devmap_device_register_with_iface(const char *, devmap_handle_t *, sysarg_t);
+extern int devmap_device_register_with_iface(const char *, devmap_handle_t *,
+    sysarg_t);
 
-extern int devmap_device_get_handle(const char *, devmap_handle_t *, unsigned int);
-extern int devmap_namespace_get_handle(const char *, devmap_handle_t *, unsigned int);
+extern int devmap_device_get_handle(const char *, devmap_handle_t *,
+    unsigned int);
+extern int devmap_namespace_get_handle(const char *, devmap_handle_t *,
+    unsigned int);
 extern devmap_handle_type_t devmap_handle_probe(devmap_handle_t);
 
-extern int devmap_device_connect(devmap_handle_t, unsigned int);
+extern async_sess_t *devmap_device_connect(exch_mgmt_t, devmap_handle_t,
+    unsigned int);
 
 extern int devmap_null_create(void);
Index: uspace/lib/c/include/devmap_obsolete.h
===================================================================
--- uspace/lib/c/include/devmap_obsolete.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/include/devmap_obsolete.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2009 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_DEVMAP_OBSOLETE_H_
+#define LIBC_DEVMAP_OBSOLETE_H_
+
+#include <ipc/devmap.h>
+#include <async.h>
+#include <bool.h>
+
+extern int devmap_obsolete_get_phone(devmap_interface_t, unsigned int);
+extern void devmap_obsolete_hangup_phone(devmap_interface_t iface);
+
+extern int devmap_obsolete_device_connect(devmap_handle_t, unsigned int);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/io/console.h
===================================================================
--- uspace/lib/c/include/io/console.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/io/console.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -36,10 +36,8 @@
 #define LIBC_IO_CONSOLE_H_
 
+#include <sys/time.h>
+#include <async.h>
 #include <bool.h>
-
-typedef enum {
-	KEY_PRESS,
-	KEY_RELEASE
-} console_ev_type_t;
+#include <stdio.h>
 
 typedef enum {
@@ -50,8 +48,34 @@
 } console_caps_t;
 
+/** Console control structure. */
+typedef struct {
+	/** Console input file */
+	FILE *input;
+	
+	/** Console output file */
+	FILE *output;
+	
+	/** Console input session */
+	async_sess_t *input_sess;
+	
+	/** Console output session */
+	async_sess_t *output_sess;
+	
+	/** Input request call with timeout */
+	ipc_call_t input_call;
+	
+	/** Input response with timeout */
+	aid_t input_aid;
+} console_ctrl_t;
+
+typedef enum {
+	KEY_PRESS,
+	KEY_RELEASE
+} kbd_event_type_t;
+
 /** Console event structure. */
 typedef struct {
 	/** Press or release event. */
-	console_ev_type_t type;
+	kbd_event_type_t type;
 	
 	/** Keycode of the key that was pressed or released. */
@@ -63,22 +87,26 @@
 	/** The character that was generated or '\0' for none. */
 	wchar_t c;
-} console_event_t;
+} kbd_event_t;
 
-extern void console_clear(int phone);
+extern console_ctrl_t *console_init(FILE *, FILE *);
+extern void console_done(console_ctrl_t *);
+extern bool console_kcon(void);
 
-extern int console_get_size(int phone, sysarg_t *cols, sysarg_t *rows);
-extern int console_get_pos(int phone, sysarg_t *col, sysarg_t *row);
-extern void console_set_pos(int phone, sysarg_t col, sysarg_t row);
+extern void console_flush(console_ctrl_t *);
+extern void console_clear(console_ctrl_t *);
 
-extern void console_set_style(int phone, uint8_t style);
-extern void console_set_color(int phone, uint8_t fg_color, uint8_t bg_color,
-    uint8_t flags);
-extern void console_set_rgb_color(int phone, uint32_t fg_color, uint32_t bg_color);
+extern int console_get_size(console_ctrl_t *, sysarg_t *, sysarg_t *);
+extern int console_get_pos(console_ctrl_t *, sysarg_t *, sysarg_t *);
+extern void console_set_pos(console_ctrl_t *, sysarg_t, sysarg_t);
 
-extern void console_cursor_visibility(int phone, bool show);
-extern int console_get_color_cap(int phone, sysarg_t *ccap);
-extern void console_kcon_enable(int phone);
+extern void console_set_style(console_ctrl_t *, uint8_t);
+extern void console_set_color(console_ctrl_t *, uint8_t, uint8_t, uint8_t);
+extern void console_set_rgb_color(console_ctrl_t *, uint32_t, uint32_t);
 
-extern bool console_get_event(int phone, console_event_t *event);
+extern void console_cursor_visibility(console_ctrl_t *, bool);
+extern int console_get_color_cap(console_ctrl_t *, sysarg_t *);
+extern bool console_get_kbd_event(console_ctrl_t *, kbd_event_t *);
+extern bool console_get_kbd_event_timeout(console_ctrl_t *, kbd_event_t *,
+    suseconds_t *);
 
 #endif
Index: uspace/lib/c/include/ipc/devmap.h
===================================================================
--- uspace/lib/c/include/ipc/devmap.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/ipc/devmap.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -31,6 +31,6 @@
  */
 
-#ifndef DEVMAP_DEVMAP_H_
-#define DEVMAP_DEVMAP_H_
+#ifndef LIBC_IPC_DEVMAP_H_
+#define LIBC_IPC_DEVMAP_H_
 
 #include <ipc/common.h>
Index: uspace/lib/c/include/ipc/ipc.h
===================================================================
--- uspace/lib/c/include/ipc/ipc.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/ipc/ipc.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -42,4 +42,5 @@
 #include <sys/types.h>
 #include <ipc/common.h>
+#include <kernel/ipc/ipc_methods.h>
 #include <kernel/synch/synch.h>
 #include <task.h>
@@ -255,4 +256,5 @@
 extern int ipc_connect_to_me(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t *,
     sysarg_t *);
+extern int ipc_connect_me(int);
 extern int ipc_connect_me_to(int, sysarg_t, sysarg_t, sysarg_t);
 extern int ipc_connect_me_to_blocking(int, sysarg_t, sysarg_t, sysarg_t);
Index: uspace/lib/c/include/ipc/ns.h
===================================================================
--- uspace/lib/c/include/ipc/ns.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/ipc/ns.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -33,8 +33,7 @@
  */
 
-#ifndef LIBC_NS_H_
-#define LIBC_NS_H_
+#ifndef LIBC_IPC_NS_H_
+#define LIBC_IPC_NS_H_
 
-#include <sys/types.h>
 #include <ipc/common.h>
 
@@ -46,8 +45,4 @@
 } ns_request_t;
 
-extern int service_register(sysarg_t);
-extern int service_connect(sysarg_t, sysarg_t, sysarg_t);
-extern int service_connect_blocking(sysarg_t, sysarg_t, sysarg_t);
-
 #endif
 
Index: uspace/lib/c/include/ipc/serial_ctl.h
===================================================================
--- uspace/lib/c/include/ipc/serial_ctl.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/ipc/serial_ctl.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -32,11 +32,13 @@
 #include <ipc/dev_iface.h>
 
-/** ipc methods for getting/setting serial communication properties
- * 	1st ipc arg: baud rate
- * 	2nd ipc arg: parity
- *	3rd ipc arg: number of bits in one word
- *	4th ipc arg: number of stop bits
+/** IPC methods for getting/setting serial communication properties
+ *
+ * 1st IPC arg: baud rate
+ * 2nd IPC arg: parity
+ * 3rd IPC arg: number of bits in one word
+ * 4th IPC arg: number of stop bits
+ *
  */
-typedef enum {	
+typedef enum {
 	SERIAL_GET_COM_PROPS = DEV_FIRST_CUSTOM_METHOD,
 	SERIAL_SET_COM_PROPS
@@ -48,5 +50,5 @@
 	SERIAL_EVEN_PARITY = 3,
 	SERIAL_MARK_PARITY = 5,
-	SERIAL_SPACE_PARITY = 7	
+	SERIAL_SPACE_PARITY = 7
 } serial_parity_t;
 
Index: uspace/lib/c/include/ipc/vfs.h
===================================================================
--- uspace/lib/c/include/ipc/vfs.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/ipc/vfs.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -69,4 +69,5 @@
 	VFS_IN_FSTAT,
 	VFS_IN_CLOSE,
+	VFS_IN_PING,
 	VFS_IN_MOUNT,
 	VFS_IN_UNMOUNT,
Index: uspace/lib/c/include/loader/loader.h
===================================================================
--- uspace/lib/c/include/loader/loader.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/loader/loader.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -40,9 +40,7 @@
 #include <vfs/vfs.h>
 
-/** Abstraction of a loader connection */
-typedef struct {
-	/** ID of the phone connected to the loader. */
-	int phone_id;
-} loader_t;
+/** Forward declararion */
+struct loader;
+typedef struct loader loader_t;
 
 extern int loader_spawn(const char *);
Index: uspace/lib/c/include/ns.h
===================================================================
--- uspace/lib/c/include/ns.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/include/ns.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_NS_H_
+#define LIBC_NS_H_
+
+#include <sys/types.h>
+#include <task.h>
+#include <async.h>
+
+extern int service_register(sysarg_t);
+extern async_sess_t *service_connect(exch_mgmt_t, sysarg_t, sysarg_t, sysarg_t);
+extern async_sess_t *service_connect_blocking(exch_mgmt_t, sysarg_t, sysarg_t,
+    sysarg_t);
+
+extern int ns_ping(void);
+extern int ns_intro(task_id_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/ns_obsolete.h
===================================================================
--- uspace/lib/c/include/ns_obsolete.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/include/ns_obsolete.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_NS_OBSOLETE_H_
+#define LIBC_NS_OBSOLETE_H_
+
+#include <sys/types.h>
+#include <task.h>
+
+extern int service_obsolete_connect(sysarg_t, sysarg_t, sysarg_t);
+extern int service_obsolete_connect_blocking(sysarg_t, sysarg_t,
+    sysarg_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/include/stdio.h
===================================================================
--- uspace/lib/c/include/stdio.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/stdio.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -97,47 +97,7 @@
 };
 
-typedef struct {
-	/** Linked list pointer. */
-	link_t link;
-	
-	/** Underlying file descriptor. */
-	int fd;
-	
-	/** Error indicator. */
-	int error;
-	
-	/** End-of-file indicator. */
-	int eof;
-	
-	/** Klog indicator */
-	int klog;
-	
-	/** Phone to the file provider */
-	int phone;
-
-	/**
-	 * Non-zero if the stream needs sync on fflush(). XXX change
-	 * console semantics so that sync is not needed.
-	 */
-	int need_sync;
-
-	/** Buffering type */
-	enum _buffer_type btype;
-
-	/** Buffer */
-	uint8_t *buf;
-
-	/** Buffer size */
-	size_t buf_size;
-
-	/** Buffer state */
-	enum _buffer_state buf_state;
-
-	/** Buffer I/O pointer */
-	uint8_t *buf_head;
-
-	/** Points to end of occupied space when in read mode. */
-	uint8_t *buf_tail;
-} FILE;
+/** Forward declaration */
+struct _IO_FILE;
+typedef struct _IO_FILE FILE;
 
 extern FILE *stdin;
Index: uspace/lib/c/include/udebug.h
===================================================================
--- uspace/lib/c/include/udebug.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/udebug.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -38,18 +38,23 @@
 #include <kernel/udebug/udebug.h>
 #include <sys/types.h>
+#include <async.h>
 
 typedef sysarg_t thash_t;
 
-int udebug_begin(int);
-int udebug_end(int);
-int udebug_set_evmask(int, udebug_evmask_t);
-int udebug_thread_read(int, void *, size_t , size_t *, size_t *);
-int udebug_name_read(int, void *, size_t, size_t *, size_t *);
-int udebug_areas_read(int, void *, size_t, size_t *, size_t *);
-int udebug_mem_read(int, void *, uintptr_t, size_t);
-int udebug_args_read(int, thash_t, sysarg_t *);
-int udebug_regs_read(int, thash_t, void *);
-int udebug_go(int, thash_t, udebug_event_t *, sysarg_t *, sysarg_t *);
-int udebug_stop(int, thash_t);
+extern int udebug_begin(async_sess_t *);
+extern int udebug_end(async_sess_t *);
+extern int udebug_set_evmask(async_sess_t *, udebug_evmask_t);
+extern int udebug_thread_read(async_sess_t *, void *, size_t , size_t *,
+    size_t *);
+extern int udebug_name_read(async_sess_t *, void *, size_t, size_t *,
+    size_t *);
+extern int udebug_areas_read(async_sess_t *, void *, size_t, size_t *,
+    size_t *);
+extern int udebug_mem_read(async_sess_t *, void *, uintptr_t, size_t);
+extern int udebug_args_read(async_sess_t *, thash_t, sysarg_t *);
+extern int udebug_regs_read(async_sess_t *, thash_t, void *);
+extern int udebug_go(async_sess_t *, thash_t, udebug_event_t *, sysarg_t *,
+    sysarg_t *);
+extern int udebug_stop(async_sess_t *, thash_t);
 
 #endif
Index: uspace/lib/c/include/vfs/vfs.h
===================================================================
--- uspace/lib/c/include/vfs/vfs.h	(revision 764d71e80b7c72cc3d48b7d5d789623dd67c6961)
+++ uspace/lib/c/include/vfs/vfs.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -41,7 +41,9 @@
 #include <stdio.h>
 
-/**
- * This type is a libc version of the VFS triplet.
- * It uniquely identifies a file system node within a file system instance.
+/** Libc version of the VFS triplet.
+ *
+ * Unique identification of a file system node
+ * within a file system instance.
+ *
  */
 typedef struct {
@@ -58,9 +60,7 @@
 
 extern int open_node(fdi_node_t *, int);
-extern int fd_phone(int);
 extern int fd_node(int, fdi_node_t *);
 
 extern FILE *fopen_node(fdi_node_t *, const char *);
-extern int fphone(FILE *);
 extern int fnode(FILE *, fdi_node_t *);
 
Index: uspace/lib/c/include/vfs/vfs_sess.h
===================================================================
--- uspace/lib/c/include/vfs/vfs_sess.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
+++ uspace/lib/c/include/vfs/vfs_sess.h	(revision 79ae36ddc409577eb0da3750b3a7280e034566a2)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_VFS_SESS_H_
+#define LIBC_VFS_SESS_H_
+
+#include <async.h>
+#include <stdio.h>
+
+extern async_sess_t *fd_session(exch_mgmt_t, int);
+extern async_sess_t *fsession(exch_mgmt_t, FILE *);
+
+#endif
+
+/** @}
+ */
