Changes in uspace/lib/c/generic/async.c [c1c0184:23882034] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
rc1c0184 r23882034 134 134 135 135 typedef struct { 136 sysarg_t in_task_hash; 137 link_t link; 138 int refcnt; 139 void *data; 140 } client_t; 141 142 typedef struct { 136 143 awaiter_t wdata; 137 144 … … 139 146 link_t link; 140 147 148 /** Incoming client task hash. */ 149 sysarg_t in_task_hash; 141 150 /** Incoming phone hash. */ 142 151 sysarg_t in_phone_hash; 143 152 153 /** Link to the client tracking structure. */ 154 client_t *client; 155 144 156 /** Messages that should be delivered to this fibril. */ 145 157 link_t msg_queue; … … 160 172 fibril_local connection_t *FIBRIL_connection; 161 173 174 static void *default_client_data_constructor(void) 175 { 176 return NULL; 177 } 178 179 static void default_client_data_destructor(void *data) 180 { 181 } 182 183 static async_client_data_ctor_t async_client_data_create = 184 default_client_data_constructor; 185 static async_client_data_dtor_t async_client_data_destroy = 186 default_client_data_destructor; 187 188 void async_set_client_data_constructor(async_client_data_ctor_t ctor) 189 { 190 async_client_data_create = ctor; 191 } 192 193 void async_set_client_data_destructor(async_client_data_dtor_t dtor) 194 { 195 async_client_data_destroy = dtor; 196 } 197 198 void *async_client_data_get(void) 199 { 200 assert(FIBRIL_connection); 201 202 return FIBRIL_connection->client->data; 203 } 204 162 205 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); 163 206 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); … … 174 217 static async_client_conn_t interrupt_received = default_interrupt_received; 175 218 219 static hash_table_t client_hash_table; 176 220 static hash_table_t conn_hash_table; 177 221 static LIST_INITIALIZE(timeout_list); 178 222 179 #define CONN_HASH_TABLE_CHAINS 32 223 #define CLIENT_HASH_TABLE_BUCKETS 32 224 #define CONN_HASH_TABLE_BUCKETS 32 225 226 static hash_index_t client_hash(unsigned long *key) 227 { 228 assert(key); 229 return (((*key) >> 4) % CLIENT_HASH_TABLE_BUCKETS); 230 } 231 232 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item) 233 { 234 client_t *cl = hash_table_get_instance(item, client_t, link); 235 return (key[0] == cl->in_task_hash); 236 } 237 238 static void client_remove(link_t *item) 239 { 240 } 241 242 /** Operations for the client hash table. */ 243 static hash_table_operations_t client_hash_table_ops = { 244 .hash = client_hash, 245 .compare = client_compare, 246 .remove_callback = client_remove 247 }; 180 248 181 249 /** Compute hash into the connection hash table based on the source phone hash. … … 189 257 { 190 258 assert(key); 191 return (((*key) >> 4) % CONN_HASH_TABLE_ CHAINS);259 return (((*key) >> 4) % CONN_HASH_TABLE_BUCKETS); 192 260 } 193 261 … … 480 548 static int connection_fibril(void *arg) 481 549 { 550 unsigned long key; 551 client_t *cl; 552 link_t *lnk; 553 bool destroy = false; 554 482 555 /* 483 * Setup fibril-local connection pointer and call client_connection(). 484 * 556 * Setup fibril-local connection pointer. 485 557 */ 486 558 FIBRIL_connection = (connection_t *) arg; 559 560 /* 561 * Add our reference for the current connection in the client task 562 * tracking structure. If this is the first reference, create and 563 * hash in a new tracking structure. 564 */ 565 futex_down(&async_futex); 566 key = FIBRIL_connection->in_task_hash; 567 lnk = hash_table_find(&client_hash_table, &key); 568 if (lnk) { 569 cl = hash_table_get_instance(lnk, client_t, link); 570 cl->refcnt++; 571 } else { 572 cl = malloc(sizeof(client_t)); 573 if (!cl) { 574 ipc_answer_0(FIBRIL_connection->callid, ENOMEM); 575 futex_up(&async_futex); 576 return 0; 577 } 578 cl->in_task_hash = FIBRIL_connection->in_task_hash; 579 async_serialize_start(); 580 cl->data = async_client_data_create(); 581 async_serialize_end(); 582 cl->refcnt = 1; 583 hash_table_insert(&client_hash_table, &key, &cl->link); 584 } 585 futex_up(&async_futex); 586 587 FIBRIL_connection->client = cl; 588 589 /* 590 * Call the connection handler function. 591 */ 487 592 FIBRIL_connection->cfibril(FIBRIL_connection->callid, 488 593 &FIBRIL_connection->call); 489 594 490 /* Remove myself from the connection hash table */ 595 /* 596 * Remove the reference for this client task connection. 597 */ 491 598 futex_down(&async_futex); 492 unsigned long key = FIBRIL_connection->in_phone_hash; 599 if (--cl->refcnt == 0) { 600 hash_table_remove(&client_hash_table, &key, 1); 601 destroy = true; 602 } 603 futex_up(&async_futex); 604 605 if (destroy) { 606 if (cl->data) 607 async_client_data_destroy(cl->data); 608 free(cl); 609 } 610 611 /* 612 * Remove myself from the connection hash table. 613 */ 614 futex_down(&async_futex); 615 key = FIBRIL_connection->in_phone_hash; 493 616 hash_table_remove(&conn_hash_table, &key, 1); 494 617 futex_up(&async_futex); 495 618 496 /* Answer all remaining messages with EHANGUP */ 619 /* 620 * Answer all remaining messages with EHANGUP. 621 */ 497 622 while (!list_empty(&FIBRIL_connection->msg_queue)) { 498 623 msg_t *msg; … … 505 630 } 506 631 632 /* 633 * If the connection was hung-up, answer the last call, 634 * i.e. IPC_M_PHONE_HUNGUP. 635 */ 507 636 if (FIBRIL_connection->close_callid) 508 637 ipc_answer_0(FIBRIL_connection->close_callid, EOK); … … 517 646 * particular fibrils. 518 647 * 648 * @param in_task_hash Identification of the incoming connection. 519 649 * @param in_phone_hash Identification of the incoming connection. 520 650 * @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. … … 529 659 * 530 660 */ 531 fid_t async_new_connection(sysarg_t in_phone_hash, ipc_callid_t callid, 532 ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *)) 661 fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash, 662 ipc_callid_t callid, ipc_call_t *call, 663 void (*cfibril)(ipc_callid_t, ipc_call_t *)) 533 664 { 534 665 connection_t *conn = malloc(sizeof(*conn)); … … 539 670 } 540 671 672 conn->in_task_hash = in_task_hash; 541 673 conn->in_phone_hash = in_phone_hash; 542 674 list_initialize(&conn->msg_queue); … … 592 724 case IPC_M_CONNECT_ME_TO: 593 725 /* Open new connection with fibril etc. */ 594 async_new_connection( IPC_GET_ARG5(*call), callid, call,595 c lient_connection);726 async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call), 727 callid, call, client_connection); 596 728 goto out; 597 729 } … … 744 876 int __async_init(void) 745 877 { 746 if (!hash_table_create(&c onn_hash_table, CONN_HASH_TABLE_CHAINS, 1,747 &c onn_hash_table_ops)) {748 printf("%s: Cannot create async hash table\n", "libc");878 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1, 879 &client_hash_table_ops) || !hash_table_create(&conn_hash_table, 880 CONN_HASH_TABLE_BUCKETS, 1, &conn_hash_table_ops)) { 749 881 return ENOMEM; 750 882 }
Note:
See TracChangeset
for help on using the changeset viewer.