Changeset 514d561 in mainline for uspace/lib/c/generic/async/client.c
- Timestamp:
- 2018-07-20T16:27:20Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 05208d9
- Parents:
- 7137f74c
- git-author:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-19 21:52:47)
- git-committer:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-07-20 16:27:20)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async/client.c
r7137f74c r514d561 104 104 #include <ipc/irq.h> 105 105 #include <ipc/event.h> 106 #include <futex.h>107 106 #include <fibril.h> 108 107 #include <adt/hash_table.h> … … 128 127 /** Message data */ 129 128 typedef struct { 130 awaiter_t wdata;129 fibril_event_t received; 131 130 132 131 /** If reply was received. */ … … 136 135 bool forget; 137 136 138 /** If already destroyed. */139 bool destroyed;140 141 137 /** Pointer to where the answer data is stored. */ 142 138 ipc_call_t *dataptr; … … 145 141 } amsg_t; 146 142 147 static void to_event_initialize(to_event_t *to)148 {149 struct timeval tv = { 0, 0 };150 151 to->inlist = false;152 to->occurred = false;153 link_initialize(&to->link);154 to->expires = tv;155 }156 157 static void wu_event_initialize(wu_event_t *wu)158 {159 wu->inlist = false;160 link_initialize(&wu->link);161 }162 163 void awaiter_initialize(awaiter_t *aw)164 {165 aw->fid = 0;166 aw->active = false;167 to_event_initialize(&aw->to_event);168 wu_event_initialize(&aw->wu_event);169 }170 171 143 static amsg_t *amsg_create(void) 172 144 { 173 amsg_t *msg = malloc(sizeof(amsg_t)); 174 if (msg) { 175 msg->done = false; 176 msg->forget = false; 177 msg->destroyed = false; 178 msg->dataptr = NULL; 179 msg->retval = EINVAL; 180 awaiter_initialize(&msg->wdata); 181 } 182 183 return msg; 145 return calloc(1, sizeof(amsg_t)); 184 146 } 185 147 186 148 static void amsg_destroy(amsg_t *msg) 187 149 { 188 if (!msg)189 return;190 191 assert(!msg->destroyed);192 msg->destroyed = true;193 150 free(msg); 194 151 } … … 251 208 msg->retval = IPC_GET_RETVAL(*data); 252 209 253 /* Copy data after futex_down, just in case the call was detached */210 /* Copy data inside lock, just in case the call was detached */ 254 211 if ((msg->dataptr) && (data)) 255 212 *msg->dataptr = *data; 256 213 257 write_barrier();258 259 /* Remove message from timeout list */260 if (msg->wdata.to_event.inlist)261 list_remove(&msg->wdata.to_event.link);262 263 214 msg->done = true; 264 215 265 216 if (msg->forget) { 266 assert(msg->wdata.active);267 217 amsg_destroy(msg); 268 } else if (!msg->wdata.active) { 269 msg->wdata.active = true; 270 fibril_add_ready(msg->wdata.fid); 218 } else { 219 fibril_notify(&msg->received); 271 220 } 272 221 … … 301 250 302 251 msg->dataptr = dataptr; 303 msg->wdata.active = true;304 252 305 253 errno_t rc = ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, … … 343 291 344 292 msg->dataptr = dataptr; 345 msg->wdata.active = true;346 293 347 294 errno_t rc = ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, … … 371 318 372 319 amsg_t *msg = (amsg_t *) amsgid; 373 374 futex_lock(&async_futex); 375 376 assert(!msg->forget); 377 assert(!msg->destroyed); 378 379 if (msg->done) { 380 futex_unlock(&async_futex); 381 goto done; 382 } 383 384 msg->wdata.fid = fibril_get_id(); 385 msg->wdata.active = false; 386 msg->wdata.to_event.inlist = false; 387 388 /* Leave the async_futex locked when entering this function */ 389 fibril_switch(FIBRIL_FROM_BLOCKED); 390 futex_unlock(&async_futex); 391 392 done: 320 fibril_wait_for(&msg->received); 321 393 322 if (retval) 394 323 *retval = msg->retval; … … 420 349 421 350 amsg_t *msg = (amsg_t *) amsgid; 422 423 futex_lock(&async_futex);424 425 assert(!msg->forget);426 assert(!msg->destroyed);427 428 if (msg->done) {429 futex_unlock(&async_futex);430 goto done;431 }432 351 433 352 /* … … 438 357 timeout = 0; 439 358 440 getuptime(&msg->wdata.to_event.expires); 441 tv_add_diff(&msg->wdata.to_event.expires, timeout); 442 443 /* 444 * Current fibril is inserted as waiting regardless of the 445 * "size" of the timeout. 446 * 447 * Checking for msg->done and immediately bailing out when 448 * timeout == 0 would mean that the manager fibril would never 449 * run (consider single threaded program). 450 * Thus the IPC answer would be never retrieved from the kernel. 451 * 452 * Notice that the actual delay would be very small because we 453 * - switch to manager fibril 454 * - the manager sees expired timeout 455 * - and thus adds us back to ready queue 456 * - manager switches back to some ready fibril 457 * (prior it, it checks for incoming IPC). 458 * 459 */ 460 msg->wdata.fid = fibril_get_id(); 461 msg->wdata.active = false; 462 async_insert_timeout(&msg->wdata); 463 464 /* Leave the async_futex locked when entering this function */ 465 fibril_switch(FIBRIL_FROM_BLOCKED); 466 futex_unlock(&async_futex); 467 468 if (!msg->done) 469 return ETIMEOUT; 470 471 done: 359 struct timeval expires; 360 getuptime(&expires); 361 tv_add_diff(&expires, timeout); 362 363 errno_t rc = fibril_wait_timeout(&msg->received, &expires); 364 if (rc != EOK) 365 return rc; 366 472 367 if (retval) 473 368 *retval = msg->retval; … … 475 370 amsg_destroy(msg); 476 371 477 return 0;372 return EOK; 478 373 } 479 374 … … 494 389 495 390 assert(!msg->forget); 496 assert(!msg->destroyed);497 391 498 392 futex_lock(&async_futex); … … 506 400 507 401 futex_unlock(&async_futex); 508 }509 510 /** Wait for specified time.511 *512 * The current fibril is suspended but the thread continues to execute.513 *514 * @param timeout Duration of the wait in microseconds.515 *516 */517 void fibril_usleep(suseconds_t timeout)518 {519 awaiter_t awaiter;520 awaiter_initialize(&awaiter);521 522 awaiter.fid = fibril_get_id();523 524 getuptime(&awaiter.to_event.expires);525 tv_add_diff(&awaiter.to_event.expires, timeout);526 527 futex_lock(&async_futex);528 529 async_insert_timeout(&awaiter);530 531 /* Leave the async_futex locked when entering this function */532 fibril_switch(FIBRIL_FROM_BLOCKED);533 futex_unlock(&async_futex);534 }535 536 /** Delay execution for the specified number of seconds537 *538 * @param sec Number of seconds to sleep539 */540 void fibril_sleep(unsigned int sec)541 {542 /*543 * Sleep in 1000 second steps to support544 * full argument range545 */546 547 while (sec > 0) {548 unsigned int period = (sec > 1000) ? 1000 : sec;549 550 fibril_usleep(period * 1000000);551 sec -= period;552 }553 402 } 554 403 … … 716 565 717 566 msg->dataptr = &result; 718 msg->wdata.active = true;719 567 720 568 errno_t rc = ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO,
Note:
See TracChangeset
for help on using the changeset viewer.