Changeset bc1f1c2 in mainline for uspace/lib/libc/generic/async.c
- Timestamp:
- 2007-06-28T00:54:12Z (17 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 12f91130
- Parents:
- b9641ee
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libc/generic/async.c
rb9641ee rbc1f1c2 86 86 * } 87 87 * 88 * TODO: Detaching/joining dead psthreads?89 88 */ 90 89 #include <futex.h> 91 90 #include <async.h> 92 #include < psthread.h>91 #include <fibril.h> 93 92 #include <stdio.h> 94 93 #include <libadt/hash_table.h> … … 105 104 106 105 typedef struct { 107 struct timeval expires; /**< Expiration time for waiting thread */ 108 int inlist; /**< If true, this struct is in timeout list */ 106 /** Expiration time for waiting fibril. */ 107 struct timeval expires; 108 /** If true, this struct is in the timeout list. */ 109 int inlist; 109 110 link_t link; 110 111 111 pstid_t ptid; /**< Thread waiting for this message */ 112 int active; /**< If this thread is currently active */ 113 int timedout; /**< If true, we timed out */ 112 /** Fibril waiting for this message. */ 113 fid_t fid; 114 /** If this fibril is currently active. */ 115 int active; 116 /** If true, we timed out. */ 117 int timedout; 114 118 } awaiter_t; 115 119 … … 119 123 int done; /**< If reply was received */ 120 124 ipc_call_t *dataptr; /**< Pointer where the answer data 121 125 * is stored */ 122 126 ipcarg_t retval; 123 127 } amsg_t; … … 132 136 awaiter_t wdata; 133 137 134 link_t link; /**< Hash table link */138 link_t link; /**< Hash table link. */ 135 139 ipcarg_t in_phone_hash; /**< Incoming phone hash. */ 136 link_t msg_queue; /**< Messages that should be delivered to this thread */ 140 link_t msg_queue; /**< Messages that should be delivered 141 * to this fibril. */ 137 142 /* Structures for connection opening packet */ 138 143 ipc_callid_t callid; 139 144 ipc_call_t call; 140 ipc_callid_t close_callid; /* Identification of closing packet */141 void (*c thread)(ipc_callid_t,ipc_call_t *);145 ipc_callid_t close_callid; /* Identification of closing packet. */ 146 void (*cfibril)(ipc_callid_t, ipc_call_t *); 142 147 } connection_t; 143 148 144 /** Identifier of incoming connection handled by current thread*/145 __thread connection_t * PS_connection;149 /** Identifier of the incoming connection handled by the current fibril. */ 150 __thread connection_t *FIBRIL_connection; 146 151 /** If true, it is forbidden to use async_req functions and 147 152 * all preemption is disabled */ … … 286 291 } 287 292 conn->wdata.active = 1; 288 psthread_add_ready(conn->wdata.ptid);293 fibril_add_ready(conn->wdata.fid); 289 294 } 290 295 … … 301 306 connection_t *conn; 302 307 303 assert( PS_connection);304 /* GCC 4.1.0 coughs on PS_connection-> dereference,308 assert(FIBRIL_connection); 309 /* GCC 4.1.0 coughs on FIBRIL_connection-> dereference, 305 310 * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot. 306 311 * I would never expect to find so many errors in 307 312 * compiler *($&$(*&$ 308 313 */ 309 conn = PS_connection;314 conn = FIBRIL_connection; 310 315 311 316 futex_down(&async_futex); … … 323 328 324 329 conn->wdata.active = 0; 325 psthread_schedule_next_adv(PS_TO_MANAGER);330 fibril_schedule_next_adv(FIBRIL_TO_MANAGER); 326 331 /* Futex is up after getting back from async_manager 327 332 * get it again */ 328 333 futex_down(&async_futex); 329 if (usecs && conn->wdata.timedout && \334 if (usecs && conn->wdata.timedout && 330 335 list_empty(&conn->msg_queue)) { 331 336 /* If we timed out-> exit */ … … 365 370 * @param arg Connection structure pointer 366 371 */ 367 static int connection_ thread(void *arg)372 static int connection_fibril(void *arg) 368 373 { 369 374 unsigned long key; … … 372 377 373 378 /* Setup thread local connection pointer */ 374 PS_connection = (connection_t *)arg; 375 PS_connection->cthread(PS_connection->callid, &PS_connection->call); 379 FIBRIL_connection = (connection_t *) arg; 380 FIBRIL_connection->cfibril(FIBRIL_connection->callid, 381 &FIBRIL_connection->call); 376 382 377 383 /* Remove myself from connection hash table */ 378 384 futex_down(&async_futex); 379 key = PS_connection->in_phone_hash;385 key = FIBRIL_connection->in_phone_hash; 380 386 hash_table_remove(&conn_hash_table, &key, 1); 381 387 futex_up(&async_futex); 382 388 383 389 /* Answer all remaining messages with ehangup */ 384 while (!list_empty(&PS_connection->msg_queue)) { 385 msg = list_get_instance(PS_connection->msg_queue.next, msg_t, link); 390 while (!list_empty(&FIBRIL_connection->msg_queue)) { 391 msg = list_get_instance(FIBRIL_connection->msg_queue.next, 392 msg_t, link); 386 393 list_remove(&msg->link); 387 if (msg->callid == PS_connection->close_callid)394 if (msg->callid == FIBRIL_connection->close_callid) 388 395 close_answered = 1; 389 396 ipc_answer_fast(msg->callid, EHANGUP, 0, 0); 390 397 free(msg); 391 398 } 392 if ( PS_connection->close_callid)393 ipc_answer_fast( PS_connection->close_callid, 0, 0, 0);399 if (FIBRIL_connection->close_callid) 400 ipc_answer_fast(FIBRIL_connection->close_callid, 0, 0, 0); 394 401 395 402 return 0; … … 406 413 * @param callid Callid of the IPC_M_CONNECT_ME_TO packet 407 414 * @param call Call data of the opening packet 408 * @param c thread Threadfunction that should be called upon415 * @param cfibril Fibril function that should be called upon 409 416 * opening the connection 410 * @return New thread id 411 */ 412 pstid_t async_new_connection(ipcarg_t in_phone_hash,ipc_callid_t callid, ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *)) 417 * @return New fibril id. 418 */ 419 fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid, 420 ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *)) 413 421 { 414 422 connection_t *conn; … … 427 435 conn->call = *call; 428 436 conn->wdata.active = 1; /* We will activate it asap */ 429 conn->c thread = cthread;430 431 conn->wdata. ptid = psthread_create(connection_thread, conn);432 if (!conn->wdata. ptid) {437 conn->cfibril = cfibril; 438 439 conn->wdata.fid = fibril_create(connection_fibril, conn); 440 if (!conn->wdata.fid) { 433 441 free(conn); 434 442 ipc_answer_fast(callid, ENOMEM, 0, 0); … … 441 449 futex_up(&async_futex); 442 450 443 psthread_add_ready(conn->wdata.ptid);444 445 return conn->wdata. ptid;451 fibril_add_ready(conn->wdata.fid); 452 453 return conn->wdata.fid; 446 454 } 447 455 … … 460 468 case IPC_M_CONNECT_ME_TO: 461 469 /* Open new connection with thread etc. */ 462 async_new_connection(IPC_GET_ARG3(*call), callid, call, client_connection); 470 async_new_connection(IPC_GET_ARG3(*call), callid, call, 471 client_connection); 463 472 return; 464 473 } … … 486 495 cur = timeout_list.next; 487 496 while (cur != &timeout_list) { 488 waiter = list_get_instance(cur, awaiter_t,link);497 waiter = list_get_instance(cur, awaiter_t, link); 489 498 if (tv_gt(&waiter->expires, &tv)) 490 499 break; … … 498 507 if (!waiter->active) { 499 508 waiter->active = 1; 500 psthread_add_ready(waiter->ptid);509 fibril_add_ready(waiter->fid); 501 510 } 502 511 } … … 515 524 516 525 while (1) { 517 if ( psthread_schedule_next_adv(PS_FROM_MANAGER)) {526 if (fibril_schedule_next_adv(FIBRIL_FROM_MANAGER)) { 518 527 futex_up(&async_futex); 519 528 /* async_futex is always held … … 524 533 futex_down(&async_futex); 525 534 if (!list_empty(&timeout_list)) { 526 waiter = list_get_instance(timeout_list.next,awaiter_t,link); 527 gettimeofday(&tv,NULL); 535 waiter = list_get_instance(timeout_list.next, awaiter_t, 536 link); 537 gettimeofday(&tv, NULL); 528 538 if (tv_gteq(&tv, &waiter->expires)) { 529 539 futex_up(&async_futex); … … 573 583 void async_create_manager(void) 574 584 { 575 pstid_t ptid;576 577 ptid = psthread_create(async_manager_thread, NULL);578 psthread_add_manager(ptid);585 fid_t fid; 586 587 fid = fibril_create(async_manager_thread, NULL); 588 fibril_add_manager(fid); 579 589 } 580 590 … … 582 592 void async_destroy_manager(void) 583 593 { 584 psthread_remove_manager();594 fibril_remove_manager(); 585 595 } 586 596 … … 588 598 int _async_init(void) 589 599 { 590 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, &conn_hash_table_ops)) { 600 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, 601 &conn_hash_table_ops)) { 591 602 printf("%s: cannot create hash table\n", "async"); 592 603 return ENOMEM; … … 598 609 /** IPC handler for messages in async framework 599 610 * 600 * Notify th read thatis waiting for this message, that it arrived611 * Notify the fibril which is waiting for this message, that it arrived 601 612 */ 602 613 static void reply_received(void *private, int retval, … … 621 632 if (! msg->wdata.active) { 622 633 msg->wdata.active = 1; 623 psthread_add_ready(msg->wdata.ptid);634 fibril_add_ready(msg->wdata.fid); 624 635 } 625 636 futex_up(&async_futex); … … 633 644 aid_t async_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, 634 645 ipc_call_t *dataptr) 646 { 647 amsg_t *msg; 648 649 if (in_interrupt_handler) { 650 printf("Cannot send asynchronous request in interrupt " 651 "handler.\n"); 652 _exit(1); 653 } 654 655 msg = malloc(sizeof(*msg)); 656 msg->done = 0; 657 msg->dataptr = dataptr; 658 659 msg->wdata.active = 1; /* We may sleep in next method, but it 660 * will use it's own mechanism */ 661 ipc_call_async_2(phoneid, method, arg1, arg2, msg, reply_received, 1); 662 663 return (aid_t) msg; 664 } 665 666 /** Send message and return id of the sent message 667 * 668 * The return value can be used as input for async_wait() to wait 669 * for completion. 670 */ 671 aid_t async_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, 672 ipcarg_t arg3, ipc_call_t *dataptr) 635 673 { 636 674 amsg_t *msg; … … 647 685 msg->wdata.active = 1; /* We may sleep in next method, but it 648 686 * will use it's own mechanism */ 649 ipc_call_async_2(phoneid,method,arg1,arg2,msg,reply_received,1); 650 651 return (aid_t) msg; 652 } 653 654 /** Send message and return id of the sent message 655 * 656 * The return value can be used as input for async_wait() to wait 657 * for completion. 658 */ 659 aid_t async_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, 660 ipcarg_t arg3, ipc_call_t *dataptr) 661 { 662 amsg_t *msg; 663 664 if (in_interrupt_handler) { 665 printf("Cannot send asynchronous request in interrupt handler.\n"); 666 _exit(1); 667 } 668 669 msg = malloc(sizeof(*msg)); 670 msg->done = 0; 671 msg->dataptr = dataptr; 672 673 msg->wdata.active = 1; /* We may sleep in next method, but it 674 * will use it's own mechanism */ 675 ipc_call_async_3(phoneid,method,arg1,arg2,arg3, msg,reply_received,1); 687 ipc_call_async_3(phoneid, method, arg1, arg2, arg3, msg, reply_received, 688 1); 676 689 677 690 return (aid_t) msg; … … 695 708 } 696 709 697 msg->wdata. ptid = psthread_get_id();710 msg->wdata.fid = fibril_get_id(); 698 711 msg->wdata.active = 0; 699 712 msg->wdata.inlist = 0; 700 713 /* Leave locked async_futex when entering this function */ 701 psthread_schedule_next_adv(PS_TO_MANAGER);702 /* futex is up automatically after psthread_schedule_next...*/714 fibril_schedule_next_adv(FIBRIL_TO_MANAGER); 715 /* futex is up automatically after fibril_schedule_next...*/ 703 716 done: 704 717 if (retval) … … 733 746 tv_add(&msg->wdata.expires, timeout); 734 747 735 msg->wdata. ptid = psthread_get_id();748 msg->wdata.fid = fibril_get_id(); 736 749 msg->wdata.active = 0; 737 750 insert_timeout(&msg->wdata); 738 751 739 752 /* Leave locked async_futex when entering this function */ 740 psthread_schedule_next_adv(PS_TO_MANAGER);741 /* futex is up automatically after psthread_schedule_next...*/753 fibril_schedule_next_adv(FIBRIL_TO_MANAGER); 754 /* futex is up automatically after fibril_schedule_next...*/ 742 755 743 756 if (!msg->done) … … 769 782 return; 770 783 771 msg->wdata. ptid = psthread_get_id();784 msg->wdata.fid = fibril_get_id(); 772 785 msg->wdata.active = 0; 773 786 … … 778 791 insert_timeout(&msg->wdata); 779 792 /* Leave locked async_futex when entering this function */ 780 psthread_schedule_next_adv(PS_TO_MANAGER);781 /* futex is up automatically after psthread_schedule_next...*/793 fibril_schedule_next_adv(FIBRIL_TO_MANAGER); 794 /* futex is up automatically after fibril_schedule_next...*/ 782 795 free(msg); 783 796 } … … 800 813 ipcarg_t arg2, ipcarg_t arg3) 801 814 { 802 ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, !in_interrupt_handler); 815 ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, 816 !in_interrupt_handler); 803 817 } 804 818 805 819 void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2) 806 820 { 807 ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, !in_interrupt_handler); 821 ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, 822 !in_interrupt_handler); 808 823 } 809 824
Note:
See TracChangeset
for help on using the changeset viewer.