Changes in uspace/lib/c/generic/async.c [c0699467:649f087] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
rc0699467 r649f087 112 112 #include <mem.h> 113 113 #include <stdlib.h> 114 #include <macros.h> 114 115 #include "private/async.h" 115 116 … … 138 139 link_t link; 139 140 140 sysarg_t in_task_hash;141 task_id_t in_task_id; 141 142 atomic_t refcnt; 142 143 void *data; … … 150 151 link_t link; 151 152 152 /** Incoming client task hash. */153 sysarg_t in_task_hash;153 /** Incoming client task ID. */ 154 task_id_t in_task_id; 154 155 155 156 /** Incoming phone hash. */ … … 203 204 } 204 205 205 void *async_get_client_data(void)206 {207 assert(fibril_connection);208 return fibril_connection->client->data;209 }210 211 206 /** Default fibril function that gets called to handle new connection. 212 207 * … … 289 284 { 290 285 assert(key); 286 assert(keys == 2); 291 287 assert(item); 292 288 293 289 client_t *client = hash_table_get_instance(item, client_t, link); 294 return (key[0] == client->in_task_hash); 290 return (key[0] == LOWER32(client->in_task_id) && 291 (key[1] == UPPER32(client->in_task_id))); 295 292 } 296 293 … … 580 577 } 581 578 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 } else 621 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 582 666 /** Wrapper for client connection fibril. 583 667 * … … 598 682 */ 599 683 fibril_connection = (connection_t *) arg; 600 601 futex_down(&async_futex);602 684 603 685 /* … … 606 688 * hash in a new tracking structure. 607 689 */ 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 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 634 697 fibril_connection->client = client; 635 698 … … 643 706 * Remove the reference for this client task connection. 644 707 */ 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 } 708 async_client_put(client); 663 709 664 710 /* … … 666 712 */ 667 713 futex_down(&async_futex); 668 key = fibril_connection->in_phone_hash;714 unsigned long key = fibril_connection->in_phone_hash; 669 715 hash_table_remove(&conn_hash_table, &key, 1); 670 716 futex_up(&async_futex); … … 700 746 * particular fibrils. 701 747 * 702 * @param in_task_ hashIdentification of the incoming connection.748 * @param in_task_id Identification of the incoming connection. 703 749 * @param in_phone_hash Identification of the incoming connection. 704 750 * @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. … … 714 760 * 715 761 */ 716 fid_t async_new_connection( sysarg_t in_task_hash, sysarg_t in_phone_hash,762 fid_t async_new_connection(task_id_t in_task_id, sysarg_t in_phone_hash, 717 763 ipc_callid_t callid, ipc_call_t *call, 718 764 async_client_conn_t cfibril, void *carg) … … 726 772 } 727 773 728 conn->in_task_ hash = in_task_hash;774 conn->in_task_id = in_task_id; 729 775 conn->in_phone_hash = in_phone_hash; 730 776 list_initialize(&conn->msg_queue); … … 785 831 case IPC_M_CONNECT_ME_TO: 786 832 /* Open new connection with fibril, etc. */ 787 async_new_connection(call->in_task_ hash, IPC_GET_ARG5(*call),833 async_new_connection(call->in_task_id, IPC_GET_ARG5(*call), 788 834 callid, call, client_connection, NULL); 789 835 return; … … 933 979 { 934 980 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 935 1, &client_hash_table_ops))981 2, &client_hash_table_ops)) 936 982 abort(); 937 983 … … 1426 1472 return ENOENT; 1427 1473 1428 sysarg_t task_hash; 1474 task_id_t task_id; 1475 sysarg_t task_id_lo; 1476 sysarg_t task_id_hi; 1429 1477 sysarg_t phone_hash; 1430 1478 int rc = async_req_3_5(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 1431 NULL, NULL, NULL, &task_hash, &phone_hash);1479 NULL, NULL, &task_id_lo, &task_id_hi, &phone_hash); 1432 1480 if (rc != EOK) 1433 1481 return rc; 1482 1483 task_id = (task_id_t) MERGE_LOUP32(task_id_lo, task_id_hi); 1434 1484 1435 1485 if (client_receiver != NULL) 1436 async_new_connection(task_ hash, phone_hash, 0, NULL,1486 async_new_connection(task_id, phone_hash, 0, NULL, 1437 1487 client_receiver, carg); 1438 1488 … … 2429 2479 } 2430 2480 2481 int async_state_change_start(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2, 2482 sysarg_t arg3, async_exch_t *other_exch) 2483 { 2484 return async_req_5_0(exch, IPC_M_STATE_CHANGE_AUTHORIZE, 2485 arg1, arg2, arg3, 0, other_exch->phone); 2486 } 2487 2488 bool async_state_change_receive(ipc_callid_t *callid, sysarg_t *arg1, 2489 sysarg_t *arg2, sysarg_t *arg3) 2490 { 2491 assert(callid); 2492 2493 ipc_call_t call; 2494 *callid = async_get_call(&call); 2495 2496 if (IPC_GET_IMETHOD(call) != IPC_M_STATE_CHANGE_AUTHORIZE) 2497 return false; 2498 2499 if (arg1) 2500 *arg1 = IPC_GET_ARG1(call); 2501 if (arg2) 2502 *arg2 = IPC_GET_ARG2(call); 2503 if (arg3) 2504 *arg3 = IPC_GET_ARG3(call); 2505 2506 return true; 2507 } 2508 2509 int async_state_change_finalize(ipc_callid_t callid, async_exch_t *other_exch) 2510 { 2511 return ipc_answer_1(callid, EOK, other_exch->phone); 2512 } 2513 2431 2514 /** @} 2432 2515 */
Note:
See TracChangeset
for help on using the changeset viewer.