Index: libc/generic/async.c
===================================================================
--- libc/generic/async.c	(revision 3f695aad3bf378bdfa470559599fcc9e9df87075)
+++ libc/generic/async.c	(revision fc42b283b9c9e1662a0a330257f53d247c2a458a)
@@ -94,5 +94,5 @@
 #include <arch/barrier.h>
 
-static atomic_t async_futex = FUTEX_INITIALIZER;
+atomic_t async_futex = FUTEX_INITIALIZER;
 static hash_table_t conn_hash_table;
 static LIST_INITIALIZE(timeout_list);
Index: libc/generic/ipc.c
===================================================================
--- libc/generic/ipc.c	(revision 3f695aad3bf378bdfa470559599fcc9e9df87075)
+++ libc/generic/ipc.c	(revision fc42b283b9c9e1662a0a330257f53d247c2a458a)
@@ -36,4 +36,6 @@
 #include <futex.h>
 #include <kernel/synch/synch.h>
+#include <async.h>
+#include <psthread.h>
 
 /** Structure used for keeping track of sent async msgs 
@@ -53,8 +55,15 @@
 		} msg;
 	}u;
+	pstid_t ptid;   /**< Thread waiting for sending this msg */
 } async_call_t;
 
 LIST_INITIALIZE(dispatched_calls);
-LIST_INITIALIZE(queued_calls);
+
+/* queued_calls is protcted by async_futex, because if the
+ * call cannot be sent into kernel, async framework is used
+ * automatically
+ */
+LIST_INITIALIZE(queued_calls); /**< List of async calls that were not accepted
+				*   by kernel */
 
 static atomic_t ipc_futex = FUTEX_INITIALIZER;
@@ -125,7 +134,14 @@
 		return;
 	}
-		
+
+	call->callback = callback;
+	call->private = private;
+
+	/* We need to make sure that we get callid before
+	 * another thread accesses the queue again */
+	futex_down(&ipc_futex);
 	callid = __SYSCALL4(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, arg2);
 	if (callid == IPC_CALLRET_FATAL) {
+		futex_up(&ipc_futex);
 		/* Call asynchronous handler with error code */
 		if (callback)
@@ -135,22 +151,22 @@
 	}
 
-	call->callback = callback;
-	call->private = private;
-
 	if (callid == IPC_CALLRET_TEMPORARY) {
-		/* Add asynchronous call to queue of non-dispatched async calls */
+		futex_up(&ipc_futex);
+
 		call->u.msg.phoneid = phoneid;
 		IPC_SET_METHOD(call->u.msg.data, method);
 		IPC_SET_ARG1(call->u.msg.data, arg1);
 		IPC_SET_ARG2(call->u.msg.data, arg2);
-		
-		futex_down(&ipc_futex);
+
+		call->ptid = psthread_get_id();
+		futex_down(&async_futex);
 		list_append(&call->list, &queued_calls);
-		futex_up(&ipc_futex);
+
+		psthread_schedule_next_adv(PS_TO_MANAGER);
+		/* Async futex unlocked by previous call */
 		return;
 	}
 	call->u.callid = callid;
 	/* Add call to list of dispatched calls */
-	futex_down(&ipc_futex);
 	list_append(&call->list, &dispatched_calls);
 	futex_up(&ipc_futex);
@@ -195,5 +211,9 @@
 	ipc_callid_t callid;
 
-	futex_down(&ipc_futex);
+	/* TODO: integrate intelligently ipc_futex, so that it
+	 * is locked during ipc_call_async, until it is added
+	 * to dispatched_calls
+	 */
+	futex_down(&async_futex);
 	while (!list_empty(&queued_calls)) {
 		call = list_get_instance(queued_calls.next, async_call_t,
@@ -202,20 +222,25 @@
 		callid = _ipc_call_async(call->u.msg.phoneid,
 					 &call->u.msg.data);
-		if (callid == IPC_CALLRET_TEMPORARY)
+		if (callid == IPC_CALLRET_TEMPORARY) {
 			break;
+		}
 		list_remove(&call->list);
 
+		futex_up(&async_futex);
+		psthread_add_ready(call->ptid);
+		
 		if (callid == IPC_CALLRET_FATAL) {
-			futex_up(&ipc_futex);
 			if (call->callback)
 				call->callback(call->private, ENOENT, NULL);
 			free(call);
-			futex_down(&ipc_futex);
 		} else {
 			call->u.callid = callid;
+			futex_down(&ipc_futex);
 			list_append(&call->list, &dispatched_calls);
+			futex_up(&ipc_futex);
 		}
-	}
-	futex_up(&ipc_futex);
+		futex_down(&async_futex);
+	}
+	futex_up(&async_futex);
 }
 
@@ -265,10 +290,10 @@
 	ipc_callid_t callid;
 
-	try_dispatch_queued_calls();
-	
 	callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
 	/* Handle received answers */
-	if (callid & IPC_CALLID_ANSWERED)
+	if (callid & IPC_CALLID_ANSWERED) {
 		handle_answer(callid, call);
+		try_dispatch_queued_calls();
+	}
 
 	return callid;
Index: libc/include/async.h
===================================================================
--- libc/include/async.h	(revision 3f695aad3bf378bdfa470559599fcc9e9df87075)
+++ libc/include/async.h	(revision fc42b283b9c9e1662a0a330257f53d247c2a458a)
@@ -5,4 +5,5 @@
 #include <psthread.h>
 #include <sys/time.h>
+#include <atomic.h>
 
 typedef ipc_callid_t aid_t;
@@ -27,3 +28,6 @@
 void interrupt_received(ipc_call_t *call)  __attribute__((weak));
 
+
+extern atomic_t async_futex;
+
 #endif
