Changes in uspace/lib/c/generic/task.c [9f5cf68:1c635d6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/task.c
r9f5cf68 r1c635d6 2 2 * Copyright (c) 2006 Jakub Jermar 3 3 * Copyright (c) 2008 Jiri Svoboda 4 * Copyright (c) 2014 Martin Sucha 4 5 * All rights reserved. 5 6 * … … 94 95 * 95 96 * @param id If not NULL, the ID of the task is stored here on success. 97 * @param wait If not NULL, setup waiting for task's return value and store 98 * the information necessary for waiting here on success. 96 99 * @param path Pathname of the binary to execute. 97 100 * @param argv Command-line arguments. … … 100 103 * 101 104 */ 102 int task_spawnv(task_id_t *id, const char *path, const char *const args[]) 105 int task_spawnv(task_id_t *id, task_wait_t *wait, const char *path, 106 const char *const args[]) 103 107 { 104 108 /* Send default files */ … … 125 129 files[3] = NULL; 126 130 127 return task_spawnvf(id, path, args, files);131 return task_spawnvf(id, wait, path, args, files); 128 132 } 129 133 … … 135 139 * 136 140 * @param id If not NULL, the ID of the task is stored here on success. 141 * @param wait If not NULL, setup waiting for task's return value and store 142 * the information necessary for waiting here on success. 137 143 * @param path Pathname of the binary to execute. 138 144 * @param argv Command-line arguments. … … 142 148 * 143 149 */ 144 int task_spawnvf(task_id_t *id, const char *path, const char *const args[],145 int *const files[])150 int task_spawnvf(task_id_t *id, task_wait_t *wait, const char *path, 151 const char *const args[], int *const files[]) 146 152 { 147 153 /* Connect to a program loader. */ … … 150 156 return EREFUSED; 151 157 158 bool wait_initialized = false; 159 152 160 /* Get task ID. */ 153 161 task_id_t task_id; … … 181 189 goto error; 182 190 191 /* Setup waiting for return value if needed */ 192 if (wait) { 193 rc = task_setup_wait(task_id, wait); 194 if (rc != EOK) 195 goto error; 196 wait_initialized = true; 197 } 198 183 199 /* Run it. */ 184 200 rc = loader_run(ldr); … … 193 209 194 210 error: 211 if (wait_initialized) 212 task_cancel_wait(wait); 213 195 214 /* Error exit */ 196 215 loader_abort(ldr); … … 204 223 * 205 224 * @param id If not NULL, the ID of the task is stored here on success. 225 * @param wait If not NULL, setup waiting for task's return value and store 226 * the information necessary for waiting here on success. 206 227 * @param path Pathname of the binary to execute. 207 228 * @param cnt Number of arguments. … … 211 232 * 212 233 */ 213 int task_spawn(task_id_t *task_id, const char *path, int cnt, va_list ap) 234 int task_spawn(task_id_t *task_id, task_wait_t *wait, const char *path, 235 int cnt, va_list ap) 214 236 { 215 237 /* Allocate argument list. */ … … 227 249 228 250 /* Spawn task. */ 229 int rc = task_spawnv(task_id, path, arglist);251 int rc = task_spawnv(task_id, wait, path, arglist); 230 252 231 253 /* Free argument list. */ … … 240 262 * 241 263 * @param id If not NULL, the ID of the task is stored here on success. 264 * @param wait If not NULL, setup waiting for task's return value and store 265 * the information necessary for waiting here on success. 242 266 * @param path Pathname of the binary to execute. 243 267 * @param ... Command-line arguments. … … 246 270 * 247 271 */ 248 int task_spawnl(task_id_t *task_id, const char *path, ...)272 int task_spawnl(task_id_t *task_id, task_wait_t *wait, const char *path, ...) 249 273 { 250 274 /* Count the number of arguments. */ … … 262 286 263 287 va_start(ap, path); 264 int rc = task_spawn(task_id, path, cnt, ap);288 int rc = task_spawn(task_id, wait, path, cnt, ap); 265 289 va_end(ap); 266 290 … … 268 292 } 269 293 270 int task_wait(task_id_t id, task_exit_t *texit, int *retval) 294 /** Setup waiting for a task. 295 * 296 * If the task finishes after this call succeeds, it is guaranteed that 297 * task_wait(wait, &texit, &retval) will return correct return value for 298 * the task. 299 * 300 * @param id ID of the task to setup waiting for. 301 * @param wait Information necessary for the later task_wait call is stored here. 302 * 303 * @return EOK on success, else error code. 304 */ 305 int task_setup_wait(task_id_t id, task_wait_t *wait) 306 { 307 async_exch_t *exch = async_exchange_begin(session_ns); 308 wait->aid = async_send_2(exch, NS_TASK_WAIT, LOWER32(id), UPPER32(id), 309 &wait->result); 310 async_exchange_end(exch); 311 312 return EOK; 313 } 314 315 /** Cancel waiting for a task. 316 * 317 * This can be called *instead of* task_wait if the caller is not interested 318 * in waiting for the task anymore. 319 * 320 * This function cannot be called if the task_wait was already called. 321 * 322 * @param wait task_wait_t previously initialized by task_setup_wait. 323 */ 324 void task_cancel_wait(task_wait_t *wait) { 325 async_forget(wait->aid); 326 } 327 328 /** Wait for a task to finish. 329 * 330 * This function returns correct values even if the task finished in 331 * between task_setup_wait and this task_wait call. 332 * 333 * This function cannot be called more than once with the same task_wait_t 334 * (it can be reused, but must be reinitialized with task_setup_wait first) 335 * 336 * @param wait task_wait_t previously initialized by task_setup_wait. 337 * @param texit Store type of task exit here. 338 * @param retval Store return value of the task here. 339 * 340 * @return EOK on success, else error code. 341 */ 342 int task_wait(task_wait_t *wait, task_exit_t *texit, int *retval) 271 343 { 272 344 assert(texit); 273 345 assert(retval); 274 275 async_exch_t *exch = async_exchange_begin(session_ns); 276 sysarg_t te, rv; 277 int rc = (int) async_req_2_2(exch, NS_TASK_WAIT, LOWER32(id), 278 UPPER32(id), &te, &rv); 279 async_exchange_end(exch); 280 281 *texit = te; 282 *retval = rv; 283 284 return rc; 346 347 sysarg_t rc; 348 async_wait_for(wait->aid, &rc); 349 350 if (rc == EOK) { 351 *texit = IPC_GET_ARG1(wait->result); 352 *retval = IPC_GET_ARG2(wait->result); 353 } 354 355 return rc; 356 } 357 358 /** Wait for a task to finish by its id. 359 * 360 * Note that this will fail with ENOENT if the task id is not registered in ns 361 * (e.g. if the task finished). If you are spawning a task and need to wait 362 * for its completion, use wait parameter of the task_spawn* functions instead 363 * to prevent a race where the task exits before you may have a chance to wait 364 * wait for it. 365 * 366 * @param id ID of the task to wait for. 367 * @param texit Store type of task exit here. 368 * @param retval Store return value of the task here. 369 * 370 * @return EOK on success, else error code. 371 */ 372 int task_wait_task_id(task_id_t id, task_exit_t *texit, int *retval) 373 { 374 task_wait_t wait; 375 int rc = task_setup_wait(id, &wait); 376 if (rc != EOK) 377 return rc; 378 379 return task_wait(&wait, texit, retval); 285 380 } 286 381
Note:
See TracChangeset
for help on using the changeset viewer.