Changeset c042bdd in mainline for libc/generic/async.c
- Timestamp:
- 2006-05-28T23:41:42Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5bd03eb
- Parents:
- 2d1fde3b
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libc/generic/async.c
r2d1fde3b rc042bdd 91 91 #include <assert.h> 92 92 #include <errno.h> 93 #include <time.h> 94 #include <arch/barrier.h> 93 95 94 96 static atomic_t async_futex = FUTEX_INITIALIZER; 95 97 static hash_table_t conn_hash_table; 98 static LIST_INITIALIZE(timeout_list); 96 99 97 100 typedef struct { … … 101 104 ipc_call_t *dataptr; /**< Pointer where the answer data 102 105 * should be stored */ 106 struct timeval expires; /**< Expiration time for waiting thread */ 107 int has_timeout; /**< If true, this struct is in timeout list */ 108 link_t link; 109 103 110 ipcarg_t retval; 104 111 } amsg_t; … … 123 130 124 131 __thread connection_t *PS_connection; 132 133 /** Add microseconds to give timeval */ 134 static void tv_add(struct timeval *tv, suseconds_t usecs) 135 { 136 tv->tv_sec += usecs / 1000000; 137 tv->tv_usec += usecs % 1000000; 138 if (tv->tv_usec > 1000000) { 139 tv->tv_sec++; 140 tv->tv_usec -= 1000000; 141 } 142 } 143 144 /** Subtract 2 timevals, return microseconds difference */ 145 static suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2) 146 { 147 suseconds_t result; 148 149 result = tv1->tv_usec - tv2->tv_usec; 150 result += (tv1->tv_sec - tv2->tv_sec) * 1000000; 151 152 return result; 153 } 154 155 /** Compare timeval 156 * 157 * @return 1 if tv1 > tv2, otherwise 0 158 */ 159 static int tv_gt(struct timeval *tv1, struct timeval *tv2) 160 { 161 if (tv1->tv_sec > tv2->tv_sec) 162 return 1; 163 if (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec > tv2->tv_usec) 164 return 1; 165 return 0; 166 } 125 167 126 168 /* Hash table functions */ … … 327 369 } 328 370 371 /** Fire all timeouts that expired */ 372 static void handle_expired_timeouts(void) 373 { 374 struct timeval tv; 375 amsg_t *amsg; 376 link_t *cur; 377 378 gettimeofday(&tv,NULL); 379 futex_down(&async_futex); 380 381 cur = timeout_list.next; 382 while (cur != &timeout_list) { 383 amsg = list_get_instance(cur,amsg_t,link); 384 if (tv_gt(&amsg->expires, &tv)) 385 break; 386 cur = cur->next; 387 list_remove(&amsg->link); 388 amsg->has_timeout = 0; 389 /* Redundant condition? The thread should not 390 * be active when it gets here. 391 */ 392 if (!amsg->active) { 393 amsg->active = 1; 394 psthread_add_ready(amsg->ptid); 395 } 396 } 397 398 futex_up(&async_futex); 399 } 400 329 401 /** Endless loop dispatching incoming calls and answers */ 330 int async_manager( )402 int async_manager(void) 331 403 { 332 404 ipc_call_t call; 333 405 ipc_callid_t callid; 334 406 int timeout; 407 amsg_t *amsg; 408 struct timeval tv; 335 409 336 410 while (1) { … … 341 415 continue; 342 416 } 343 /* 344 if (expires) 345 timeout = .... ; 346 else 347 */ 417 futex_down(&async_futex); 418 if (!list_empty(&timeout_list)) { 419 amsg = list_get_instance(timeout_list.next,amsg_t,link); 420 gettimeofday(&tv,NULL); 421 if (tv_gt(&tv, &amsg->expires)) { 422 handle_expired_timeouts(); 423 continue; 424 } else 425 timeout = tv_sub(&amsg->expires, &tv); 426 } else 348 427 timeout = SYNCH_NO_TIMEOUT; 428 futex_up(&async_futex); 429 349 430 callid = ipc_wait_cycle(&call, timeout, SYNCH_BLOCKING); 350 431 351 432 if (!callid) { 352 // handle_expired_timeouts.......;433 handle_expired_timeouts(); 353 434 continue; 354 435 } … … 418 499 *msg->dataptr = *data; 419 500 420 /* TODO: memory barrier?? */ 501 write_barrier(); 502 /* Remove message from timeout list */ 503 if (msg->has_timeout) 504 list_remove(&msg->link); 421 505 msg->done = 1; 422 506 if (! msg->active) { … … 466 550 msg->ptid = psthread_get_id(); 467 551 msg->active = 0; 552 msg->has_timeout = 0; 468 553 /* Leave locked async_futex when entering this function */ 469 554 psthread_schedule_next_adv(PS_TO_MANAGER); … … 475 560 } 476 561 477 478 /* int async_wait_timeout(aid_t amsgid, ipcarg_t *retval, int timeout) */ 479 /* { */ 480 /* amsg_t *msg = (amsg_t *) amsgid; */ 481 /* connection_t *conn; */ 482 483 /* futex_down(&async_futex); */ 484 /* if (msg->done) { */ 485 /* futex_up(&async_futex); */ 486 /* goto done; */ 487 /* } */ 488 489 /* msg->ptid = psthread_get_id(); */ 490 /* msg->active = 0; */ 491 /* msg->expires = gettime() + timeout; */ 492 /* setup_timeouts_etc...(); */ 493 494 /* /\* Leave locked async_futex when entering this function *\/ */ 495 /* psthread_schedule_next_adv(PS_TO_MANAGER); */ 496 /* /\* futex is up automatically after psthread_schedule_next...*\/ */ 497 498 /* if (!msg->done) */ 499 /* return casy-casy; */ 500 501 /* /\* TODO: When memory barrier in reply_received, we can skip this *\/ */ 502 /* futex_down(&async_futex); */ 503 /* futex_up(&async_futex); */ 504 /* done: */ 505 506 /* if (retval) */ 507 /* *retval = msg->retval; */ 508 /* free(msg); */ 509 /* } */ 510 562 /** Insert sort timeout msg into timeouts list 563 * 564 * Assume async_futex is held 565 */ 566 static void insert_timeout(amsg_t *msg) 567 { 568 link_t *tmp; 569 amsg_t *cur; 570 571 tmp = timeout_list.next; 572 while (tmp != &timeout_list) { 573 cur = list_get_instance(tmp, amsg_t, link); 574 if (tv_gt(&cur->expires, &msg->expires)) 575 break; 576 tmp = tmp->next; 577 } 578 list_append(&msg->link, tmp); 579 } 580 581 /** Wait for a message sent by async framework with timeout 582 * 583 * @param amsgid Message ID to wait for 584 * @param retval Pointer to variable where will be stored retval 585 * of the answered message. If NULL, it is ignored. 586 * @param timeout Timeout in usecs 587 * @return 0 on success, ETIMEOUT if timeout expired 588 * 589 */ 590 int async_wait_timeout(aid_t amsgid, ipcarg_t *retval, suseconds_t timeout) 591 { 592 amsg_t *msg = (amsg_t *) amsgid; 593 connection_t *conn; 594 595 futex_down(&async_futex); 596 if (msg->done) { 597 futex_up(&async_futex); 598 goto done; 599 } 600 601 msg->ptid = psthread_get_id(); 602 msg->active = 0; 603 msg->has_timeout = 1; 604 605 gettimeofday(&msg->expires, NULL); 606 tv_add(&msg->expires, timeout); 607 insert_timeout(msg); 608 609 /* Leave locked async_futex when entering this function */ 610 psthread_schedule_next_adv(PS_TO_MANAGER); 611 /* futex is up automatically after psthread_schedule_next...*/ 612 613 if (!msg->done) 614 return ETIMEOUT; 615 616 done: 617 if (retval) 618 *retval = msg->retval; 619 free(msg); 620 621 return 0; 622 } 623
Note:
See TracChangeset
for help on using the changeset viewer.