Changes in uspace/lib/c/generic/async.c [23882034:c1c0184] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
r23882034 rc1c0184 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 {143 136 awaiter_t wdata; 144 137 … … 146 139 link_t link; 147 140 148 /** Incoming client task hash. */149 sysarg_t in_task_hash;150 141 /** Incoming phone hash. */ 151 142 sysarg_t in_phone_hash; 152 143 153 /** Link to the client tracking structure. */154 client_t *client;155 156 144 /** Messages that should be delivered to this fibril. */ 157 145 link_t msg_queue; … … 172 160 fibril_local connection_t *FIBRIL_connection; 173 161 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 205 162 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); 206 163 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); … … 217 174 static async_client_conn_t interrupt_received = default_interrupt_received; 218 175 219 static hash_table_t client_hash_table;220 176 static hash_table_t conn_hash_table; 221 177 static LIST_INITIALIZE(timeout_list); 222 178 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) 179 #define CONN_HASH_TABLE_CHAINS 32 180 181 /** Compute hash into the connection hash table based on the source phone hash. 182 * 183 * @param key Pointer to source phone hash. 184 * 185 * @return Index into the connection hash table. 186 * 187 */ 188 static hash_index_t conn_hash(unsigned long *key) 227 189 { 228 190 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 }; 248 249 /** Compute hash into the connection hash table based on the source phone hash. 250 * 251 * @param key Pointer to source phone hash. 252 * 253 * @return Index into the connection hash table. 254 * 255 */ 256 static hash_index_t conn_hash(unsigned long *key) 257 { 258 assert(key); 259 return (((*key) >> 4) % CONN_HASH_TABLE_BUCKETS); 191 return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS); 260 192 } 261 193 … … 548 480 static int connection_fibril(void *arg) 549 481 { 550 unsigned long key;551 client_t *cl;552 link_t *lnk;553 bool destroy = false;554 555 482 /* 556 * Setup fibril-local connection pointer. 483 * Setup fibril-local connection pointer and call client_connection(). 484 * 557 485 */ 558 486 FIBRIL_connection = (connection_t *) arg; 559 560 /*561 * Add our reference for the current connection in the client task562 * tracking structure. If this is the first reference, create and563 * 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 */592 487 FIBRIL_connection->cfibril(FIBRIL_connection->callid, 593 488 &FIBRIL_connection->call); 594 489 595 /* 596 * Remove the reference for this client task connection. 597 */ 490 /* Remove myself from the connection hash table */ 598 491 futex_down(&async_futex); 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; 492 unsigned long key = FIBRIL_connection->in_phone_hash; 616 493 hash_table_remove(&conn_hash_table, &key, 1); 617 494 futex_up(&async_futex); 618 495 619 /* 620 * Answer all remaining messages with EHANGUP. 621 */ 496 /* Answer all remaining messages with EHANGUP */ 622 497 while (!list_empty(&FIBRIL_connection->msg_queue)) { 623 498 msg_t *msg; … … 630 505 } 631 506 632 /*633 * If the connection was hung-up, answer the last call,634 * i.e. IPC_M_PHONE_HUNGUP.635 */636 507 if (FIBRIL_connection->close_callid) 637 508 ipc_answer_0(FIBRIL_connection->close_callid, EOK); … … 646 517 * particular fibrils. 647 518 * 648 * @param in_task_hash Identification of the incoming connection.649 519 * @param in_phone_hash Identification of the incoming connection. 650 520 * @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. … … 659 529 * 660 530 */ 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 *)) 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 *)) 664 533 { 665 534 connection_t *conn = malloc(sizeof(*conn)); … … 670 539 } 671 540 672 conn->in_task_hash = in_task_hash;673 541 conn->in_phone_hash = in_phone_hash; 674 542 list_initialize(&conn->msg_queue); … … 724 592 case IPC_M_CONNECT_ME_TO: 725 593 /* Open new connection with fibril etc. */ 726 async_new_connection( call->in_task_hash, IPC_GET_ARG5(*call),727 c allid, call, client_connection);594 async_new_connection(IPC_GET_ARG5(*call), callid, call, 595 client_connection); 728 596 goto out; 729 597 } … … 876 744 int __async_init(void) 877 745 { 878 if (!hash_table_create(&c lient_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,879 &c lient_hash_table_ops) || !hash_table_create(&conn_hash_table,880 CONN_HASH_TABLE_BUCKETS, 1, &conn_hash_table_ops)) {746 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, 747 &conn_hash_table_ops)) { 748 printf("%s: Cannot create async hash table\n", "libc"); 881 749 return ENOMEM; 882 750 }
Note:
See TracChangeset
for help on using the changeset viewer.