Changes in uspace/lib/c/generic/async.c [93ad49a8:3815efb] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
r93ad49a8 r3815efb 98 98 #include <ipc/ipc.h> 99 99 #include <async.h> 100 #include "private/async.h"101 100 #undef LIBC_ASYNC_C_ 102 101 … … 108 107 #include <errno.h> 109 108 #include <sys/time.h> 110 #include < libarch/barrier.h>109 #include <arch/barrier.h> 111 110 #include <bool.h> 112 111 #include <malloc.h> 113 112 #include <mem.h> 114 113 #include <stdlib.h> 115 #include <macros.h>114 #include "private/async.h" 116 115 117 116 #define CLIENT_HASH_TABLE_BUCKETS 32 … … 139 138 link_t link; 140 139 141 task_id_t in_task_id;140 sysarg_t in_task_hash; 142 141 atomic_t refcnt; 143 142 void *data; … … 151 150 link_t link; 152 151 153 /** Incoming client task ID. */154 task_id_t in_task_id;152 /** Incoming client task hash. */ 153 sysarg_t in_task_hash; 155 154 156 155 /** Incoming phone hash. */ … … 204 203 } 205 204 205 void *async_get_client_data(void) 206 { 207 assert(fibril_connection); 208 return fibril_connection->client->data; 209 } 210 206 211 /** Default fibril function that gets called to handle new connection. 207 212 * … … 284 289 { 285 290 assert(key); 286 assert(keys == 2);287 291 assert(item); 288 292 289 293 client_t *client = hash_table_get_instance(item, client_t, link); 290 return (key[0] == LOWER32(client->in_task_id) && 291 (key[1] == UPPER32(client->in_task_id))); 294 return (key[0] == client->in_task_hash); 292 295 } 293 296 … … 577 580 } 578 581 579 static client_t *async_client_get(task_id_t client_id, bool create)580 {581 unsigned long key[2] = {582 LOWER32(client_id),583 UPPER32(client_id),584 };585 client_t *client = NULL;586 587 futex_down(&async_futex);588 link_t *lnk = hash_table_find(&client_hash_table, key);589 if (lnk) {590 client = hash_table_get_instance(lnk, client_t, link);591 atomic_inc(&client->refcnt);592 } else if (create) {593 client = malloc(sizeof(client_t));594 if (client) {595 client->in_task_id = client_id;596 client->data = async_client_data_create();597 598 atomic_set(&client->refcnt, 1);599 hash_table_insert(&client_hash_table, key, &client->link);600 }601 }602 603 futex_up(&async_futex);604 return client;605 }606 607 static void async_client_put(client_t *client)608 {609 bool destroy;610 unsigned long key[2] = {611 LOWER32(client->in_task_id),612 UPPER32(client->in_task_id)613 };614 615 futex_down(&async_futex);616 617 if (atomic_predec(&client->refcnt) == 0) {618 hash_table_remove(&client_hash_table, key, 2);619 destroy = true;620 } else621 destroy = false;622 623 futex_up(&async_futex);624 625 if (destroy) {626 if (client->data)627 async_client_data_destroy(client->data);628 629 free(client);630 }631 }632 633 void *async_get_client_data(void)634 {635 assert(fibril_connection);636 return fibril_connection->client->data;637 }638 639 void *async_get_client_data_by_id(task_id_t client_id)640 {641 client_t *client = async_client_get(client_id, false);642 if (!client)643 return NULL;644 if (!client->data) {645 async_client_put(client);646 return NULL;647 }648 649 return client->data;650 }651 652 void async_put_client_data_by_id(task_id_t client_id)653 {654 client_t *client = async_client_get(client_id, false);655 656 assert(client);657 assert(client->data);658 659 /* Drop the reference we got in async_get_client_data_by_hash(). */660 async_client_put(client);661 662 /* Drop our own reference we got at the beginning of this function. */663 async_client_put(client);664 }665 666 582 /** Wrapper for client connection fibril. 667 583 * … … 682 598 */ 683 599 fibril_connection = (connection_t *) arg; 600 601 futex_down(&async_futex); 684 602 685 603 /* … … 688 606 * hash in a new tracking structure. 689 607 */ 690 691 client_t *client = async_client_get(fibril_connection->in_task_id, true); 692 if (!client) { 693 ipc_answer_0(fibril_connection->callid, ENOMEM); 694 return 0; 695 } 696 608 609 unsigned long key = fibril_connection->in_task_hash; 610 link_t *lnk = hash_table_find(&client_hash_table, &key); 611 612 client_t *client; 613 614 if (lnk) { 615 client = hash_table_get_instance(lnk, client_t, link); 616 atomic_inc(&client->refcnt); 617 } else { 618 client = malloc(sizeof(client_t)); 619 if (!client) { 620 ipc_answer_0(fibril_connection->callid, ENOMEM); 621 futex_up(&async_futex); 622 return 0; 623 } 624 625 client->in_task_hash = fibril_connection->in_task_hash; 626 client->data = async_client_data_create(); 627 628 atomic_set(&client->refcnt, 1); 629 hash_table_insert(&client_hash_table, &key, &client->link); 630 } 631 632 futex_up(&async_futex); 633 697 634 fibril_connection->client = client; 698 635 … … 706 643 * Remove the reference for this client task connection. 707 644 */ 708 async_client_put(client); 645 bool destroy; 646 647 futex_down(&async_futex); 648 649 if (atomic_predec(&client->refcnt) == 0) { 650 hash_table_remove(&client_hash_table, &key, 1); 651 destroy = true; 652 } else 653 destroy = false; 654 655 futex_up(&async_futex); 656 657 if (destroy) { 658 if (client->data) 659 async_client_data_destroy(client->data); 660 661 free(client); 662 } 709 663 710 664 /* … … 712 666 */ 713 667 futex_down(&async_futex); 714 unsigned longkey = fibril_connection->in_phone_hash;668 key = fibril_connection->in_phone_hash; 715 669 hash_table_remove(&conn_hash_table, &key, 1); 716 670 futex_up(&async_futex); … … 746 700 * particular fibrils. 747 701 * 748 * @param in_task_ idIdentification of the incoming connection.702 * @param in_task_hash Identification of the incoming connection. 749 703 * @param in_phone_hash Identification of the incoming connection. 750 704 * @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. … … 760 714 * 761 715 */ 762 fid_t async_new_connection( task_id_t in_task_id, sysarg_t in_phone_hash,716 fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash, 763 717 ipc_callid_t callid, ipc_call_t *call, 764 718 async_client_conn_t cfibril, void *carg) … … 772 726 } 773 727 774 conn->in_task_ id = in_task_id;728 conn->in_task_hash = in_task_hash; 775 729 conn->in_phone_hash = in_phone_hash; 776 730 list_initialize(&conn->msg_queue); … … 831 785 case IPC_M_CONNECT_ME_TO: 832 786 /* Open new connection with fibril, etc. */ 833 async_new_connection(call->in_task_ id, IPC_GET_ARG5(*call),787 async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call), 834 788 callid, call, client_connection, NULL); 835 789 return; … … 979 933 { 980 934 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 981 2, &client_hash_table_ops))935 1, &client_hash_table_ops)) 982 936 abort(); 983 937 … … 995 949 session_ns->arg2 = 0; 996 950 session_ns->arg3 = 0; 997 998 fibril_mutex_initialize(&session_ns->remote_state_mtx);999 session_ns->remote_state_data = NULL;1000 951 1001 952 list_initialize(&session_ns->exch_list); … … 1475 1426 return ENOENT; 1476 1427 1428 sysarg_t task_hash; 1477 1429 sysarg_t phone_hash; 1478 sysarg_t rc; 1479 1480 aid_t req; 1481 ipc_call_t answer; 1482 req = async_send_3(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 1483 &answer); 1484 async_wait_for(req, &rc); 1430 int rc = async_req_3_5(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 1431 NULL, NULL, NULL, &task_hash, &phone_hash); 1485 1432 if (rc != EOK) 1486 return (int) rc; 1487 1488 phone_hash = IPC_GET_ARG5(answer); 1489 1433 return rc; 1434 1490 1435 if (client_receiver != NULL) 1491 async_new_connection( answer.in_task_id, phone_hash, 0, NULL,1436 async_new_connection(task_hash, phone_hash, 0, NULL, 1492 1437 client_receiver, carg); 1493 1438 … … 1564 1509 sess->arg3 = 0; 1565 1510 1566 fibril_mutex_initialize(&sess->remote_state_mtx);1567 sess->remote_state_data = NULL;1568 1569 1511 list_initialize(&sess->exch_list); 1570 1512 fibril_mutex_initialize(&sess->mutex); … … 1648 1590 sess->arg3 = arg3; 1649 1591 1650 fibril_mutex_initialize(&sess->remote_state_mtx);1651 sess->remote_state_data = NULL;1652 1653 1592 list_initialize(&sess->exch_list); 1654 1593 fibril_mutex_initialize(&sess->mutex); … … 1656 1595 1657 1596 return sess; 1658 }1659 1660 /** Set arguments for new connections.1661 *1662 * FIXME This is an ugly hack to work around the problem that parallel1663 * exchanges are implemented using parallel connections. When we create1664 * a callback session, the framework does not know arguments for the new1665 * connections.1666 *1667 * The proper solution seems to be to implement parallel exchanges using1668 * tagging.1669 */1670 void async_sess_args_set(async_sess_t *sess, sysarg_t arg1, sysarg_t arg2,1671 sysarg_t arg3)1672 {1673 sess->arg1 = arg1;1674 sess->arg2 = arg2;1675 sess->arg3 = arg3;1676 1597 } 1677 1598 … … 1719 1640 sess->arg3 = arg3; 1720 1641 1721 fibril_mutex_initialize(&sess->remote_state_mtx);1722 sess->remote_state_data = NULL;1723 1724 1642 list_initialize(&sess->exch_list); 1725 1643 fibril_mutex_initialize(&sess->mutex); … … 1752 1670 sess->arg2 = 0; 1753 1671 sess->arg3 = 0; 1754 1755 fibril_mutex_initialize(&sess->remote_state_mtx);1756 sess->remote_state_data = NULL;1757 1672 1758 1673 list_initialize(&sess->exch_list); … … 2419 2334 sess->arg3 = 0; 2420 2335 2421 fibril_mutex_initialize(&sess->remote_state_mtx);2422 sess->remote_state_data = NULL;2423 2424 2336 list_initialize(&sess->exch_list); 2425 2337 fibril_mutex_initialize(&sess->mutex); … … 2468 2380 sess->arg3 = 0; 2469 2381 2470 fibril_mutex_initialize(&sess->remote_state_mtx);2471 sess->remote_state_data = NULL;2472 2473 2382 list_initialize(&sess->exch_list); 2474 2383 fibril_mutex_initialize(&sess->mutex); … … 2513 2422 sess->arg3 = 0; 2514 2423 2515 fibril_mutex_initialize(&sess->remote_state_mtx);2516 sess->remote_state_data = NULL;2517 2518 2424 list_initialize(&sess->exch_list); 2519 2425 fibril_mutex_initialize(&sess->mutex); … … 2523 2429 } 2524 2430 2525 int async_state_change_start(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,2526 sysarg_t arg3, async_exch_t *other_exch)2527 {2528 return async_req_5_0(exch, IPC_M_STATE_CHANGE_AUTHORIZE,2529 arg1, arg2, arg3, 0, other_exch->phone);2530 }2531 2532 bool async_state_change_receive(ipc_callid_t *callid, sysarg_t *arg1,2533 sysarg_t *arg2, sysarg_t *arg3)2534 {2535 assert(callid);2536 2537 ipc_call_t call;2538 *callid = async_get_call(&call);2539 2540 if (IPC_GET_IMETHOD(call) != IPC_M_STATE_CHANGE_AUTHORIZE)2541 return false;2542 2543 if (arg1)2544 *arg1 = IPC_GET_ARG1(call);2545 if (arg2)2546 *arg2 = IPC_GET_ARG2(call);2547 if (arg3)2548 *arg3 = IPC_GET_ARG3(call);2549 2550 return true;2551 }2552 2553 int async_state_change_finalize(ipc_callid_t callid, async_exch_t *other_exch)2554 {2555 return ipc_answer_1(callid, EOK, other_exch->phone);2556 }2557 2558 /** Lock and get session remote state2559 *2560 * Lock and get the local replica of the remote state2561 * in stateful sessions. The call should be paired2562 * with async_remote_state_release*().2563 *2564 * @param[in] sess Stateful session.2565 *2566 * @return Local replica of the remote state.2567 *2568 */2569 void *async_remote_state_acquire(async_sess_t *sess)2570 {2571 fibril_mutex_lock(&sess->remote_state_mtx);2572 return sess->remote_state_data;2573 }2574 2575 /** Update the session remote state2576 *2577 * Update the local replica of the remote state2578 * in stateful sessions. The remote state must2579 * be already locked.2580 *2581 * @param[in] sess Stateful session.2582 * @param[in] state New local replica of the remote state.2583 *2584 */2585 void async_remote_state_update(async_sess_t *sess, void *state)2586 {2587 assert(fibril_mutex_is_locked(&sess->remote_state_mtx));2588 sess->remote_state_data = state;2589 }2590 2591 /** Release the session remote state2592 *2593 * Unlock the local replica of the remote state2594 * in stateful sessions.2595 *2596 * @param[in] sess Stateful session.2597 *2598 */2599 void async_remote_state_release(async_sess_t *sess)2600 {2601 assert(fibril_mutex_is_locked(&sess->remote_state_mtx));2602 2603 fibril_mutex_unlock(&sess->remote_state_mtx);2604 }2605 2606 /** Release the session remote state and end an exchange2607 *2608 * Unlock the local replica of the remote state2609 * in stateful sessions. This is convenience function2610 * which gets the session pointer from the exchange2611 * and also ends the exchange.2612 *2613 * @param[in] exch Stateful session's exchange.2614 *2615 */2616 void async_remote_state_release_exchange(async_exch_t *exch)2617 {2618 if (exch == NULL)2619 return;2620 2621 async_sess_t *sess = exch->sess;2622 assert(fibril_mutex_is_locked(&sess->remote_state_mtx));2623 2624 async_exchange_end(exch);2625 fibril_mutex_unlock(&sess->remote_state_mtx);2626 }2627 2628 2431 /** @} 2629 2432 */
Note:
See TracChangeset
for help on using the changeset viewer.