Changes in uspace/lib/c/generic/async.c [c1c0184:8bf1eeb] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
rc1c0184 r8bf1eeb 43 43 * framework will automatically take care of most synchronization problems. 44 44 * 45 * Default semantics:46 * - async_send_*(): Send asynchronously. If the kernel refuses to send47 * more messages, [ try to get responses from kernel, if48 * nothing found, might try synchronous ]49 *50 45 * Example of use (pseudo C): 51 46 * … … 58 53 * int fibril1(void *arg) 59 54 * { 60 * conn = ipc_connect_me_to();55 * conn = async_connect_me_to(); 61 56 * c1 = async_send(conn); 62 57 * c2 = async_send(conn); … … 77 72 * { 78 73 * if (want_refuse) { 79 * ipc_answer_0(icallid, ELIMIT);74 * async_answer_0(icallid, ELIMIT); 80 75 * return; 81 76 * } 82 * ipc_answer_0(icallid, EOK);77 * async_answer_0(icallid, EOK); 83 78 * 84 79 * callid = async_get_call(&call); 85 80 * somehow_handle_the_call(callid, call); 86 * ipc_answer_2(callid, 1, 2, 3);81 * async_answer_2(callid, 1, 2, 3); 87 82 * 88 83 * callid = async_get_call(&call); … … 92 87 */ 93 88 89 #define LIBC_ASYNC_C_ 90 #include <ipc/ipc.h> 91 #include <async.h> 92 #undef LIBC_ASYNC_C_ 93 94 94 #include <futex.h> 95 #include <async.h>96 #include <async_priv.h>97 95 #include <fibril.h> 98 96 #include <stdio.h> 99 97 #include <adt/hash_table.h> 100 98 #include <adt/list.h> 101 #include <ipc/ipc.h>102 99 #include <assert.h> 103 100 #include <errno.h> … … 105 102 #include <arch/barrier.h> 106 103 #include <bool.h> 104 #include "private/async.h" 107 105 108 106 atomic_t async_futex = FUTEX_INITIALIZER; … … 124 122 125 123 /** 126 * Structures of this type are used to group information about a call and a127 * message queue link.124 * Structures of this type are used to group information about 125 * a call and about a message queue link. 128 126 */ 129 127 typedef struct { … … 134 132 135 133 typedef struct { 134 sysarg_t in_task_hash; 135 link_t link; 136 int refcnt; 137 void *data; 138 } client_t; 139 140 typedef struct { 136 141 awaiter_t wdata; 137 142 … … 139 144 link_t link; 140 145 146 /** Incoming client task hash. */ 147 sysarg_t in_task_hash; 141 148 /** Incoming phone hash. */ 142 149 sysarg_t in_phone_hash; 150 151 /** Link to the client tracking structure. */ 152 client_t *client; 143 153 144 154 /** Messages that should be delivered to this fibril. */ … … 158 168 159 169 /** Identifier of the incoming connection handled by the current fibril. */ 160 fibril_local connection_t *FIBRIL_connection; 161 162 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); 163 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); 170 static fibril_local connection_t *FIBRIL_connection; 171 172 static void *default_client_data_constructor(void) 173 { 174 return NULL; 175 } 176 177 static void default_client_data_destructor(void *data) 178 { 179 } 180 181 static async_client_data_ctor_t async_client_data_create = 182 default_client_data_constructor; 183 static async_client_data_dtor_t async_client_data_destroy = 184 default_client_data_destructor; 185 186 void async_set_client_data_constructor(async_client_data_ctor_t ctor) 187 { 188 async_client_data_create = ctor; 189 } 190 191 void async_set_client_data_destructor(async_client_data_dtor_t dtor) 192 { 193 async_client_data_destroy = dtor; 194 } 195 196 void *async_client_data_get(void) 197 { 198 assert(FIBRIL_connection); 199 return FIBRIL_connection->client->data; 200 } 201 202 /** Default fibril function that gets called to handle new connection. 203 * 204 * This function is defined as a weak symbol - to be redefined in user code. 205 * 206 * @param callid Hash of the incoming call. 207 * @param call Data of the incoming call. 208 * 209 */ 210 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) 211 { 212 ipc_answer_0(callid, ENOENT); 213 } 164 214 165 215 /** … … 167 217 */ 168 218 static async_client_conn_t client_connection = default_client_connection; 219 220 /** Default fibril function that gets called to handle interrupt notifications. 221 * 222 * This function is defined as a weak symbol - to be redefined in user code. 223 * 224 * @param callid Hash of the incoming call. 225 * @param call Data of the incoming call. 226 * 227 */ 228 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call) 229 { 230 } 169 231 170 232 /** … … 174 236 static async_client_conn_t interrupt_received = default_interrupt_received; 175 237 238 static hash_table_t client_hash_table; 176 239 static hash_table_t conn_hash_table; 177 240 static LIST_INITIALIZE(timeout_list); 178 241 179 #define CONN_HASH_TABLE_CHAINS 32 242 #define CLIENT_HASH_TABLE_BUCKETS 32 243 #define CONN_HASH_TABLE_BUCKETS 32 244 245 static hash_index_t client_hash(unsigned long key[]) 246 { 247 assert(key); 248 return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS); 249 } 250 251 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item) 252 { 253 client_t *client = hash_table_get_instance(item, client_t, link); 254 return (key[0] == client->in_task_hash); 255 } 256 257 static void client_remove(link_t *item) 258 { 259 } 260 261 /** Operations for the client hash table. */ 262 static hash_table_operations_t client_hash_table_ops = { 263 .hash = client_hash, 264 .compare = client_compare, 265 .remove_callback = client_remove 266 }; 180 267 181 268 /** Compute hash into the connection hash table based on the source phone hash. … … 186 273 * 187 274 */ 188 static hash_index_t conn_hash(unsigned long *key)275 static hash_index_t conn_hash(unsigned long key[]) 189 276 { 190 277 assert(key); 191 return ((( *key) >> 4) % CONN_HASH_TABLE_CHAINS);278 return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS); 192 279 } 193 280 … … 203 290 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) 204 291 { 205 connection_t *hs = hash_table_get_instance(item, connection_t, link); 206 return (key[0] == hs->in_phone_hash); 207 } 208 209 /** Connection hash table removal callback function. 210 * 211 * This function is called whenever a connection is removed from the connection 212 * hash table. 213 * 214 * @param item Connection hash table item being removed. 215 * 216 */ 292 connection_t *conn = hash_table_get_instance(item, connection_t, link); 293 return (key[0] == conn->in_phone_hash); 294 } 295 217 296 static void conn_remove(link_t *item) 218 297 { 219 free(hash_table_get_instance(item, connection_t, link)); 220 } 221 298 } 222 299 223 300 /** Operations for the connection hash table. */ … … 240 317 link_t *tmp = timeout_list.next; 241 318 while (tmp != &timeout_list) { 242 awaiter_t *cur ;243 244 cur = list_get_instance(tmp, awaiter_t, to_event.link);319 awaiter_t *cur 320 = list_get_instance(tmp, awaiter_t, to_event.link); 321 245 322 if (tv_gteq(&cur->to_event.expires, &wd->to_event.expires)) 246 323 break; 324 247 325 tmp = tmp->next; 248 326 } … … 261 339 * 262 340 * @return False if the call doesn't match any connection. 263 * 341 * @return True if the call was passed to the respective connection fibril. 264 342 * 265 343 */ … … 352 430 353 431 fid_t fid = fibril_create(notification_fibril, msg); 432 if (fid == 0) { 433 free(msg); 434 futex_up(&async_futex); 435 return false; 436 } 437 354 438 fibril_add_ready(fid); 355 439 … … 398 482 * the first IPC_M_PHONE_HUNGUP call and continues to 399 483 * call async_get_call_timeout(). Repeat 400 * IPC_M_PHONE_HUNGUP until the caller notices. 484 * IPC_M_PHONE_HUNGUP until the caller notices. 401 485 */ 402 486 memset(call, 0, sizeof(ipc_call_t)); … … 405 489 return conn->close_callid; 406 490 } 407 491 408 492 if (usecs) 409 493 async_insert_timeout(&conn->wdata); … … 443 527 } 444 528 445 /** Default fibril function that gets called to handle new connection.446 *447 * This function is defined as a weak symbol - to be redefined in user code.448 *449 * @param callid Hash of the incoming call.450 * @param call Data of the incoming call.451 *452 */453 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)454 {455 ipc_answer_0(callid, ENOENT);456 }457 458 /** Default fibril function that gets called to handle interrupt notifications.459 *460 * This function is defined as a weak symbol - to be redefined in user code.461 *462 * @param callid Hash of the incoming call.463 * @param call Data of the incoming call.464 *465 */466 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)467 {468 }469 470 529 /** Wrapper for client connection fibril. 471 530 * … … 481 540 { 482 541 /* 483 * Setup fibril-local connection pointer and call client_connection(). 484 * 542 * Setup fibril-local connection pointer. 485 543 */ 486 544 FIBRIL_connection = (connection_t *) arg; 545 546 futex_down(&async_futex); 547 548 /* 549 * Add our reference for the current connection in the client task 550 * tracking structure. If this is the first reference, create and 551 * hash in a new tracking structure. 552 */ 553 554 unsigned long key = FIBRIL_connection->in_task_hash; 555 link_t *lnk = hash_table_find(&client_hash_table, &key); 556 557 client_t *client; 558 559 if (lnk) { 560 client = hash_table_get_instance(lnk, client_t, link); 561 client->refcnt++; 562 } else { 563 client = malloc(sizeof(client_t)); 564 if (!client) { 565 ipc_answer_0(FIBRIL_connection->callid, ENOMEM); 566 futex_up(&async_futex); 567 return 0; 568 } 569 570 client->in_task_hash = FIBRIL_connection->in_task_hash; 571 572 async_serialize_start(); 573 client->data = async_client_data_create(); 574 async_serialize_end(); 575 576 client->refcnt = 1; 577 hash_table_insert(&client_hash_table, &key, &client->link); 578 } 579 580 futex_up(&async_futex); 581 582 FIBRIL_connection->client = client; 583 584 /* 585 * Call the connection handler function. 586 */ 487 587 FIBRIL_connection->cfibril(FIBRIL_connection->callid, 488 588 &FIBRIL_connection->call); 489 589 490 /* Remove myself from the connection hash table */ 590 /* 591 * Remove the reference for this client task connection. 592 */ 593 bool destroy; 594 491 595 futex_down(&async_futex); 492 unsigned long key = FIBRIL_connection->in_phone_hash; 596 597 if (--client->refcnt == 0) { 598 hash_table_remove(&client_hash_table, &key, 1); 599 destroy = true; 600 } else 601 destroy = false; 602 603 futex_up(&async_futex); 604 605 if (destroy) { 606 if (client->data) 607 async_client_data_destroy(client->data); 608 609 free(client); 610 } 611 612 /* 613 * Remove myself from the connection hash table. 614 */ 615 futex_down(&async_futex); 616 key = FIBRIL_connection->in_phone_hash; 493 617 hash_table_remove(&conn_hash_table, &key, 1); 494 618 futex_up(&async_futex); 495 619 496 /* Answer all remaining messages with EHANGUP */ 620 /* 621 * Answer all remaining messages with EHANGUP. 622 */ 497 623 while (!list_empty(&FIBRIL_connection->msg_queue)) { 498 msg_t *msg ;499 500 msg = list_get_instance(FIBRIL_connection->msg_queue.next,501 msg_t, link);624 msg_t *msg = 625 list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, 626 link); 627 502 628 list_remove(&msg->link); 503 629 ipc_answer_0(msg->callid, EHANGUP); … … 505 631 } 506 632 633 /* 634 * If the connection was hung-up, answer the last call, 635 * i.e. IPC_M_PHONE_HUNGUP. 636 */ 507 637 if (FIBRIL_connection->close_callid) 508 638 ipc_answer_0(FIBRIL_connection->close_callid, EOK); 509 639 640 free(FIBRIL_connection); 510 641 return 0; 511 642 } … … 517 648 * particular fibrils. 518 649 * 650 * @param in_task_hash Identification of the incoming connection. 519 651 * @param in_phone_hash Identification of the incoming connection. 520 652 * @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. … … 529 661 * 530 662 */ 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 *)) 663 fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash, 664 ipc_callid_t callid, ipc_call_t *call, 665 void (*cfibril)(ipc_callid_t, ipc_call_t *)) 533 666 { 534 667 connection_t *conn = malloc(sizeof(*conn)); … … 536 669 if (callid) 537 670 ipc_answer_0(callid, ENOMEM); 671 538 672 return (uintptr_t) NULL; 539 673 } 540 674 675 conn->in_task_hash = in_task_hash; 541 676 conn->in_phone_hash = in_phone_hash; 542 677 list_initialize(&conn->msg_queue); … … 552 687 conn->wdata.fid = fibril_create(connection_fibril, conn); 553 688 554 if ( !conn->wdata.fid) {689 if (conn->wdata.fid == 0) { 555 690 free(conn); 691 556 692 if (callid) 557 693 ipc_answer_0(callid, ENOMEM); 694 558 695 return (uintptr_t) NULL; 559 696 } … … 582 719 static void handle_call(ipc_callid_t callid, ipc_call_t *call) 583 720 { 584 /* Unrouted call - do some default behaviour*/721 /* Unrouted call - take some default action */ 585 722 if ((callid & IPC_CALLID_NOTIFICATION)) { 586 723 process_notification(callid, call); 587 goto out;724 return; 588 725 } 589 726 … … 591 728 case IPC_M_CONNECT_ME: 592 729 case IPC_M_CONNECT_ME_TO: 593 /* Open new connection with fibril etc. */594 async_new_connection( IPC_GET_ARG5(*call), callid, call,595 c lient_connection);596 goto out;730 /* Open new connection with fibril, etc. */ 731 async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call), 732 callid, call, client_connection); 733 return; 597 734 } 598 735 599 736 /* Try to route the call through the connection hash table */ 600 737 if (route_call(callid, call)) 601 goto out;738 return; 602 739 603 740 /* Unknown call from unknown phone - hang it up */ 604 741 ipc_answer_0(callid, EHANGUP); 605 return;606 607 out:608 ;609 742 } 610 743 … … 619 752 link_t *cur = timeout_list.next; 620 753 while (cur != &timeout_list) { 621 awaiter_t *waiter ;622 623 waiter = list_get_instance(cur, awaiter_t, to_event.link);754 awaiter_t *waiter = 755 list_get_instance(cur, awaiter_t, to_event.link); 756 624 757 if (tv_gt(&waiter->to_event.expires, &tv)) 625 758 break; 626 759 627 760 cur = cur->next; 628 761 629 762 list_remove(&waiter->to_event.link); 630 763 waiter->to_event.inlist = false; … … 653 786 while (true) { 654 787 if (fibril_switch(FIBRIL_FROM_MANAGER)) { 655 futex_up(&async_futex); 788 futex_up(&async_futex); 656 789 /* 657 790 * async_futex is always held when entering a manager … … 676 809 continue; 677 810 } else 678 timeout = tv_sub(&waiter->to_event.expires, 679 &tv); 811 timeout = tv_sub(&waiter->to_event.expires, &tv); 680 812 } else 681 813 timeout = SYNCH_NO_TIMEOUT; 682 814 683 815 futex_up(&async_futex); 684 816 685 817 atomic_inc(&threads_in_ipc_wait); 686 818 … … 690 822 691 823 atomic_dec(&threads_in_ipc_wait); 692 824 693 825 if (!callid) { 694 826 handle_expired_timeouts(); … … 729 861 { 730 862 fid_t fid = fibril_create(async_manager_fibril, NULL); 731 fibril_add_manager(fid); 863 if (fid != 0) 864 fibril_add_manager(fid); 732 865 } 733 866 … … 740 873 /** Initialize the async framework. 741 874 * 742 * @return Zero on success or an error code. 743 */ 744 int __async_init(void) 745 { 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"); 749 return ENOMEM; 750 } 751 752 _async_sess_init(); 753 754 return 0; 875 */ 876 void __async_init(void) 877 { 878 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1, 879 &client_hash_table_ops)) 880 abort(); 881 882 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1, 883 &conn_hash_table_ops)) 884 abort(); 755 885 } 756 886 … … 765 895 * @param retval Value returned in the answer. 766 896 * @param data Call data of the answer. 897 * 767 898 */ 768 899 static void reply_received(void *arg, int retval, ipc_call_t *data) … … 812 943 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 813 944 { 814 amsg_t *msg = malloc(sizeof( *msg));945 amsg_t *msg = malloc(sizeof(amsg_t)); 815 946 816 947 if (!msg) … … 821 952 822 953 msg->wdata.to_event.inlist = false; 823 /* We may sleep in the next method, but it will use its own mechanism */ 954 955 /* 956 * We may sleep in the next method, 957 * but it will use its own means 958 */ 824 959 msg->wdata.active = true; 825 960 … … 852 987 ipc_call_t *dataptr) 853 988 { 854 amsg_t *msg = malloc(sizeof( *msg));989 amsg_t *msg = malloc(sizeof(amsg_t)); 855 990 856 991 if (!msg) … … 861 996 862 997 msg->wdata.to_event.inlist = false; 863 /* We may sleep in next method, but it will use its own mechanism */ 998 999 /* 1000 * We may sleep in the next method, 1001 * but it will use its own means 1002 */ 864 1003 msg->wdata.active = true; 865 1004 … … 960 1099 void async_usleep(suseconds_t timeout) 961 1100 { 962 amsg_t *msg = malloc(sizeof( *msg));1101 amsg_t *msg = malloc(sizeof(amsg_t)); 963 1102 964 1103 if (!msg) … … 1103 1242 } 1104 1243 1244 void async_msg_0(int phone, sysarg_t imethod) 1245 { 1246 ipc_call_async_0(phone, imethod, NULL, NULL, true); 1247 } 1248 1249 void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1) 1250 { 1251 ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true); 1252 } 1253 1254 void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2) 1255 { 1256 ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true); 1257 } 1258 1259 void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1260 sysarg_t arg3) 1261 { 1262 ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true); 1263 } 1264 1265 void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1266 sysarg_t arg3, sysarg_t arg4) 1267 { 1268 ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL, 1269 true); 1270 } 1271 1272 void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1273 sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 1274 { 1275 ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL, 1276 NULL, true); 1277 } 1278 1279 sysarg_t async_answer_0(ipc_callid_t callid, sysarg_t retval) 1280 { 1281 return ipc_answer_0(callid, retval); 1282 } 1283 1284 sysarg_t async_answer_1(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1) 1285 { 1286 return ipc_answer_1(callid, retval, arg1); 1287 } 1288 1289 sysarg_t async_answer_2(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1290 sysarg_t arg2) 1291 { 1292 return ipc_answer_2(callid, retval, arg1, arg2); 1293 } 1294 1295 sysarg_t async_answer_3(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1296 sysarg_t arg2, sysarg_t arg3) 1297 { 1298 return ipc_answer_3(callid, retval, arg1, arg2, arg3); 1299 } 1300 1301 sysarg_t async_answer_4(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1302 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4) 1303 { 1304 return ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4); 1305 } 1306 1307 sysarg_t async_answer_5(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1308 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 1309 { 1310 return ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5); 1311 } 1312 1313 int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod, 1314 sysarg_t arg1, sysarg_t arg2, unsigned int mode) 1315 { 1316 return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode); 1317 } 1318 1319 int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod, 1320 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 1321 unsigned int mode) 1322 { 1323 return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4, 1324 arg5, mode); 1325 } 1326 1327 /** Wrapper for making IPC_M_CONNECT_TO_ME calls using the async framework. 1328 * 1329 * Ask through phone for a new connection to some service. 1330 * 1331 * @param phone Phone handle used for contacting the other side. 1332 * @param arg1 User defined argument. 1333 * @param arg2 User defined argument. 1334 * @param arg3 User defined argument. 1335 * @param client_receiver Connection handing routine. 1336 * 1337 * @return New phone handle on success or a negative error code. 1338 * 1339 */ 1340 int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2, 1341 sysarg_t arg3, async_client_conn_t client_receiver) 1342 { 1343 sysarg_t task_hash; 1344 sysarg_t phone_hash; 1345 int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 1346 NULL, NULL, NULL, &task_hash, &phone_hash); 1347 if (rc != EOK) 1348 return rc; 1349 1350 if (client_receiver != NULL) 1351 async_new_connection(task_hash, phone_hash, 0, NULL, 1352 client_receiver); 1353 1354 return EOK; 1355 } 1356 1105 1357 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1106 * 1358 * 1107 1359 * Ask through phone for a new connection to some service. 1108 1360 * 1109 * @param phone idPhone handle used for contacting the other side.1110 * @param arg1 1111 * @param arg2 1112 * @param arg3 1113 * 1114 * @return 1115 * /1116 int 1117 async_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) 1118 { 1119 int rc; 1361 * @param phone Phone handle used for contacting the other side. 1362 * @param arg1 User defined argument. 1363 * @param arg2 User defined argument. 1364 * @param arg3 User defined argument. 1365 * 1366 * @return New phone handle on success or a negative error code. 1367 * 1368 */ 1369 int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2, 1370 sysarg_t arg3) 1371 { 1120 1372 sysarg_t newphid; 1121 1122 rc = async_req_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, NULL, 1123 NULL, NULL, NULL, &newphid); 1124 1125 if (rc != EOK) 1373 int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1374 NULL, NULL, NULL, NULL, &newphid); 1375 1376 if (rc != EOK) 1126 1377 return rc; 1127 1378 1128 1379 return newphid; 1129 1380 } 1130 1381 1131 1382 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1132 * 1383 * 1133 1384 * Ask through phone for a new connection to some service and block until 1134 1385 * success. 1135 1386 * 1136 * @param phoneid 1137 * @param arg1 1138 * @param arg2 1139 * @param arg3 1140 * 1141 * @return 1142 * /1143 int 1144 async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,1387 * @param phoneid Phone handle used for contacting the other side. 1388 * @param arg1 User defined argument. 1389 * @param arg2 User defined argument. 1390 * @param arg3 User defined argument. 1391 * 1392 * @return New phone handle on success or a negative error code. 1393 * 1394 */ 1395 int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2, 1145 1396 sysarg_t arg3) 1146 1397 { 1147 int rc;1148 1398 sysarg_t newphid; 1149 1150 rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1399 int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1151 1400 IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); 1152 1401 1153 if (rc != EOK) 1402 if (rc != EOK) 1154 1403 return rc; 1155 1404 1156 1405 return newphid; 1157 1406 } 1158 1407 1159 /** Wrapper for making IPC_M_SHARE_IN calls using the async framework. 1160 * 1161 * @param phoneid Phone that will be used to contact the receiving side. 1162 * @param dst Destination address space area base. 1163 * @param size Size of the destination address space area. 1164 * @param arg User defined argument. 1165 * @param flags Storage where the received flags will be stored. Can be 1166 * NULL. 1167 * 1168 * @return Zero on success or a negative error code from errno.h. 1408 /** Connect to a task specified by id. 1409 * 1410 */ 1411 int async_connect_kbox(task_id_t id) 1412 { 1413 return ipc_connect_kbox(id); 1414 } 1415 1416 /** Wrapper for ipc_hangup. 1417 * 1418 * @param phone Phone handle to hung up. 1419 * 1420 * @return Zero on success or a negative error code. 1421 * 1422 */ 1423 int async_hangup(int phone) 1424 { 1425 return ipc_hangup(phone); 1426 } 1427 1428 /** Interrupt one thread of this task from waiting for IPC. */ 1429 void async_poke(void) 1430 { 1431 ipc_poke(); 1432 } 1433 1434 /** Wrapper for IPC_M_SHARE_IN calls using the async framework. 1435 * 1436 * @param phoneid Phone that will be used to contact the receiving side. 1437 * @param dst Destination address space area base. 1438 * @param size Size of the destination address space area. 1439 * @param arg User defined argument. 1440 * @param flags Storage for the received flags. Can be NULL. 1441 * 1442 * @return Zero on success or a negative error code from errno.h. 1443 * 1169 1444 */ 1170 1445 int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg, 1171 int *flags) 1172 { 1173 int res; 1446 unsigned int *flags) 1447 { 1174 1448 sysarg_t tmp_flags; 1175 res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,1449 int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst, 1176 1450 (sysarg_t) size, arg, NULL, &tmp_flags); 1451 1177 1452 if (flags) 1178 *flags = tmp_flags; 1453 *flags = (unsigned int) tmp_flags; 1454 1179 1455 return res; 1180 1456 } … … 1182 1458 /** Wrapper for receiving the IPC_M_SHARE_IN calls using the async framework. 1183 1459 * 1184 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN calls 1185 * so that the user doesn't have to remember the meaning of each IPC argument. 1460 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN 1461 * calls so that the user doesn't have to remember the meaning of each IPC 1462 * argument. 1186 1463 * 1187 1464 * So far, this wrapper is to be used from within a connection fibril. 1188 1465 * 1189 * @param callid Storage where the hash of the IPC_M_SHARE_IN call will 1190 * be stored. 1191 * @param size Destination address space area size. 1192 * 1193 * @return Non-zero on success, zero on failure. 1194 */ 1195 int async_share_in_receive(ipc_callid_t *callid, size_t *size) 1196 { 1197 ipc_call_t data; 1198 1466 * @param callid Storage for the hash of the IPC_M_SHARE_IN call. 1467 * @param size Destination address space area size. 1468 * 1469 * @return True on success, false on failure. 1470 * 1471 */ 1472 bool async_share_in_receive(ipc_callid_t *callid, size_t *size) 1473 { 1199 1474 assert(callid); 1200 1475 assert(size); 1201 1476 1477 ipc_call_t data; 1202 1478 *callid = async_get_call(&data); 1479 1203 1480 if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_IN) 1204 return 0; 1481 return false; 1482 1205 1483 *size = (size_t) IPC_GET_ARG2(data); 1206 return 1;1484 return true; 1207 1485 } 1208 1486 1209 1487 /** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework. 1210 1488 * 1211 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls 1212 * so that the user doesn't have to remember the meaning of each IPC argument. 1213 * 1214 * @param callid Hash of the IPC_M_DATA_READ call to answer. 1215 * @param src Source address space base. 1216 * @param flags Flags to be used for sharing. Bits can be only cleared. 1217 * 1218 * @return Zero on success or a value from @ref errno.h on failure. 1219 */ 1220 int async_share_in_finalize(ipc_callid_t callid, void *src, int flags) 1489 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 1490 * calls so that the user doesn't have to remember the meaning of each IPC 1491 * argument. 1492 * 1493 * @param callid Hash of the IPC_M_DATA_READ call to answer. 1494 * @param src Source address space base. 1495 * @param flags Flags to be used for sharing. Bits can be only cleared. 1496 * 1497 * @return Zero on success or a value from @ref errno.h on failure. 1498 * 1499 */ 1500 int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags) 1221 1501 { 1222 1502 return ipc_share_in_finalize(callid, src, flags); 1223 1503 } 1224 1504 1225 /** Wrapper for making IPC_M_SHARE_OUT calls using the async framework. 1226 * 1227 * @param phoneid Phone that will be used to contact the receiving side. 1228 * @param src Source address space area base address. 1229 * @param flags Flags to be used for sharing. Bits can be only cleared. 1230 * 1231 * @return Zero on success or a negative error code from errno.h. 1232 */ 1233 int async_share_out_start(int phoneid, void *src, int flags) 1505 /** Wrapper for IPC_M_SHARE_OUT calls using the async framework. 1506 * 1507 * @param phoneid Phone that will be used to contact the receiving side. 1508 * @param src Source address space area base address. 1509 * @param flags Flags to be used for sharing. Bits can be only cleared. 1510 * 1511 * @return Zero on success or a negative error code from errno.h. 1512 * 1513 */ 1514 int async_share_out_start(int phoneid, void *src, unsigned int flags) 1234 1515 { 1235 1516 return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0, … … 1239 1520 /** Wrapper for receiving the IPC_M_SHARE_OUT calls using the async framework. 1240 1521 * 1241 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT calls 1242 * so that the user doesn't have to remember the meaning of each IPC argument. 1522 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT 1523 * calls so that the user doesn't have to remember the meaning of each IPC 1524 * argument. 1243 1525 * 1244 1526 * So far, this wrapper is to be used from within a connection fibril. 1245 1527 * 1246 * @param callid Storage where the hash of the IPC_M_SHARE_OUT call will 1247 * be stored. 1248 * @param size Storage where the source address space area size will be 1249 * stored. 1250 * @param flags Storage where the sharing flags will be stored. 1251 * 1252 * @return Non-zero on success, zero on failure. 1253 */ 1254 int async_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags) 1255 { 1256 ipc_call_t data; 1257 1528 * @param callid Storage for the hash of the IPC_M_SHARE_OUT call. 1529 * @param size Storage for the source address space area size. 1530 * @param flags Storage for the sharing flags. 1531 * 1532 * @return True on success, false on failure. 1533 * 1534 */ 1535 bool async_share_out_receive(ipc_callid_t *callid, size_t *size, unsigned int *flags) 1536 { 1258 1537 assert(callid); 1259 1538 assert(size); 1260 1539 assert(flags); 1261 1540 1541 ipc_call_t data; 1262 1542 *callid = async_get_call(&data); 1543 1263 1544 if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_OUT) 1264 return 0; 1545 return false; 1546 1265 1547 *size = (size_t) IPC_GET_ARG2(data); 1266 *flags = ( int) IPC_GET_ARG3(data);1267 return 1;1548 *flags = (unsigned int) IPC_GET_ARG3(data); 1549 return true; 1268 1550 } 1269 1551 1270 1552 /** Wrapper for answering the IPC_M_SHARE_OUT calls using the async framework. 1271 1553 * 1272 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls 1273 * so that the user doesn't have to remember the meaning of each IPC argument. 1274 * 1275 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 1276 * @param dst Destination address space area base address. 1277 * 1278 * @return Zero on success or a value from @ref errno.h on failure. 1554 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT 1555 * calls so that the user doesn't have to remember the meaning of each IPC 1556 * argument. 1557 * 1558 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 1559 * @param dst Destination address space area base address. 1560 * 1561 * @return Zero on success or a value from @ref errno.h on failure. 1562 * 1279 1563 */ 1280 1564 int async_share_out_finalize(ipc_callid_t callid, void *dst) … … 1283 1567 } 1284 1568 1285 1286 /** Wrapper for making IPC_M_DATA_READ calls using the async framework. 1287 * 1288 * @param phoneid Phone that will be used to contact the receiving side. 1289 * @param dst Address of the beginning of the destination buffer. 1290 * @param size Size of the destination buffer. 1291 * 1292 * @return Zero on success or a negative error code from errno.h. 1569 /** Start IPC_M_DATA_READ using the async framework. 1570 * 1571 * @param phoneid Phone that will be used to contact the receiving side. 1572 * @param dst Address of the beginning of the destination buffer. 1573 * @param size Size of the destination buffer (in bytes). 1574 * @param dataptr Storage of call data (arg 2 holds actual data size). 1575 * @return Hash of the sent message or 0 on error. 1576 */ 1577 aid_t async_data_read(int phoneid, void *dst, size_t size, ipc_call_t *dataptr) 1578 { 1579 return async_send_2(phoneid, IPC_M_DATA_READ, (sysarg_t) dst, 1580 (sysarg_t) size, dataptr); 1581 } 1582 1583 /** Wrapper for IPC_M_DATA_READ calls using the async framework. 1584 * 1585 * @param phoneid Phone that will be used to contact the receiving side. 1586 * @param dst Address of the beginning of the destination buffer. 1587 * @param size Size of the destination buffer. 1588 * 1589 * @return Zero on success or a negative error code from errno.h. 1590 * 1293 1591 */ 1294 1592 int async_data_read_start(int phoneid, void *dst, size_t size) … … 1300 1598 /** Wrapper for receiving the IPC_M_DATA_READ calls using the async framework. 1301 1599 * 1302 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ calls 1303 * so that the user doesn't have to remember the meaning of each IPC argument. 1600 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ 1601 * calls so that the user doesn't have to remember the meaning of each IPC 1602 * argument. 1304 1603 * 1305 1604 * So far, this wrapper is to be used from within a connection fibril. 1306 1605 * 1307 * @param callid Storage where the hash of the IPC_M_DATA_READ call will 1308 * be stored. 1309 * @param size Storage where the maximum size will be stored. Can be 1310 * NULL. 1311 * 1312 * @return Non-zero on success, zero on failure. 1313 */ 1314 int async_data_read_receive(ipc_callid_t *callid, size_t *size) 1315 { 1606 * @param callid Storage for the hash of the IPC_M_DATA_READ. 1607 * @param size Storage for the maximum size. Can be NULL. 1608 * 1609 * @return True on success, false on failure. 1610 * 1611 */ 1612 bool async_data_read_receive(ipc_callid_t *callid, size_t *size) 1613 { 1614 assert(callid); 1615 1316 1616 ipc_call_t data; 1317 1318 assert(callid);1319 1320 1617 *callid = async_get_call(&data); 1618 1321 1619 if (IPC_GET_IMETHOD(data) != IPC_M_DATA_READ) 1322 return 0; 1620 return false; 1621 1323 1622 if (size) 1324 1623 *size = (size_t) IPC_GET_ARG2(data); 1325 return 1; 1624 1625 return true; 1326 1626 } 1327 1627 1328 1628 /** Wrapper for answering the IPC_M_DATA_READ calls using the async framework. 1329 1629 * 1330 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls 1331 * so that the user doesn't have to remember the meaning of each IPC argument. 1332 * 1333 * @param callid Hash of the IPC_M_DATA_READ call to answer. 1334 * @param src Source address for the IPC_M_DATA_READ call. 1335 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 1336 * the maximum size announced by the sender. 1337 * 1338 * @return Zero on success or a value from @ref errno.h on failure. 1630 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 1631 * calls so that the user doesn't have to remember the meaning of each IPC 1632 * argument. 1633 * 1634 * @param callid Hash of the IPC_M_DATA_READ call to answer. 1635 * @param src Source address for the IPC_M_DATA_READ call. 1636 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 1637 * the maximum size announced by the sender. 1638 * 1639 * @return Zero on success or a value from @ref errno.h on failure. 1640 * 1339 1641 */ 1340 1642 int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size) … … 1344 1646 1345 1647 /** Wrapper for forwarding any read request 1346 *1347 1648 * 1348 1649 */ … … 1377 1678 } 1378 1679 1379 /** Wrapper for makingIPC_M_DATA_WRITE calls using the async framework.1680 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework. 1380 1681 * 1381 1682 * @param phoneid Phone that will be used to contact the receiving side. … … 1394 1695 /** Wrapper for receiving the IPC_M_DATA_WRITE calls using the async framework. 1395 1696 * 1396 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE calls 1397 * so that the user doesn't have to remember the meaning of each IPC argument. 1697 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE 1698 * calls so that the user doesn't have to remember the meaning of each IPC 1699 * argument. 1398 1700 * 1399 1701 * So far, this wrapper is to be used from within a connection fibril. 1400 1702 * 1401 * @param callid Storage where the hash of the IPC_M_DATA_WRITE call will1402 * be stored.1403 * @param size Storage where the suggested size will be stored. May be1404 * NULL1405 * 1406 * @return Non-zero on success, zero on failure.1407 * 1408 */ 1409 int async_data_write_receive(ipc_callid_t *callid, size_t *size) 1410 { 1703 * @param callid Storage for the hash of the IPC_M_DATA_WRITE. 1704 * @param size Storage for the suggested size. May be NULL. 1705 * 1706 * @return True on success, false on failure. 1707 * 1708 */ 1709 bool async_data_write_receive(ipc_callid_t *callid, size_t *size) 1710 { 1711 assert(callid); 1712 1411 1713 ipc_call_t data; 1412 1413 assert(callid);1414 1415 1714 *callid = async_get_call(&data); 1715 1416 1716 if (IPC_GET_IMETHOD(data) != IPC_M_DATA_WRITE) 1417 return 0;1717 return false; 1418 1718 1419 1719 if (size) 1420 1720 *size = (size_t) IPC_GET_ARG2(data); 1421 1721 1422 return 1;1722 return true; 1423 1723 } 1424 1724 1425 1725 /** Wrapper for answering the IPC_M_DATA_WRITE calls using the async framework. 1426 1726 * 1427 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls 1428 * so that the user doesn't have to remember the meaning of each IPC argument. 1727 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE 1728 * calls so that the user doesn't have to remember the meaning of each IPC 1729 * argument. 1429 1730 * 1430 1731 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. … … 1522 1823 * 1523 1824 */ 1524 void async_data_write_void( const int retval)1825 void async_data_write_void(sysarg_t retval) 1525 1826 { 1526 1827 ipc_callid_t callid; … … 1530 1831 1531 1832 /** Wrapper for forwarding any data that is about to be received 1532 *1533 1833 * 1534 1834 */
Note:
See TracChangeset
for help on using the changeset viewer.