Index: generic/include/ipc/ipc.h
===================================================================
--- generic/include/ipc/ipc.h	(revision 1065603efb7bcf9b443a20c1bfea32b1545909c0)
+++ generic/include/ipc/ipc.h	(revision 5f62ef99a9c5aa3020510303c82ab8fcbfa0b83b)
@@ -33,4 +33,7 @@
 /* - the uspace may not be able to utilize full length */
 #define IPC_CALL_LEN    4
+
+/** Maximum active async calls per thread */
+#define IPC_MAX_ASYNC_CALLS  4
 
 /* Flags for calls */
Index: generic/include/proc/task.h
===================================================================
--- generic/include/proc/task.h	(revision 1065603efb7bcf9b443a20c1bfea32b1545909c0)
+++ generic/include/proc/task.h	(revision 5f62ef99a9c5aa3020510303c82ab8fcbfa0b83b)
@@ -41,6 +41,8 @@
 	link_t tasks_link;	/**< Link to other tasks within the system. */
 	as_t *as;		/**< Address space. */
+	/* IPC stuff */
 	answerbox_t answerbox;  /**< Communication endpoint */
 	phone_t phones[IPC_MAX_PHONES];
+	atomic_t active_calls;  /**< Active asynchronous messages */
 };
 
Index: generic/include/syscall/syscall.h
===================================================================
--- generic/include/syscall/syscall.h	(revision 1065603efb7bcf9b443a20c1bfea32b1545909c0)
+++ generic/include/syscall/syscall.h	(revision 5f62ef99a9c5aa3020510303c82ab8fcbfa0b83b)
@@ -34,6 +34,7 @@
 	SYS_IO,
 	SYS_MREMAP,
+	SYS_IPC_CALL_SYNC_FAST,
 	SYS_IPC_CALL_SYNC,
-	SYS_IPC_CALL_SYNC_MEDIUM,
+	SYS_IPC_CALL_ASYNC_FAST,
 	SYS_IPC_CALL_ASYNC,
 	SYS_IPC_ANSWER,
Index: generic/src/ipc/ns.c
===================================================================
--- generic/src/ipc/ns.c	(revision 1065603efb7bcf9b443a20c1bfea32b1545909c0)
+++ generic/src/ipc/ns.c	(revision 5f62ef99a9c5aa3020510303c82ab8fcbfa0b83b)
@@ -46,6 +46,9 @@
 		switch (IPC_GET_METHOD(call->data)) {
 		case NS_PING:
-			printf("Ping.\n");
+			printf("Ping - %X, %X\n", IPC_GET_ARG1(call->data),
+			       IPC_GET_ARG2(call->data));
 			IPC_SET_RETVAL(call->data, 0);
+			IPC_SET_ARG1(call->data, 0xdeaddead);
+			IPC_SET_ARG2(call->data, 0xdeaddea2);
 			break;
 		default:
Index: generic/src/proc/task.c
===================================================================
--- generic/src/proc/task.c	(revision 1065603efb7bcf9b443a20c1bfea32b1545909c0)
+++ generic/src/proc/task.c	(revision 5f62ef99a9c5aa3020510303c82ab8fcbfa0b83b)
@@ -82,4 +82,5 @@
 	if (ipc_phone_0)
 		ipc_phone_init(&ta->phones[0], ipc_phone_0);
+	atomic_set(&ta->active_calls, 0);
 	
 	ipl = interrupts_disable();
Index: generic/src/syscall/syscall.c
===================================================================
--- generic/src/syscall/syscall.c	(revision 1065603efb7bcf9b443a20c1bfea32b1545909c0)
+++ generic/src/syscall/syscall.c	(revision 5f62ef99a9c5aa3020510303c82ab8fcbfa0b83b)
@@ -57,4 +57,17 @@
 }
 
+static phone_t * get_phone(__native phoneid)
+{
+	phone_t *phone;
+
+	if (phoneid >= IPC_MAX_PHONES)
+		return NULL;
+
+	phone = &TASK->phones[phoneid];
+	if (!phone->callee)
+		return NULL;
+	return phone;
+}
+
 /** Send a call over IPC, wait for reply, return to user
  *
@@ -62,6 +75,6 @@
            -2 on 'Too many async request, handle answers first
  */
-static __native sys_ipc_call_sync(__native phoneid, __native method, 
-				   __native arg1, __native *data)
+static __native sys_ipc_call_sync_fast(__native phoneid, __native method, 
+				       __native arg1, __native *data)
 {
 	call_t call;
@@ -69,9 +82,6 @@
 	/* Special answerbox for synchronous messages */
 
-	if (phoneid >= IPC_MAX_PHONES)
-		return IPC_CALLRET_FATAL;
-
-	phone = &TASK->phones[phoneid];
-	if (!phone->callee)
+	phone = get_phone(phoneid);
+	if (!phone)
 		return IPC_CALLRET_FATAL;
 
@@ -87,5 +97,6 @@
 }
 
-static __native sys_ipc_call_sync_medium(__native phoneid, __native *data)
+/** Synchronous IPC call allowing to send whole message */
+static __native sys_ipc_call_sync(__native phoneid, __native *data)
 {
 	call_t call;
@@ -93,9 +104,6 @@
 	/* Special answerbox for synchronous messages */
 
-	if (phoneid >= IPC_MAX_PHONES)
-		return IPC_CALLRET_FATAL;
-
-	phone = &TASK->phones[phoneid];
-	if (!phone->callee)
+	phone = get_phone(phoneid);
+	if (!phone)
 		return IPC_CALLRET_FATAL;
 
@@ -110,4 +118,16 @@
 }
 
+/** Check that the task did not exceed allowed limit
+ *
+ * @return 0 - Limit OK,   -1 - limit exceeded
+ */
+static int check_call_limit(void)
+{
+	if (atomic_inc_post(&TASK->active_calls) > IPC_MAX_ASYNC_CALLS) {
+		atomic_dec(&TASK->active_calls);
+		return -1;
+	}
+	return 0;
+}
 
 /** Send an asynchronous call over ipc
@@ -116,21 +136,17 @@
            -2 on 'Too many async request, handle answers first
  */
-static __native sys_ipc_call_async(__native phoneid, __native method, 
-				   __native arg1, __native arg2)
-{
-	call_t *call;
-	phone_t *phone;
-
-	if (phoneid >= IPC_MAX_PHONES)
-		return IPC_CALLRET_FATAL;
-
-	phone = &TASK->phones[phoneid];
-	if (!phone->callee)
-		return IPC_CALLRET_FATAL;
-
-	/* TODO: Check that we did not exceed system imposed maximum
-	 * of asynchrnously sent messages
-	 * - the userspace should be able to handle it correctly
-	 */
+static __native sys_ipc_call_async_fast(__native phoneid, __native method, 
+					__native arg1, __native arg2)
+{
+	call_t *call;
+	phone_t *phone;
+
+	phone = get_phone(phoneid);
+	if (!phone)
+		return IPC_CALLRET_FATAL;
+
+	if (check_call_limit())
+		return IPC_CALLRET_TEMPORARY;
+
 	call = ipc_call_alloc();
 	IPC_SET_METHOD(call->data, method);
@@ -143,4 +159,29 @@
 }
 
+/** Synchronous IPC call allowing to send whole message
+ *
+ * @return The same as sys_ipc_call_async
+ */
+static __native sys_ipc_call_async(__native phoneid, __native *data)
+{
+	call_t *call;
+	phone_t *phone;
+
+	phone = get_phone(phoneid);
+	if (!phone)
+		return IPC_CALLRET_FATAL;
+
+	if (check_call_limit())
+		return IPC_CALLRET_TEMPORARY;
+
+	call = ipc_call_alloc();
+	copy_from_uspace(&call->data, data, sizeof(call->data));
+	
+	ipc_call(phone, call);
+
+	return (__native) call;
+}
+
+
 /** Send IPC answer */
 static __native sys_ipc_answer(__native callid, __native retval, __native arg1,
@@ -175,7 +216,9 @@
 
 	copy_to_uspace(calldata, &call->data, sizeof(call->data));
+
 	if (call->flags & IPC_CALL_ANSWERED) {
 		ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
 		ipc_call_free(call);
+		atomic_dec(&TASK->active_calls);
 		return ((__native)call) | IPC_CALLID_ANSWERED;
 	}
@@ -192,6 +235,7 @@
 	sys_io,
 	sys_mremap,
+	sys_ipc_call_sync_fast,
 	sys_ipc_call_sync,
-	sys_ipc_call_sync_medium,
+	sys_ipc_call_async_fast,
 	sys_ipc_call_async,
 	sys_ipc_answer,
