Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision df7f5cea55c99ad82d12a32bcd20102e9fb8cbe2)
+++ uspace/lib/c/generic/task.c	(revision 4be73ba2544fcfad829cc03bac95ab5135d899d4)
@@ -2,4 +2,5 @@
  * Copyright (c) 2006 Jakub Jermar
  * Copyright (c) 2008 Jiri Svoboda
+ * Copyright (c) 2014 Martin Sucha
  * All rights reserved.
  *
@@ -94,4 +95,6 @@
  *
  * @param id   If not NULL, the ID of the task is stored here on success.
+ * @param wait If not NULL, setup waiting for task's return value and store
+ *             the information necessary for waiting here on success.
  * @param path Pathname of the binary to execute.
  * @param argv Command-line arguments.
@@ -100,5 +103,6 @@
  *
  */
-int task_spawnv(task_id_t *id, const char *path, const char *const args[])
+int task_spawnv(task_id_t *id, task_wait_t *wait, const char *path,
+    const char *const args[])
 {
 	/* Send default files */
@@ -125,5 +129,5 @@
 	files[3] = NULL;
 	
-	return task_spawnvf(id, path, args, files);
+	return task_spawnvf(id, wait, path, args, files);
 }
 
@@ -135,4 +139,6 @@
  *
  * @param id    If not NULL, the ID of the task is stored here on success.
+ * @param wait  If not NULL, setup waiting for task's return value and store
+ *              the information necessary for waiting here on success.
  * @param path  Pathname of the binary to execute.
  * @param argv  Command-line arguments.
@@ -142,6 +148,6 @@
  *
  */
-int task_spawnvf(task_id_t *id, const char *path, const char *const args[],
-    int *const files[])
+int task_spawnvf(task_id_t *id, task_wait_t *wait, const char *path,
+    const char *const args[], int *const files[])
 {
 	/* Connect to a program loader. */
@@ -150,4 +156,6 @@
 		return EREFUSED;
 	
+	bool wait_initialized = false;
+	
 	/* Get task ID. */
 	task_id_t task_id;
@@ -181,4 +189,12 @@
 		goto error;
 	
+	/* Setup waiting for return value if needed */
+	if (wait) {
+		rc = task_setup_wait(task_id, wait);
+		if (rc != EOK)
+			goto error;
+		wait_initialized = true;
+	}
+	
 	/* Run it. */
 	rc = loader_run(ldr);
@@ -193,4 +209,7 @@
 	
 error:
+	if (wait_initialized)
+		task_cancel_wait(wait);
+	
 	/* Error exit */
 	loader_abort(ldr);
@@ -204,4 +223,6 @@
  *
  * @param id   If not NULL, the ID of the task is stored here on success.
+ * @param wait If not NULL, setup waiting for task's return value and store
+ *             the information necessary for waiting here on success.
  * @param path Pathname of the binary to execute.
  * @param cnt  Number of arguments.
@@ -211,5 +232,6 @@
  *
  */
-int task_spawn(task_id_t *task_id, const char *path, int cnt, va_list ap)
+int task_spawn(task_id_t *task_id, task_wait_t *wait, const char *path,
+    int cnt, va_list ap)
 {
 	/* Allocate argument list. */
@@ -227,5 +249,5 @@
 	
 	/* Spawn task. */
-	int rc = task_spawnv(task_id, path, arglist);
+	int rc = task_spawnv(task_id, wait, path, arglist);
 	
 	/* Free argument list. */
@@ -240,4 +262,6 @@
  *
  * @param id   If not NULL, the ID of the task is stored here on success.
+ * @param wait If not NULL, setup waiting for task's return value and store
+ *             the information necessary for waiting here on success.
  * @param path Pathname of the binary to execute.
  * @param ...  Command-line arguments.
@@ -246,5 +270,5 @@
  *
  */
-int task_spawnl(task_id_t *task_id, const char *path, ...)
+int task_spawnl(task_id_t *task_id, task_wait_t *wait, const char *path, ...)
 {
 	/* Count the number of arguments. */
@@ -262,5 +286,5 @@
 	
 	va_start(ap, path);
-	int rc = task_spawn(task_id, path, cnt, ap);
+	int rc = task_spawn(task_id, wait, path, cnt, ap);
 	va_end(ap);
 	
@@ -268,19 +292,90 @@
 }
 
-int task_wait(task_id_t id, task_exit_t *texit, int *retval)
+/** Setup waiting for a task.
+ * 
+ * If the task finishes after this call succeeds, it is guaranteed that
+ * task_wait(wait, &texit, &retval) will return correct return value for
+ * the task.
+ *
+ * @param id   ID of the task to setup waiting for.
+ * @param wait Information necessary for the later task_wait call is stored here.
+ *
+ * @return EOK on success, else error code.
+ */
+int task_setup_wait(task_id_t id, task_wait_t *wait)
+{
+	async_exch_t *exch = async_exchange_begin(session_ns);
+	wait->aid = async_send_2(exch, NS_TASK_WAIT, LOWER32(id), UPPER32(id),
+	    &wait->result);
+	async_exchange_end(exch);
+
+	return EOK;
+}
+
+/** Cancel waiting for a task.
+ *
+ * This can be called *instead of* task_wait if the caller is not interested
+ * in waiting for the task anymore.
+ *
+ * This function cannot be called if the task_wait was already called.
+ *
+ * @param wait task_wait_t previously initialized by task_setup_wait.
+ */
+void task_cancel_wait(task_wait_t *wait) {
+	async_forget(wait->aid);
+}
+
+/** Wait for a task to finish.
+ *
+ * This function returns correct values even if the task finished in
+ * between task_setup_wait and this task_wait call.
+ *
+ * This function cannot be called more than once with the same task_wait_t
+ * (it can be reused, but must be reinitialized with task_setup_wait first)
+ *
+ * @param wait   task_wait_t previously initialized by task_setup_wait.
+ * @param texit  Store type of task exit here.
+ * @param retval Store return value of the task here.
+ * 
+ * @return EOK on success, else error code.
+ */
+int task_wait(task_wait_t *wait, 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 = (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;
+
+	sysarg_t rc;
+	async_wait_for(wait->aid, &rc);
+
+	if (rc == EOK) {
+		*texit = IPC_GET_ARG1(wait->result);
+		*retval = IPC_GET_ARG2(wait->result);
+	}
+
+	return rc;
+}
+
+/** Wait for a task to finish by its id.
+ *
+ * Note that this will fail with ENOENT if the task id is not registered in ns
+ * (e.g. if the task finished). If you are spawning a task and need to wait
+ * for its completion, use wait parameter of the task_spawn* functions instead
+ * to prevent a race where the task exits before you may have a chance to wait
+ * wait for it.
+ *
+ * @param id ID of the task to wait for.
+ * @param texit  Store type of task exit here.
+ * @param retval Store return value of the task here.
+ * 
+ * @return EOK on success, else error code.
+ */
+int task_wait_task_id(task_id_t id, task_exit_t *texit, int *retval)
+{
+	task_wait_t wait;
+	int rc = task_setup_wait(id, &wait);
+	if (rc != EOK)
+		return rc;
+	
+	return task_wait(&wait, texit, retval);
 }
 
Index: uspace/lib/c/include/async.h
===================================================================
--- uspace/lib/c/include/async.h	(revision df7f5cea55c99ad82d12a32bcd20102e9fb8cbe2)
+++ uspace/lib/c/include/async.h	(revision 4be73ba2544fcfad829cc03bac95ab5135d899d4)
@@ -45,5 +45,5 @@
 #include <atomic.h>
 #include <stdbool.h>
-#include <task.h>
+#include <abi/proc/task.h>
 #include <abi/ddi/irq.h>
 #include <abi/ipc/event.h>
Index: uspace/lib/c/include/ipc/common.h
===================================================================
--- uspace/lib/c/include/ipc/common.h	(revision df7f5cea55c99ad82d12a32bcd20102e9fb8cbe2)
+++ uspace/lib/c/include/ipc/common.h	(revision 4be73ba2544fcfad829cc03bac95ab5135d899d4)
@@ -39,5 +39,5 @@
 #include <abi/ipc/ipc.h>
 #include <atomic.h>
-#include <task.h>
+#include <abi/proc/task.h>
 
 #define IPC_FLAG_BLOCKING  0x01
Index: uspace/lib/c/include/ipc/ipc.h
===================================================================
--- uspace/lib/c/include/ipc/ipc.h	(revision df7f5cea55c99ad82d12a32bcd20102e9fb8cbe2)
+++ uspace/lib/c/include/ipc/ipc.h	(revision 4be73ba2544fcfad829cc03bac95ab5135d899d4)
@@ -44,5 +44,5 @@
 #include <abi/ipc/methods.h>
 #include <abi/synch.h>
-#include <task.h>
+#include <abi/proc/task.h>
 
 typedef void (*ipc_async_callback_t)(void *, int, ipc_call_t *);
Index: uspace/lib/c/include/loader/loader.h
===================================================================
--- uspace/lib/c/include/loader/loader.h	(revision df7f5cea55c99ad82d12a32bcd20102e9fb8cbe2)
+++ uspace/lib/c/include/loader/loader.h	(revision 4be73ba2544fcfad829cc03bac95ab5135d899d4)
@@ -37,5 +37,5 @@
 #define LIBC_LOADER_H_
 
-#include <task.h>
+#include <abi/proc/task.h>
 
 /** Forward declararion */
Index: uspace/lib/c/include/task.h
===================================================================
--- uspace/lib/c/include/task.h	(revision df7f5cea55c99ad82d12a32bcd20102e9fb8cbe2)
+++ uspace/lib/c/include/task.h	(revision 4be73ba2544fcfad829cc03bac95ab5135d899d4)
@@ -39,9 +39,14 @@
 #include <abi/proc/task.h>
 #include <stdarg.h>
+#include <async.h>
+#include <types/task.h>
 
-typedef enum {
-	TASK_EXIT_NORMAL,
-	TASK_EXIT_UNEXPECTED
-} task_exit_t;
+typedef struct {
+	ipc_call_t result;
+	aid_t aid;
+} task_wait_t;
+
+struct _TASK;
+typedef struct _TASK task_t;
 
 extern task_id_t task_get_id(void);
@@ -49,11 +54,16 @@
 extern int task_kill(task_id_t);
 
-extern int task_spawnv(task_id_t *, const char *path, const char *const []);
-extern int task_spawnvf(task_id_t *, const char *path, const char *const [],
-    int *const []);
-extern int task_spawn(task_id_t *, const char *path, int, va_list ap);
-extern int task_spawnl(task_id_t *, const char *path, ...);
+extern int task_spawnv(task_id_t *, task_wait_t *, const char *path,
+    const char *const []);
+extern int task_spawnvf(task_id_t *, task_wait_t *, const char *path,
+    const char *const [], int *const []);
+extern int task_spawn(task_id_t *, task_wait_t *, const char *path, int,
+    va_list ap);
+extern int task_spawnl(task_id_t *, task_wait_t *, const char *path, ...);
 
-extern int task_wait(task_id_t id, task_exit_t *, int *);
+extern int task_setup_wait(task_id_t, task_wait_t *);
+extern void task_cancel_wait(task_wait_t *);
+extern int task_wait(task_wait_t *, task_exit_t *, int *);
+extern int task_wait_task_id(task_id_t, task_exit_t *, int *);
 extern int task_retval(int);
 
Index: uspace/lib/c/include/types/task.h
===================================================================
--- uspace/lib/c/include/types/task.h	(revision 4be73ba2544fcfad829cc03bac95ab5135d899d4)
+++ uspace/lib/c/include/types/task.h	(revision 4be73ba2544fcfad829cc03bac95ab5135d899d4)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2006 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_TYPES_TASK_H_
+#define LIBC_TYPES_TASK_H_
+
+typedef enum {
+	TASK_EXIT_NORMAL,
+	TASK_EXIT_UNEXPECTED
+} task_exit_t;
+
+#endif
+
+/** @}
+ */
