Changes in uspace/lib/c/generic/async.c [86d7bfa:c1c0184] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
r86d7bfa rc1c0184 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 send 47 * more messages, [ try to get responses from kernel, if 48 * nothing found, might try synchronous ] 49 * 45 50 * Example of use (pseudo C): 46 51 * … … 53 58 * int fibril1(void *arg) 54 59 * { 55 * conn = async_connect_me_to();60 * conn = ipc_connect_me_to(); 56 61 * c1 = async_send(conn); 57 62 * c2 = async_send(conn); … … 72 77 * { 73 78 * if (want_refuse) { 74 * async_answer_0(icallid, ELIMIT);79 * ipc_answer_0(icallid, ELIMIT); 75 80 * return; 76 81 * } 77 * async_answer_0(icallid, EOK);82 * ipc_answer_0(icallid, EOK); 78 83 * 79 84 * callid = async_get_call(&call); 80 85 * somehow_handle_the_call(callid, call); 81 * async_answer_2(callid, 1, 2, 3);86 * ipc_answer_2(callid, 1, 2, 3); 82 87 * 83 88 * callid = async_get_call(&call); … … 87 92 */ 88 93 89 #define LIBC_ASYNC_C_ 90 #include <ipc/ipc.h> 94 #include <futex.h> 91 95 #include <async.h> 92 #undef LIBC_ASYNC_C_ 93 94 #include <futex.h> 96 #include <async_priv.h> 95 97 #include <fibril.h> 96 98 #include <stdio.h> 97 99 #include <adt/hash_table.h> 98 100 #include <adt/list.h> 101 #include <ipc/ipc.h> 99 102 #include <assert.h> 100 103 #include <errno.h> … … 102 105 #include <arch/barrier.h> 103 106 #include <bool.h> 104 #include "private/async.h"105 107 106 108 atomic_t async_futex = FUTEX_INITIALIZER; … … 122 124 123 125 /** 124 * Structures of this type are used to group information about 125 * a call and about amessage queue link.126 * Structures of this type are used to group information about a call and a 127 * message queue link. 126 128 */ 127 129 typedef struct { … … 132 134 133 135 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 {141 136 awaiter_t wdata; 142 137 … … 144 139 link_t link; 145 140 146 /** Incoming client task hash. */147 sysarg_t in_task_hash;148 141 /** Incoming phone hash. */ 149 142 sysarg_t in_phone_hash; 150 151 /** Link to the client tracking structure. */152 client_t *client;153 143 154 144 /** Messages that should be delivered to this fibril. */ … … 168 158 169 159 /** Identifier of the incoming connection handled by the current fibril. */ 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 } 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); 214 164 215 165 /** … … 217 167 */ 218 168 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 }231 169 232 170 /** … … 236 174 static async_client_conn_t interrupt_received = default_interrupt_received; 237 175 238 static hash_table_t client_hash_table;239 176 static hash_table_t conn_hash_table; 240 177 static LIST_INITIALIZE(timeout_list); 241 178 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[]) 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) 246 189 { 247 190 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 }; 267 268 /** Compute hash into the connection hash table based on the source phone hash. 269 * 270 * @param key Pointer to source phone hash. 271 * 272 * @return Index into the connection hash table. 273 * 274 */ 275 static hash_index_t conn_hash(unsigned long key[]) 276 { 277 assert(key); 278 return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS); 191 return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS); 279 192 } 280 193 … … 290 203 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) 291 204 { 292 connection_t * conn= hash_table_get_instance(item, connection_t, link);293 return (key[0] == conn->in_phone_hash);205 connection_t *hs = hash_table_get_instance(item, connection_t, link); 206 return (key[0] == hs->in_phone_hash); 294 207 } 295 208 … … 306 219 free(hash_table_get_instance(item, connection_t, link)); 307 220 } 221 308 222 309 223 /** Operations for the connection hash table. */ … … 326 240 link_t *tmp = timeout_list.next; 327 241 while (tmp != &timeout_list) { 328 awaiter_t *cur 329 = list_get_instance(tmp, awaiter_t, to_event.link); 242 awaiter_t *cur; 330 243 244 cur = list_get_instance(tmp, awaiter_t, to_event.link); 331 245 if (tv_gteq(&cur->to_event.expires, &wd->to_event.expires)) 332 246 break; 333 334 247 tmp = tmp->next; 335 248 } … … 348 261 * 349 262 * @return False if the call doesn't match any connection. 350 * @returnTrue if the call was passed to the respective connection fibril.263 * True if the call was passed to the respective connection fibril. 351 264 * 352 265 */ … … 439 352 440 353 fid_t fid = fibril_create(notification_fibril, msg); 441 if (fid == 0) {442 free(msg);443 futex_up(&async_futex);444 return false;445 }446 447 354 fibril_add_ready(fid); 448 355 … … 491 398 * the first IPC_M_PHONE_HUNGUP call and continues to 492 399 * call async_get_call_timeout(). Repeat 493 * IPC_M_PHONE_HUNGUP until the caller notices. 400 * IPC_M_PHONE_HUNGUP until the caller notices. 494 401 */ 495 402 memset(call, 0, sizeof(ipc_call_t)); … … 498 405 return conn->close_callid; 499 406 } 500 407 501 408 if (usecs) 502 409 async_insert_timeout(&conn->wdata); … … 536 443 } 537 444 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 538 470 /** Wrapper for client connection fibril. 539 471 * … … 549 481 { 550 482 /* 551 * Setup fibril-local connection pointer. 483 * Setup fibril-local connection pointer and call client_connection(). 484 * 552 485 */ 553 486 FIBRIL_connection = (connection_t *) arg; 554 555 futex_down(&async_futex);556 557 /*558 * Add our reference for the current connection in the client task559 * tracking structure. If this is the first reference, create and560 * hash in a new tracking structure.561 */562 563 unsigned long key = FIBRIL_connection->in_task_hash;564 link_t *lnk = hash_table_find(&client_hash_table, &key);565 566 client_t *client;567 568 if (lnk) {569 client = hash_table_get_instance(lnk, client_t, link);570 client->refcnt++;571 } else {572 client = malloc(sizeof(client_t));573 if (!client) {574 ipc_answer_0(FIBRIL_connection->callid, ENOMEM);575 futex_up(&async_futex);576 return 0;577 }578 579 client->in_task_hash = FIBRIL_connection->in_task_hash;580 581 async_serialize_start();582 client->data = async_client_data_create();583 async_serialize_end();584 585 client->refcnt = 1;586 hash_table_insert(&client_hash_table, &key, &client->link);587 }588 589 futex_up(&async_futex);590 591 FIBRIL_connection->client = client;592 593 /*594 * Call the connection handler function.595 */596 487 FIBRIL_connection->cfibril(FIBRIL_connection->callid, 597 488 &FIBRIL_connection->call); 598 489 599 /* 600 * Remove the reference for this client task connection. 601 */ 602 bool destroy; 603 490 /* Remove myself from the connection hash table */ 604 491 futex_down(&async_futex); 605 606 if (--client->refcnt == 0) { 607 hash_table_remove(&client_hash_table, &key, 1); 608 destroy = true; 609 } else 610 destroy = false; 611 612 futex_up(&async_futex); 613 614 if (destroy) { 615 if (client->data) 616 async_client_data_destroy(client->data); 617 618 free(client); 619 } 620 621 /* 622 * Remove myself from the connection hash table. 623 */ 624 futex_down(&async_futex); 625 key = FIBRIL_connection->in_phone_hash; 492 unsigned long key = FIBRIL_connection->in_phone_hash; 626 493 hash_table_remove(&conn_hash_table, &key, 1); 627 494 futex_up(&async_futex); 628 495 629 /* 630 * Answer all remaining messages with EHANGUP. 631 */ 496 /* Answer all remaining messages with EHANGUP */ 632 497 while (!list_empty(&FIBRIL_connection->msg_queue)) { 633 msg_t *msg = 634 list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, 635 link); 498 msg_t *msg; 636 499 500 msg = list_get_instance(FIBRIL_connection->msg_queue.next, 501 msg_t, link); 637 502 list_remove(&msg->link); 638 503 ipc_answer_0(msg->callid, EHANGUP); … … 640 505 } 641 506 642 /*643 * If the connection was hung-up, answer the last call,644 * i.e. IPC_M_PHONE_HUNGUP.645 */646 507 if (FIBRIL_connection->close_callid) 647 508 ipc_answer_0(FIBRIL_connection->close_callid, EOK); … … 656 517 * particular fibrils. 657 518 * 658 * @param in_task_hash Identification of the incoming connection.659 519 * @param in_phone_hash Identification of the incoming connection. 660 520 * @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. … … 669 529 * 670 530 */ 671 fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash, 672 ipc_callid_t callid, ipc_call_t *call, 673 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 *)) 674 533 { 675 534 connection_t *conn = malloc(sizeof(*conn)); … … 677 536 if (callid) 678 537 ipc_answer_0(callid, ENOMEM); 679 680 538 return (uintptr_t) NULL; 681 539 } 682 540 683 conn->in_task_hash = in_task_hash;684 541 conn->in_phone_hash = in_phone_hash; 685 542 list_initialize(&conn->msg_queue); … … 695 552 conn->wdata.fid = fibril_create(connection_fibril, conn); 696 553 697 if ( conn->wdata.fid == 0) {554 if (!conn->wdata.fid) { 698 555 free(conn); 699 700 556 if (callid) 701 557 ipc_answer_0(callid, ENOMEM); 702 703 558 return (uintptr_t) NULL; 704 559 } … … 727 582 static void handle_call(ipc_callid_t callid, ipc_call_t *call) 728 583 { 729 /* Unrouted call - take some default action*/584 /* Unrouted call - do some default behaviour */ 730 585 if ((callid & IPC_CALLID_NOTIFICATION)) { 731 586 process_notification(callid, call); 732 return;587 goto out; 733 588 } 734 589 … … 736 591 case IPC_M_CONNECT_ME: 737 592 case IPC_M_CONNECT_ME_TO: 738 /* Open new connection with fibril ,etc. */739 async_new_connection( call->in_task_hash, IPC_GET_ARG5(*call),740 c allid, call, client_connection);741 return;593 /* Open new connection with fibril etc. */ 594 async_new_connection(IPC_GET_ARG5(*call), callid, call, 595 client_connection); 596 goto out; 742 597 } 743 598 744 599 /* Try to route the call through the connection hash table */ 745 600 if (route_call(callid, call)) 746 return;601 goto out; 747 602 748 603 /* Unknown call from unknown phone - hang it up */ 749 604 ipc_answer_0(callid, EHANGUP); 605 return; 606 607 out: 608 ; 750 609 } 751 610 … … 760 619 link_t *cur = timeout_list.next; 761 620 while (cur != &timeout_list) { 762 awaiter_t *waiter = 763 list_get_instance(cur, awaiter_t, to_event.link); 621 awaiter_t *waiter; 764 622 623 waiter = list_get_instance(cur, awaiter_t, to_event.link); 765 624 if (tv_gt(&waiter->to_event.expires, &tv)) 766 625 break; 767 626 768 627 cur = cur->next; 769 628 770 629 list_remove(&waiter->to_event.link); 771 630 waiter->to_event.inlist = false; … … 794 653 while (true) { 795 654 if (fibril_switch(FIBRIL_FROM_MANAGER)) { 796 futex_up(&async_futex); 655 futex_up(&async_futex); 797 656 /* 798 657 * async_futex is always held when entering a manager … … 817 676 continue; 818 677 } else 819 timeout = tv_sub(&waiter->to_event.expires, &tv); 678 timeout = tv_sub(&waiter->to_event.expires, 679 &tv); 820 680 } else 821 681 timeout = SYNCH_NO_TIMEOUT; 822 682 823 683 futex_up(&async_futex); 824 684 825 685 atomic_inc(&threads_in_ipc_wait); 826 686 … … 830 690 831 691 atomic_dec(&threads_in_ipc_wait); 832 692 833 693 if (!callid) { 834 694 handle_expired_timeouts(); … … 869 729 { 870 730 fid_t fid = fibril_create(async_manager_fibril, NULL); 871 if (fid != 0) 872 fibril_add_manager(fid); 731 fibril_add_manager(fid); 873 732 } 874 733 … … 881 740 /** Initialize the async framework. 882 741 * 883 */ 884 void __async_init(void) 885 { 886 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1, 887 &client_hash_table_ops)) 888 abort(); 889 890 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1, 891 &conn_hash_table_ops)) 892 abort(); 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; 893 755 } 894 756 … … 903 765 * @param retval Value returned in the answer. 904 766 * @param data Call data of the answer. 905 *906 767 */ 907 768 static void reply_received(void *arg, int retval, ipc_call_t *data) … … 951 812 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 952 813 { 953 amsg_t *msg = malloc(sizeof( amsg_t));814 amsg_t *msg = malloc(sizeof(*msg)); 954 815 955 816 if (!msg) … … 960 821 961 822 msg->wdata.to_event.inlist = false; 962 963 /* 964 * We may sleep in the next method, 965 * but it will use its own means 966 */ 823 /* We may sleep in the next method, but it will use its own mechanism */ 967 824 msg->wdata.active = true; 968 825 … … 995 852 ipc_call_t *dataptr) 996 853 { 997 amsg_t *msg = malloc(sizeof( amsg_t));854 amsg_t *msg = malloc(sizeof(*msg)); 998 855 999 856 if (!msg) … … 1004 861 1005 862 msg->wdata.to_event.inlist = false; 1006 1007 /* 1008 * We may sleep in the next method, 1009 * but it will use its own means 1010 */ 863 /* We may sleep in next method, but it will use its own mechanism */ 1011 864 msg->wdata.active = true; 1012 865 … … 1107 960 void async_usleep(suseconds_t timeout) 1108 961 { 1109 amsg_t *msg = malloc(sizeof( amsg_t));962 amsg_t *msg = malloc(sizeof(*msg)); 1110 963 1111 964 if (!msg) … … 1250 1103 } 1251 1104 1252 void async_msg_0(int phone, sysarg_t imethod) 1253 { 1254 ipc_call_async_0(phone, imethod, NULL, NULL, true); 1255 } 1256 1257 void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1) 1258 { 1259 ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true); 1260 } 1261 1262 void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2) 1263 { 1264 ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true); 1265 } 1266 1267 void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1268 sysarg_t arg3) 1269 { 1270 ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true); 1271 } 1272 1273 void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1274 sysarg_t arg3, sysarg_t arg4) 1275 { 1276 ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL, 1277 true); 1278 } 1279 1280 void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1281 sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 1282 { 1283 ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL, 1284 NULL, true); 1285 } 1286 1287 sysarg_t async_answer_0(ipc_callid_t callid, sysarg_t retval) 1288 { 1289 return ipc_answer_0(callid, retval); 1290 } 1291 1292 sysarg_t async_answer_1(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1) 1293 { 1294 return ipc_answer_1(callid, retval, arg1); 1295 } 1296 1297 sysarg_t async_answer_2(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1298 sysarg_t arg2) 1299 { 1300 return ipc_answer_2(callid, retval, arg1, arg2); 1301 } 1302 1303 sysarg_t async_answer_3(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1304 sysarg_t arg2, sysarg_t arg3) 1305 { 1306 return ipc_answer_3(callid, retval, arg1, arg2, arg3); 1307 } 1308 1309 sysarg_t async_answer_4(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1310 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4) 1311 { 1312 return ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4); 1313 } 1314 1315 sysarg_t async_answer_5(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1316 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 1317 { 1318 return ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5); 1319 } 1320 1321 int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod, 1322 sysarg_t arg1, sysarg_t arg2, unsigned int mode) 1323 { 1324 return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode); 1325 } 1326 1327 int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod, 1328 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 1329 unsigned int mode) 1330 { 1331 return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4, 1332 arg5, mode); 1333 } 1334 1335 /** Wrapper for making IPC_M_CONNECT_TO_ME calls using the async framework. 1336 * 1105 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1106 * 1337 1107 * Ask through phone for a new connection to some service. 1338 1108 * 1339 * @param phone 1340 * @param arg1 1341 * @param arg2 1342 * @param arg3 1343 * @param client_receiver Connection handing routine.1344 * 1345 * @return New phone handle on success or a negative error code.1346 * 1347 */ 1348 int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2, 1349 sysarg_t arg3, async_client_conn_t client_receiver) 1350 { 1351 sysarg_t task_hash; 1352 sysarg_t phone_hash;1353 int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,1354 NULL, NULL, NULL, &task_hash, &phone_hash);1355 if (rc != EOK) 1109 * @param phoneid Phone handle used for contacting the other side. 1110 * @param arg1 User defined argument. 1111 * @param arg2 User defined argument. 1112 * @param arg3 User defined argument. 1113 * 1114 * @return New phone handle on success or a negative error code. 1115 */ 1116 int 1117 async_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) 1118 { 1119 int rc; 1120 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) 1356 1126 return rc; 1357 1358 if (client_receiver != NULL) 1359 async_new_connection(task_hash, phone_hash, 0, NULL, 1360 client_receiver); 1361 1362 return EOK; 1127 1128 return newphid; 1363 1129 } 1364 1130 1365 1131 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1366 * 1367 * Ask through phone for a new connection to some service. 1368 * 1369 * @param phone Phone handle used for contacting the other side. 1370 * @param arg1 User defined argument. 1371 * @param arg2 User defined argument. 1372 * @param arg3 User defined argument. 1373 * 1374 * @return New phone handle on success or a negative error code. 1375 * 1376 */ 1377 int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2, 1378 sysarg_t arg3) 1379 { 1380 sysarg_t newphid; 1381 int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1382 NULL, NULL, NULL, NULL, &newphid); 1383 1384 if (rc != EOK) 1385 return rc; 1386 1387 return newphid; 1388 } 1389 1390 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1391 * 1132 * 1392 1133 * Ask through phone for a new connection to some service and block until 1393 1134 * success. 1394 1135 * 1395 * @param phoneid 1396 * @param arg1 1397 * @param arg2 1398 * @param arg3 1399 * 1400 * @return 1401 * 1402 */ 1403 intasync_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,1136 * @param phoneid Phone handle used for contacting the other side. 1137 * @param arg1 User defined argument. 1138 * @param arg2 User defined argument. 1139 * @param arg3 User defined argument. 1140 * 1141 * @return New phone handle on success or a negative error code. 1142 */ 1143 int 1144 async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2, 1404 1145 sysarg_t arg3) 1405 1146 { 1147 int rc; 1406 1148 sysarg_t newphid; 1407 int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1149 1150 rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1408 1151 IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); 1409 1152 1410 if (rc != EOK) 1153 if (rc != EOK) 1411 1154 return rc; 1412 1155 1413 1156 return newphid; 1414 1157 } 1415 1158 1416 /** Connect to a task specified by id. 1417 * 1418 */ 1419 int async_connect_kbox(task_id_t id) 1420 { 1421 return ipc_connect_kbox(id); 1422 } 1423 1424 /** Wrapper for ipc_hangup. 1425 * 1426 * @param phone Phone handle to hung up. 1427 * 1428 * @return Zero on success or a negative error code. 1429 * 1430 */ 1431 int async_hangup(int phone) 1432 { 1433 return ipc_hangup(phone); 1434 } 1435 1436 /** Interrupt one thread of this task from waiting for IPC. */ 1437 void async_poke(void) 1438 { 1439 ipc_poke(); 1440 } 1441 1442 /** Wrapper for IPC_M_SHARE_IN calls using the async framework. 1443 * 1444 * @param phoneid Phone that will be used to contact the receiving side. 1445 * @param dst Destination address space area base. 1446 * @param size Size of the destination address space area. 1447 * @param arg User defined argument. 1448 * @param flags Storage for the received flags. Can be NULL. 1449 * 1450 * @return Zero on success or a negative error code from errno.h. 1451 * 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. 1452 1169 */ 1453 1170 int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg, 1454 unsigned int *flags) 1455 { 1171 int *flags) 1172 { 1173 int res; 1456 1174 sysarg_t tmp_flags; 1457 intres = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,1175 res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst, 1458 1176 (sysarg_t) size, arg, NULL, &tmp_flags); 1459 1460 1177 if (flags) 1461 *flags = (unsigned int) tmp_flags; 1462 1178 *flags = tmp_flags; 1463 1179 return res; 1464 1180 } … … 1466 1182 /** Wrapper for receiving the IPC_M_SHARE_IN calls using the async framework. 1467 1183 * 1468 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN 1469 * calls so that the user doesn't have to remember the meaning of each IPC 1470 * argument. 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. 1471 1186 * 1472 1187 * So far, this wrapper is to be used from within a connection fibril. 1473 1188 * 1474 * @param callid Storage for the hash of the IPC_M_SHARE_IN call. 1475 * @param size Destination address space area size. 1476 * 1477 * @return True on success, false on failure. 1478 * 1479 */ 1480 bool async_share_in_receive(ipc_callid_t *callid, size_t *size) 1481 { 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 1482 1199 assert(callid); 1483 1200 assert(size); 1484 1485 ipc_call_t data; 1201 1486 1202 *callid = async_get_call(&data); 1487 1488 1203 if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_IN) 1489 return false; 1490 1204 return 0; 1491 1205 *size = (size_t) IPC_GET_ARG2(data); 1492 return true;1206 return 1; 1493 1207 } 1494 1208 1495 1209 /** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework. 1496 1210 * 1497 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 1498 * calls so that the user doesn't have to remember the meaning of each IPC 1499 * argument. 1500 * 1501 * @param callid Hash of the IPC_M_DATA_READ call to answer. 1502 * @param src Source address space base. 1503 * @param flags Flags to be used for sharing. Bits can be only cleared. 1504 * 1505 * @return Zero on success or a value from @ref errno.h on failure. 1506 * 1507 */ 1508 int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags) 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) 1509 1221 { 1510 1222 return ipc_share_in_finalize(callid, src, flags); 1511 1223 } 1512 1224 1513 /** Wrapper for IPC_M_SHARE_OUT calls using the async framework. 1514 * 1515 * @param phoneid Phone that will be used to contact the receiving side. 1516 * @param src Source address space area base address. 1517 * @param flags Flags to be used for sharing. Bits can be only cleared. 1518 * 1519 * @return Zero on success or a negative error code from errno.h. 1520 * 1521 */ 1522 int async_share_out_start(int phoneid, void *src, unsigned int flags) 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) 1523 1234 { 1524 1235 return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0, … … 1528 1239 /** Wrapper for receiving the IPC_M_SHARE_OUT calls using the async framework. 1529 1240 * 1530 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT 1531 * calls so that the user doesn't have to remember the meaning of each IPC 1532 * argument. 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. 1533 1243 * 1534 1244 * So far, this wrapper is to be used from within a connection fibril. 1535 1245 * 1536 * @param callid Storage for the hash of the IPC_M_SHARE_OUT call. 1537 * @param size Storage for the source address space area size. 1538 * @param flags Storage for the sharing flags. 1539 * 1540 * @return True on success, false on failure. 1541 * 1542 */ 1543 bool async_share_out_receive(ipc_callid_t *callid, size_t *size, unsigned int *flags) 1544 { 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 1545 1258 assert(callid); 1546 1259 assert(size); 1547 1260 assert(flags); 1548 1549 ipc_call_t data; 1261 1550 1262 *callid = async_get_call(&data); 1551 1552 1263 if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_OUT) 1553 return false; 1554 1264 return 0; 1555 1265 *size = (size_t) IPC_GET_ARG2(data); 1556 *flags = ( unsignedint) IPC_GET_ARG3(data);1557 return true;1266 *flags = (int) IPC_GET_ARG3(data); 1267 return 1; 1558 1268 } 1559 1269 1560 1270 /** Wrapper for answering the IPC_M_SHARE_OUT calls using the async framework. 1561 1271 * 1562 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT 1563 * calls so that the user doesn't have to remember the meaning of each IPC 1564 * argument. 1565 * 1566 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 1567 * @param dst Destination address space area base address. 1568 * 1569 * @return Zero on success or a value from @ref errno.h on failure. 1570 * 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. 1571 1279 */ 1572 1280 int async_share_out_finalize(ipc_callid_t callid, void *dst) … … 1575 1283 } 1576 1284 1577 /** Wrapper for IPC_M_DATA_READ calls using the async framework. 1578 * 1579 * @param phoneid Phone that will be used to contact the receiving side.1580 * @param dst Address of the beginning of the destination buffer.1581 * @param size Sizeof the destination buffer.1582 * 1583 * @return Zero on success or a negative error code from errno.h.1584 * 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. 1585 1293 */ 1586 1294 int async_data_read_start(int phoneid, void *dst, size_t size) … … 1592 1300 /** Wrapper for receiving the IPC_M_DATA_READ calls using the async framework. 1593 1301 * 1594 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ 1595 * calls so that the user doesn't have to remember the meaning of each IPC 1596 * argument. 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. 1597 1304 * 1598 1305 * So far, this wrapper is to be used from within a connection fibril. 1599 1306 * 1600 * @param callid Storage for the hash of the IPC_M_DATA_READ. 1601 * @param size Storage for the maximum size. Can be NULL. 1602 * 1603 * @return True on success, false on failure. 1604 * 1605 */ 1606 bool async_data_read_receive(ipc_callid_t *callid, size_t *size) 1607 { 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 { 1316 ipc_call_t data; 1317 1608 1318 assert(callid); 1609 1610 ipc_call_t data; 1319 1611 1320 *callid = async_get_call(&data); 1612 1613 1321 if (IPC_GET_IMETHOD(data) != IPC_M_DATA_READ) 1614 return false; 1615 1322 return 0; 1616 1323 if (size) 1617 1324 *size = (size_t) IPC_GET_ARG2(data); 1618 1619 return true; 1325 return 1; 1620 1326 } 1621 1327 1622 1328 /** Wrapper for answering the IPC_M_DATA_READ calls using the async framework. 1623 1329 * 1624 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 1625 * calls so that the user doesn't have to remember the meaning of each IPC 1626 * argument. 1627 * 1628 * @param callid Hash of the IPC_M_DATA_READ call to answer. 1629 * @param src Source address for the IPC_M_DATA_READ call. 1630 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 1631 * the maximum size announced by the sender. 1632 * 1633 * @return Zero on success or a value from @ref errno.h on failure. 1634 * 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. 1635 1339 */ 1636 1340 int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size) … … 1640 1344 1641 1345 /** Wrapper for forwarding any read request 1346 * 1642 1347 * 1643 1348 */ … … 1672 1377 } 1673 1378 1674 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework.1379 /** Wrapper for making IPC_M_DATA_WRITE calls using the async framework. 1675 1380 * 1676 1381 * @param phoneid Phone that will be used to contact the receiving side. … … 1689 1394 /** Wrapper for receiving the IPC_M_DATA_WRITE calls using the async framework. 1690 1395 * 1691 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE 1692 * calls so that the user doesn't have to remember the meaning of each IPC 1693 * argument. 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. 1694 1398 * 1695 1399 * So far, this wrapper is to be used from within a connection fibril. 1696 1400 * 1697 * @param callid Storage for the hash of the IPC_M_DATA_WRITE. 1698 * @param size Storage for the suggested size. May be NULL. 1699 * 1700 * @return True on success, false on failure. 1701 * 1702 */ 1703 bool async_data_write_receive(ipc_callid_t *callid, size_t *size) 1704 { 1401 * @param callid Storage where the hash of the IPC_M_DATA_WRITE call will 1402 * be stored. 1403 * @param size Storage where the suggested size will be stored. May be 1404 * NULL 1405 * 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 { 1411 ipc_call_t data; 1412 1705 1413 assert(callid); 1706 1414 1707 ipc_call_t data;1708 1415 *callid = async_get_call(&data); 1709 1710 1416 if (IPC_GET_IMETHOD(data) != IPC_M_DATA_WRITE) 1711 return false;1417 return 0; 1712 1418 1713 1419 if (size) 1714 1420 *size = (size_t) IPC_GET_ARG2(data); 1715 1421 1716 return true;1422 return 1; 1717 1423 } 1718 1424 1719 1425 /** Wrapper for answering the IPC_M_DATA_WRITE calls using the async framework. 1720 1426 * 1721 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE 1722 * calls so that the user doesn't have to remember the meaning of each IPC 1723 * argument. 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. 1724 1429 * 1725 1430 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. … … 1817 1522 * 1818 1523 */ 1819 void async_data_write_void( sysarg_t retval)1524 void async_data_write_void(const int retval) 1820 1525 { 1821 1526 ipc_callid_t callid; … … 1825 1530 1826 1531 /** Wrapper for forwarding any data that is about to be received 1532 * 1827 1533 * 1828 1534 */
Note:
See TracChangeset
for help on using the changeset viewer.