Changes in uspace/lib/c/generic/async.c [c7bbf029:3815efb] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
rc7bbf029 r3815efb 40 40 * programming. 41 41 * 42 * You should be able to write very simple multithreaded programs, the async 43 * framework will automatically take care of most synchronization problems. 42 * You should be able to write very simple multithreaded programs. The async 43 * framework will automatically take care of most of the synchronization 44 * problems. 44 45 * 45 46 * Example of use (pseudo C): … … 53 54 * int fibril1(void *arg) 54 55 * { 55 * conn = async_connect_me_to(); 56 * c1 = async_send(conn); 57 * c2 = async_send(conn); 56 * conn = async_connect_me_to(...); 57 * 58 * exch = async_exchange_begin(conn); 59 * c1 = async_send(exch); 60 * async_exchange_end(exch); 61 * 62 * exch = async_exchange_begin(conn); 63 * c2 = async_send(exch); 64 * async_exchange_end(exch); 65 * 58 66 * async_wait_for(c1); 59 67 * async_wait_for(c2); … … 94 102 #include <futex.h> 95 103 #include <fibril.h> 96 #include <stdio.h>97 104 #include <adt/hash_table.h> 98 105 #include <adt/list.h> … … 102 109 #include <arch/barrier.h> 103 110 #include <bool.h> 111 #include <malloc.h> 112 #include <mem.h> 104 113 #include <stdlib.h> 105 #include <malloc.h>106 114 #include "private/async.h" 107 115 116 #define CLIENT_HASH_TABLE_BUCKETS 32 117 #define CONN_HASH_TABLE_BUCKETS 32 118 119 /** Async framework global futex */ 108 120 atomic_t async_futex = FUTEX_INITIALIZER; 109 121 … … 111 123 atomic_t threads_in_ipc_wait = { 0 }; 112 124 113 typedef struct { 114 awaiter_t wdata; 115 116 /** If reply was received. */ 117 bool done; 118 119 /** Pointer to where the answer data is stored. */ 120 ipc_call_t *dataptr; 121 122 sysarg_t retval; 123 } amsg_t; 124 125 /** 126 * Structures of this type are used to group information about 127 * a call and about a message queue link. 128 */ 125 /** Naming service session */ 126 async_sess_t *session_ns; 127 128 /** Call data */ 129 129 typedef struct { 130 130 link_t link; 131 131 132 ipc_callid_t callid; 132 133 ipc_call_t call; 133 134 } msg_t; 134 135 136 /* Client connection data */ 135 137 typedef struct { 138 link_t link; 139 136 140 sysarg_t in_task_hash; 137 link_t link; 138 int refcnt; 141 atomic_t refcnt; 139 142 void *data; 140 143 } client_t; 141 144 145 /* Server connection data */ 142 146 typedef struct { 143 147 awaiter_t wdata; … … 148 152 /** Incoming client task hash. */ 149 153 sysarg_t in_task_hash; 154 150 155 /** Incoming phone hash. */ 151 156 sysarg_t in_phone_hash; … … 155 160 156 161 /** Messages that should be delivered to this fibril. */ 157 li nk_t msg_queue;162 list_t msg_queue; 158 163 159 164 /** Identification of the opening call. */ … … 161 166 /** Call data of the opening call. */ 162 167 ipc_call_t call; 168 /** Local argument or NULL if none. */ 169 void *carg; 163 170 164 171 /** Identification of the closing call. */ … … 166 173 167 174 /** Fibril function that will be used to handle the connection. */ 168 void (*cfibril)(ipc_callid_t, ipc_call_t *);175 async_client_conn_t cfibril; 169 176 } connection_t; 170 177 171 178 /** Identifier of the incoming connection handled by the current fibril. */ 172 static fibril_local connection_t * FIBRIL_connection;179 static fibril_local connection_t *fibril_connection; 173 180 174 181 static void *default_client_data_constructor(void) … … 196 203 } 197 204 198 void *async_ client_data_get(void)199 { 200 assert( FIBRIL_connection);201 return FIBRIL_connection->client->data;205 void *async_get_client_data(void) 206 { 207 assert(fibril_connection); 208 return fibril_connection->client->data; 202 209 } 203 210 … … 208 215 * @param callid Hash of the incoming call. 209 216 * @param call Data of the incoming call. 210 * 211 */ 212 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) 217 * @param arg Local argument 218 * 219 */ 220 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call, 221 void *arg) 213 222 { 214 223 ipc_answer_0(callid, ENOENT); 215 224 } 216 217 /**218 * Pointer to a fibril function that will be used to handle connections.219 */220 static async_client_conn_t client_connection = default_client_connection;221 225 222 226 /** Default fibril function that gets called to handle interrupt notifications. … … 226 230 * @param callid Hash of the incoming call. 227 231 * @param call Data of the incoming call. 232 * @param arg Local argument. 228 233 * 229 234 */ … … 232 237 } 233 238 234 /** 235 * Pointer to a fibril function that will be used to handle interrupt 236 * notifications. 237 */ 238 static async_client_conn_t interrupt_received = default_interrupt_received; 239 static async_client_conn_t client_connection = default_client_connection; 240 static async_interrupt_handler_t interrupt_received = default_interrupt_received; 241 242 /** Setter for client_connection function pointer. 243 * 244 * @param conn Function that will implement a new connection fibril. 245 * 246 */ 247 void async_set_client_connection(async_client_conn_t conn) 248 { 249 client_connection = conn; 250 } 251 252 /** Setter for interrupt_received function pointer. 253 * 254 * @param intr Function that will implement a new interrupt 255 * notification fibril. 256 */ 257 void async_set_interrupt_received(async_interrupt_handler_t intr) 258 { 259 interrupt_received = intr; 260 } 261 262 /** Mutex protecting inactive_exch_list and avail_phone_cv. 263 * 264 */ 265 static FIBRIL_MUTEX_INITIALIZE(async_sess_mutex); 266 267 /** List of all currently inactive exchanges. 268 * 269 */ 270 static LIST_INITIALIZE(inactive_exch_list); 271 272 /** Condition variable to wait for a phone to become available. 273 * 274 */ 275 static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv); 239 276 240 277 static hash_table_t client_hash_table; … … 242 279 static LIST_INITIALIZE(timeout_list); 243 280 244 #define CLIENT_HASH_TABLE_BUCKETS 32245 #define CONN_HASH_TABLE_BUCKETS 32246 247 281 static hash_index_t client_hash(unsigned long key[]) 248 282 { 249 283 assert(key); 284 250 285 return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS); 251 286 } … … 253 288 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item) 254 289 { 290 assert(key); 291 assert(item); 292 255 293 client_t *client = hash_table_get_instance(item, client_t, link); 256 294 return (key[0] == client->in_task_hash); … … 278 316 { 279 317 assert(key); 318 280 319 return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS); 281 320 } … … 292 331 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) 293 332 { 333 assert(key); 334 assert(item); 335 294 336 connection_t *conn = hash_table_get_instance(item, connection_t, link); 295 337 return (key[0] == conn->in_phone_hash); … … 314 356 void async_insert_timeout(awaiter_t *wd) 315 357 { 358 assert(wd); 359 316 360 wd->to_event.occurred = false; 317 361 wd->to_event.inlist = true; 318 362 319 link_t *tmp = timeout_list. next;320 while (tmp != &timeout_list ) {363 link_t *tmp = timeout_list.head.next; 364 while (tmp != &timeout_list.head) { 321 365 awaiter_t *cur 322 366 = list_get_instance(tmp, awaiter_t, to_event.link); … … 328 372 } 329 373 330 list_ append(&wd->to_event.link, tmp);374 list_insert_before(&wd->to_event.link, tmp); 331 375 } 332 376 … … 346 390 static bool route_call(ipc_callid_t callid, ipc_call_t *call) 347 391 { 392 assert(call); 393 348 394 futex_down(&async_futex); 349 395 … … 400 446 static int notification_fibril(void *arg) 401 447 { 448 assert(arg); 449 402 450 msg_t *msg = (msg_t *) arg; 403 451 interrupt_received(msg->callid, &msg->call); … … 420 468 static bool process_notification(ipc_callid_t callid, ipc_call_t *call) 421 469 { 470 assert(call); 471 422 472 futex_down(&async_futex); 423 473 … … 458 508 ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) 459 509 { 460 assert(FIBRIL_connection); 510 assert(call); 511 assert(fibril_connection); 461 512 462 513 /* Why doing this? 463 * GCC 4.1.0 coughs on FIBRIL_connection-> dereference.514 * GCC 4.1.0 coughs on fibril_connection-> dereference. 464 515 * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot. 465 516 * I would never expect to find so many errors in 466 517 * a compiler. 467 518 */ 468 connection_t *conn = FIBRIL_connection;519 connection_t *conn = fibril_connection; 469 520 470 521 futex_down(&async_futex); … … 518 569 } 519 570 520 msg_t *msg = list_get_instance( conn->msg_queue.next, msg_t, link);571 msg_t *msg = list_get_instance(list_first(&conn->msg_queue), msg_t, link); 521 572 list_remove(&msg->link); 522 573 … … 541 592 static int connection_fibril(void *arg) 542 593 { 594 assert(arg); 595 543 596 /* 544 597 * Setup fibril-local connection pointer. 545 598 */ 546 FIBRIL_connection = (connection_t *) arg;599 fibril_connection = (connection_t *) arg; 547 600 548 601 futex_down(&async_futex); … … 554 607 */ 555 608 556 unsigned long key = FIBRIL_connection->in_task_hash;609 unsigned long key = fibril_connection->in_task_hash; 557 610 link_t *lnk = hash_table_find(&client_hash_table, &key); 558 611 … … 561 614 if (lnk) { 562 615 client = hash_table_get_instance(lnk, client_t, link); 563 client->refcnt++;616 atomic_inc(&client->refcnt); 564 617 } else { 565 618 client = malloc(sizeof(client_t)); 566 619 if (!client) { 567 ipc_answer_0( FIBRIL_connection->callid, ENOMEM);620 ipc_answer_0(fibril_connection->callid, ENOMEM); 568 621 futex_up(&async_futex); 569 622 return 0; 570 623 } 571 624 572 client->in_task_hash = FIBRIL_connection->in_task_hash; 573 574 async_serialize_start(); 625 client->in_task_hash = fibril_connection->in_task_hash; 575 626 client->data = async_client_data_create(); 576 async_serialize_end(); 577 578 client->refcnt = 1; 627 628 atomic_set(&client->refcnt, 1); 579 629 hash_table_insert(&client_hash_table, &key, &client->link); 580 630 } … … 582 632 futex_up(&async_futex); 583 633 584 FIBRIL_connection->client = client;634 fibril_connection->client = client; 585 635 586 636 /* 587 637 * Call the connection handler function. 588 638 */ 589 FIBRIL_connection->cfibril(FIBRIL_connection->callid,590 & FIBRIL_connection->call);639 fibril_connection->cfibril(fibril_connection->callid, 640 &fibril_connection->call, fibril_connection->carg); 591 641 592 642 /* … … 597 647 futex_down(&async_futex); 598 648 599 if ( --client->refcnt== 0) {649 if (atomic_predec(&client->refcnt) == 0) { 600 650 hash_table_remove(&client_hash_table, &key, 1); 601 651 destroy = true; … … 616 666 */ 617 667 futex_down(&async_futex); 618 key = FIBRIL_connection->in_phone_hash;668 key = fibril_connection->in_phone_hash; 619 669 hash_table_remove(&conn_hash_table, &key, 1); 620 670 futex_up(&async_futex); … … 623 673 * Answer all remaining messages with EHANGUP. 624 674 */ 625 while (!list_empty(& FIBRIL_connection->msg_queue)) {675 while (!list_empty(&fibril_connection->msg_queue)) { 626 676 msg_t *msg = 627 list_get_instance( FIBRIL_connection->msg_queue.next, msg_t,628 link);677 list_get_instance(list_first(&fibril_connection->msg_queue), 678 msg_t, link); 629 679 630 680 list_remove(&msg->link); … … 637 687 * i.e. IPC_M_PHONE_HUNGUP. 638 688 */ 639 if ( FIBRIL_connection->close_callid)640 ipc_answer_0( FIBRIL_connection->close_callid, EOK);641 642 free( FIBRIL_connection);689 if (fibril_connection->close_callid) 690 ipc_answer_0(fibril_connection->close_callid, EOK); 691 692 free(fibril_connection); 643 693 return 0; 644 694 } … … 646 696 /** Create a new fibril for a new connection. 647 697 * 648 * Create new fibril for connection, fill in connection structures and insert s698 * Create new fibril for connection, fill in connection structures and insert 649 699 * it into the hash table, so that later we can easily do routing of messages to 650 700 * particular fibrils. … … 659 709 * @param cfibril Fibril function that should be called upon opening the 660 710 * connection. 711 * @param carg Extra argument to pass to the connection fibril 661 712 * 662 713 * @return New fibril id or NULL on failure. … … 665 716 fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash, 666 717 ipc_callid_t callid, ipc_call_t *call, 667 void (*cfibril)(ipc_callid_t, ipc_call_t *))718 async_client_conn_t cfibril, void *carg) 668 719 { 669 720 connection_t *conn = malloc(sizeof(*conn)); … … 680 731 conn->callid = callid; 681 732 conn->close_callid = 0; 733 conn->carg = carg; 682 734 683 735 if (call) … … 721 773 static void handle_call(ipc_callid_t callid, ipc_call_t *call) 722 774 { 775 assert(call); 776 723 777 /* Unrouted call - take some default action */ 724 778 if ((callid & IPC_CALLID_NOTIFICATION)) { … … 732 786 /* Open new connection with fibril, etc. */ 733 787 async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call), 734 callid, call, client_connection );788 callid, call, client_connection, NULL); 735 789 return; 736 790 } … … 752 806 futex_down(&async_futex); 753 807 754 link_t *cur = timeout_list.next;755 while (cur != &timeout_list) {808 link_t *cur = list_first(&timeout_list); 809 while (cur != NULL) { 756 810 awaiter_t *waiter = 757 811 list_get_instance(cur, awaiter_t, to_event.link); … … 759 813 if (tv_gt(&waiter->to_event.expires, &tv)) 760 814 break; 761 762 cur = cur->next;763 815 764 816 list_remove(&waiter->to_event.link); … … 774 826 fibril_add_ready(waiter->fid); 775 827 } 828 829 cur = list_first(&timeout_list); 776 830 } 777 831 … … 800 854 suseconds_t timeout; 801 855 if (!list_empty(&timeout_list)) { 802 awaiter_t *waiter = list_get_instance( timeout_list.next,803 awaiter_t, to_event.link);856 awaiter_t *waiter = list_get_instance( 857 list_first(&timeout_list), awaiter_t, to_event.link); 804 858 805 859 struct timeval tv; … … 878 932 void __async_init(void) 879 933 { 880 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,881 &client_hash_table_ops))934 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 935 1, &client_hash_table_ops)) 882 936 abort(); 883 937 884 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1,885 &conn_hash_table_ops))938 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 939 1, &conn_hash_table_ops)) 886 940 abort(); 941 942 session_ns = (async_sess_t *) malloc(sizeof(async_sess_t)); 943 if (session_ns == NULL) 944 abort(); 945 946 session_ns->mgmt = EXCHANGE_ATOMIC; 947 session_ns->phone = PHONE_NS; 948 session_ns->arg1 = 0; 949 session_ns->arg2 = 0; 950 session_ns->arg3 = 0; 951 952 list_initialize(&session_ns->exch_list); 953 fibril_mutex_initialize(&session_ns->mutex); 954 atomic_set(&session_ns->refcnt, 0); 887 955 } 888 956 … … 899 967 * 900 968 */ 901 static void reply_received(void *arg, int retval, ipc_call_t *data) 902 { 969 void reply_received(void *arg, int retval, ipc_call_t *data) 970 { 971 assert(arg); 972 903 973 futex_down(&async_futex); 904 974 … … 930 1000 * completion. 931 1001 * 932 * @param phoneid Handle of the phone that will be used for the send.933 * @param method Service-defined method.1002 * @param exch Exchange for sending the message. 1003 * @param imethod Service-defined interface and method. 934 1004 * @param arg1 Service-defined payload argument. 935 1005 * @param arg2 Service-defined payload argument. … … 942 1012 * 943 1013 */ 944 aid_t async_send_fast( int phoneid, sysarg_tmethod, sysarg_t arg1,1014 aid_t async_send_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 945 1015 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 946 1016 { 1017 if (exch == NULL) 1018 return 0; 1019 947 1020 amsg_t *msg = malloc(sizeof(amsg_t)); 948 949 if (!msg) 1021 if (msg == NULL) 950 1022 return 0; 951 1023 … … 961 1033 msg->wdata.active = true; 962 1034 963 ipc_call_async_4( phoneid,method, arg1, arg2, arg3, arg4, msg,1035 ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, msg, 964 1036 reply_received, true); 965 1037 … … 972 1044 * completion. 973 1045 * 974 * @param phoneid Handle of the phone that will be used for the send.975 * @param method Service-defined method.1046 * @param exch Exchange for sending the message. 1047 * @param imethod Service-defined interface and method. 976 1048 * @param arg1 Service-defined payload argument. 977 1049 * @param arg2 Service-defined payload argument. … … 985 1057 * 986 1058 */ 987 aid_t async_send_slow( int phoneid, sysarg_tmethod, sysarg_t arg1,1059 aid_t async_send_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 988 1060 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 989 1061 ipc_call_t *dataptr) 990 1062 { 1063 if (exch == NULL) 1064 return 0; 1065 991 1066 amsg_t *msg = malloc(sizeof(amsg_t)); 992 1067 993 if ( !msg)1068 if (msg == NULL) 994 1069 return 0; 995 1070 … … 1005 1080 msg->wdata.active = true; 1006 1081 1007 ipc_call_async_5( phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,1008 reply_received, true);1082 ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, arg5, 1083 msg, reply_received, true); 1009 1084 1010 1085 return (aid_t) msg; … … 1020 1095 void async_wait_for(aid_t amsgid, sysarg_t *retval) 1021 1096 { 1097 assert(amsgid); 1098 1022 1099 amsg_t *msg = (amsg_t *) amsgid; 1023 1100 … … 1056 1133 int async_wait_timeout(aid_t amsgid, sysarg_t *retval, suseconds_t timeout) 1057 1134 { 1135 assert(amsgid); 1136 1058 1137 amsg_t *msg = (amsg_t *) amsgid; 1059 1138 … … 1124 1203 } 1125 1204 1126 /** Setter for client_connection function pointer.1127 *1128 * @param conn Function that will implement a new connection fibril.1129 *1130 */1131 void async_set_client_connection(async_client_conn_t conn)1132 {1133 client_connection = conn;1134 }1135 1136 /** Setter for interrupt_received function pointer.1137 *1138 * @param intr Function that will implement a new interrupt1139 * notification fibril.1140 */1141 void async_set_interrupt_received(async_client_conn_t intr)1142 {1143 interrupt_received = intr;1144 }1145 1146 1205 /** Pseudo-synchronous message sending - fast version. 1147 1206 * … … 1151 1210 * transferring more arguments, see the slower async_req_slow(). 1152 1211 * 1153 * @param phoneid Hash of the phone through which to make the call.1154 * @param method Method of the call.1212 * @param exch Exchange for sending the message. 1213 * @param imethod Interface and method of the call. 1155 1214 * @param arg1 Service-defined payload argument. 1156 1215 * @param arg2 Service-defined payload argument. … … 1166 1225 * 1167 1226 */ 1168 sysarg_t async_req_fast( int phoneid, sysarg_tmethod, sysarg_t arg1,1227 sysarg_t async_req_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1169 1228 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2, 1170 1229 sysarg_t *r3, sysarg_t *r4, sysarg_t *r5) 1171 1230 { 1231 if (exch == NULL) 1232 return ENOENT; 1233 1172 1234 ipc_call_t result; 1173 aid_t eid = async_send_4(phoneid,method, arg1, arg2, arg3, arg4,1235 aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4, 1174 1236 &result); 1175 1237 1176 1238 sysarg_t rc; 1177 async_wait_for( eid, &rc);1239 async_wait_for(aid, &rc); 1178 1240 1179 1241 if (r1) … … 1199 1261 * Send message asynchronously and return only after the reply arrives. 1200 1262 * 1201 * @param phoneid Hash of the phone through which to make the call.1202 * @param method Method of the call.1263 * @param exch Exchange for sending the message. 1264 * @param imethod Interface and method of the call. 1203 1265 * @param arg1 Service-defined payload argument. 1204 1266 * @param arg2 Service-defined payload argument. … … 1215 1277 * 1216 1278 */ 1217 sysarg_t async_req_slow( int phoneid, sysarg_tmethod, sysarg_t arg1,1279 sysarg_t async_req_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1218 1280 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1, 1219 1281 sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5) 1220 1282 { 1283 if (exch == NULL) 1284 return ENOENT; 1285 1221 1286 ipc_call_t result; 1222 aid_t eid = async_send_5(phoneid,method, arg1, arg2, arg3, arg4, arg5,1287 aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5, 1223 1288 &result); 1224 1289 1225 1290 sysarg_t rc; 1226 async_wait_for( eid, &rc);1291 async_wait_for(aid, &rc); 1227 1292 1228 1293 if (r1) … … 1244 1309 } 1245 1310 1246 void async_msg_0(int phone, sysarg_t imethod) 1247 { 1248 ipc_call_async_0(phone, imethod, NULL, NULL, true); 1249 } 1250 1251 void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1) 1252 { 1253 ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true); 1254 } 1255 1256 void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2) 1257 { 1258 ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true); 1259 } 1260 1261 void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1262 sysarg_t arg3) 1263 { 1264 ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true); 1265 } 1266 1267 void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1268 sysarg_t arg3, sysarg_t arg4) 1269 { 1270 ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL, 1271 true); 1272 } 1273 1274 void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1275 sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 1276 { 1277 ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL, 1278 NULL, true); 1311 void async_msg_0(async_exch_t *exch, sysarg_t imethod) 1312 { 1313 if (exch != NULL) 1314 ipc_call_async_0(exch->phone, imethod, NULL, NULL, true); 1315 } 1316 1317 void async_msg_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1) 1318 { 1319 if (exch != NULL) 1320 ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL, true); 1321 } 1322 1323 void async_msg_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1324 sysarg_t arg2) 1325 { 1326 if (exch != NULL) 1327 ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL, 1328 true); 1329 } 1330 1331 void async_msg_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1332 sysarg_t arg2, sysarg_t arg3) 1333 { 1334 if (exch != NULL) 1335 ipc_call_async_3(exch->phone, imethod, arg1, arg2, arg3, NULL, 1336 NULL, true); 1337 } 1338 1339 void async_msg_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1340 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4) 1341 { 1342 if (exch != NULL) 1343 ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, 1344 NULL, NULL, true); 1345 } 1346 1347 void async_msg_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1348 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 1349 { 1350 if (exch != NULL) 1351 ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, 1352 arg5, NULL, NULL, true); 1279 1353 } 1280 1354 … … 1313 1387 } 1314 1388 1315 int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod, 1316 sysarg_t arg1, sysarg_t arg2, unsigned int mode) 1317 { 1318 return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode); 1319 } 1320 1321 int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod, 1322 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 1323 unsigned int mode) 1324 { 1325 return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4, 1326 arg5, mode); 1389 int async_forward_fast(ipc_callid_t callid, async_exch_t *exch, 1390 sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode) 1391 { 1392 if (exch == NULL) 1393 return ENOENT; 1394 1395 return ipc_forward_fast(callid, exch->phone, imethod, arg1, arg2, mode); 1396 } 1397 1398 int async_forward_slow(ipc_callid_t callid, async_exch_t *exch, 1399 sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, 1400 sysarg_t arg4, sysarg_t arg5, unsigned int mode) 1401 { 1402 if (exch == NULL) 1403 return ENOENT; 1404 1405 return ipc_forward_slow(callid, exch->phone, imethod, arg1, arg2, arg3, 1406 arg4, arg5, mode); 1327 1407 } 1328 1408 … … 1331 1411 * Ask through phone for a new connection to some service. 1332 1412 * 1333 * @param phone Phone handle used for contacting the other side.1413 * @param exch Exchange for sending the message. 1334 1414 * @param arg1 User defined argument. 1335 1415 * @param arg2 User defined argument. … … 1337 1417 * @param client_receiver Connection handing routine. 1338 1418 * 1339 * @return New phone handle on success or a negative error code. 1340 * 1341 */ 1342 int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2, 1343 sysarg_t arg3, async_client_conn_t client_receiver) 1344 { 1419 * @return Zero on success or a negative error code. 1420 * 1421 */ 1422 int async_connect_to_me(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2, 1423 sysarg_t arg3, async_client_conn_t client_receiver, void *carg) 1424 { 1425 if (exch == NULL) 1426 return ENOENT; 1427 1345 1428 sysarg_t task_hash; 1346 1429 sysarg_t phone_hash; 1347 int rc = async_req_3_5( phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,1430 int rc = async_req_3_5(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 1348 1431 NULL, NULL, NULL, &task_hash, &phone_hash); 1349 1432 if (rc != EOK) … … 1352 1435 if (client_receiver != NULL) 1353 1436 async_new_connection(task_hash, phone_hash, 0, NULL, 1354 client_receiver );1437 client_receiver, carg); 1355 1438 1356 1439 return EOK; 1357 1440 } 1358 1441 1359 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1360 * 1361 * Ask through phone for a new connection to some service. 1362 * 1363 * @param phone Phone handle used for contacting the other side. 1364 * @param arg1 User defined argument. 1365 * @param arg2 User defined argument. 1366 * @param arg3 User defined argument. 1367 * 1368 * @return New phone handle on success or a negative error code. 1369 * 1370 */ 1371 int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2, 1372 sysarg_t arg3) 1373 { 1374 sysarg_t newphid; 1375 int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1376 NULL, NULL, NULL, NULL, &newphid); 1442 /** Wrapper for making IPC_M_CONNECT_ME calls using the async framework. 1443 * 1444 * Ask through for a cloned connection to some service. 1445 * 1446 * @param mgmt Exchange management style. 1447 * @param exch Exchange for sending the message. 1448 * 1449 * @return New session on success or NULL on error. 1450 * 1451 */ 1452 async_sess_t *async_connect_me(exch_mgmt_t mgmt, async_exch_t *exch) 1453 { 1454 if (exch == NULL) { 1455 errno = ENOENT; 1456 return NULL; 1457 } 1458 1459 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 1460 if (sess == NULL) { 1461 errno = ENOMEM; 1462 return NULL; 1463 } 1464 1465 ipc_call_t result; 1466 1467 amsg_t *msg = malloc(sizeof(amsg_t)); 1468 if (msg == NULL) { 1469 free(sess); 1470 errno = ENOMEM; 1471 return NULL; 1472 } 1473 1474 msg->done = false; 1475 msg->dataptr = &result; 1476 1477 msg->wdata.to_event.inlist = false; 1478 1479 /* 1480 * We may sleep in the next method, 1481 * but it will use its own means 1482 */ 1483 msg->wdata.active = true; 1484 1485 ipc_call_async_0(exch->phone, IPC_M_CONNECT_ME, msg, 1486 reply_received, true); 1487 1488 sysarg_t rc; 1489 async_wait_for((aid_t) msg, &rc); 1490 1491 if (rc != EOK) { 1492 errno = rc; 1493 free(sess); 1494 return NULL; 1495 } 1496 1497 int phone = (int) IPC_GET_ARG5(result); 1498 1499 if (phone < 0) { 1500 errno = phone; 1501 free(sess); 1502 return NULL; 1503 } 1504 1505 sess->mgmt = mgmt; 1506 sess->phone = phone; 1507 sess->arg1 = 0; 1508 sess->arg2 = 0; 1509 sess->arg3 = 0; 1510 1511 list_initialize(&sess->exch_list); 1512 fibril_mutex_initialize(&sess->mutex); 1513 atomic_set(&sess->refcnt, 0); 1514 1515 return sess; 1516 } 1517 1518 static int async_connect_me_to_internal(int phone, sysarg_t arg1, sysarg_t arg2, 1519 sysarg_t arg3, sysarg_t arg4) 1520 { 1521 ipc_call_t result; 1522 1523 amsg_t *msg = malloc(sizeof(amsg_t)); 1524 if (msg == NULL) 1525 return ENOENT; 1526 1527 msg->done = false; 1528 msg->dataptr = &result; 1529 1530 msg->wdata.to_event.inlist = false; 1531 1532 /* 1533 * We may sleep in the next method, 1534 * but it will use its own means 1535 */ 1536 msg->wdata.active = true; 1537 1538 ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, arg4, 1539 msg, reply_received, true); 1540 1541 sysarg_t rc; 1542 async_wait_for((aid_t) msg, &rc); 1377 1543 1378 1544 if (rc != EOK) 1379 1545 return rc; 1380 1546 1381 return newphid; 1547 return (int) IPC_GET_ARG5(result); 1548 } 1549 1550 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1551 * 1552 * Ask through for a new connection to some service. 1553 * 1554 * @param mgmt Exchange management style. 1555 * @param exch Exchange for sending the message. 1556 * @param arg1 User defined argument. 1557 * @param arg2 User defined argument. 1558 * @param arg3 User defined argument. 1559 * 1560 * @return New session on success or NULL on error. 1561 * 1562 */ 1563 async_sess_t *async_connect_me_to(exch_mgmt_t mgmt, async_exch_t *exch, 1564 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) 1565 { 1566 if (exch == NULL) { 1567 errno = ENOENT; 1568 return NULL; 1569 } 1570 1571 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 1572 if (sess == NULL) { 1573 errno = ENOMEM; 1574 return NULL; 1575 } 1576 1577 int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3, 1578 0); 1579 1580 if (phone < 0) { 1581 errno = phone; 1582 free(sess); 1583 return NULL; 1584 } 1585 1586 sess->mgmt = mgmt; 1587 sess->phone = phone; 1588 sess->arg1 = arg1; 1589 sess->arg2 = arg2; 1590 sess->arg3 = arg3; 1591 1592 list_initialize(&sess->exch_list); 1593 fibril_mutex_initialize(&sess->mutex); 1594 atomic_set(&sess->refcnt, 0); 1595 1596 return sess; 1382 1597 } 1383 1598 … … 1387 1602 * success. 1388 1603 * 1389 * @param phoneid Phone handle used for contacting the other side. 1390 * @param arg1 User defined argument. 1391 * @param arg2 User defined argument. 1392 * @param arg3 User defined argument. 1393 * 1394 * @return New phone handle on success or a negative error code. 1395 * 1396 */ 1397 int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2, 1398 sysarg_t arg3) 1399 { 1400 sysarg_t newphid; 1401 int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1402 IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); 1403 1404 if (rc != EOK) 1405 return rc; 1406 1407 return newphid; 1604 * @param mgmt Exchange management style. 1605 * @param exch Exchange for sending the message. 1606 * @param arg1 User defined argument. 1607 * @param arg2 User defined argument. 1608 * @param arg3 User defined argument. 1609 * 1610 * @return New session on success or NULL on error. 1611 * 1612 */ 1613 async_sess_t *async_connect_me_to_blocking(exch_mgmt_t mgmt, async_exch_t *exch, 1614 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) 1615 { 1616 if (exch == NULL) { 1617 errno = ENOENT; 1618 return NULL; 1619 } 1620 1621 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 1622 if (sess == NULL) { 1623 errno = ENOMEM; 1624 return NULL; 1625 } 1626 1627 int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3, 1628 IPC_FLAG_BLOCKING); 1629 1630 if (phone < 0) { 1631 errno = phone; 1632 free(sess); 1633 return NULL; 1634 } 1635 1636 sess->mgmt = mgmt; 1637 sess->phone = phone; 1638 sess->arg1 = arg1; 1639 sess->arg2 = arg2; 1640 sess->arg3 = arg3; 1641 1642 list_initialize(&sess->exch_list); 1643 fibril_mutex_initialize(&sess->mutex); 1644 atomic_set(&sess->refcnt, 0); 1645 1646 return sess; 1408 1647 } 1409 1648 … … 1411 1650 * 1412 1651 */ 1413 int async_connect_kbox(task_id_t id) 1414 { 1415 return ipc_connect_kbox(id); 1652 async_sess_t *async_connect_kbox(task_id_t id) 1653 { 1654 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 1655 if (sess == NULL) { 1656 errno = ENOMEM; 1657 return NULL; 1658 } 1659 1660 int phone = ipc_connect_kbox(id); 1661 if (phone < 0) { 1662 errno = phone; 1663 free(sess); 1664 return NULL; 1665 } 1666 1667 sess->mgmt = EXCHANGE_ATOMIC; 1668 sess->phone = phone; 1669 sess->arg1 = 0; 1670 sess->arg2 = 0; 1671 sess->arg3 = 0; 1672 1673 list_initialize(&sess->exch_list); 1674 fibril_mutex_initialize(&sess->mutex); 1675 atomic_set(&sess->refcnt, 0); 1676 1677 return sess; 1678 } 1679 1680 static int async_hangup_internal(int phone) 1681 { 1682 return ipc_hangup(phone); 1416 1683 } 1417 1684 1418 1685 /** Wrapper for ipc_hangup. 1419 1686 * 1420 * @param phone Phone handleto hung up.1687 * @param sess Session to hung up. 1421 1688 * 1422 1689 * @return Zero on success or a negative error code. 1423 1690 * 1424 1691 */ 1425 int async_hangup(int phone) 1426 { 1427 return ipc_hangup(phone); 1692 int async_hangup(async_sess_t *sess) 1693 { 1694 assert(sess); 1695 1696 if (atomic_get(&sess->refcnt) > 0) 1697 return EBUSY; 1698 1699 int rc = async_hangup_internal(sess->phone); 1700 if (rc == EOK) 1701 free(sess); 1702 1703 return rc; 1428 1704 } 1429 1705 … … 1434 1710 } 1435 1711 1712 /** Start new exchange in a session. 1713 * 1714 * @param session Session. 1715 * 1716 * @return New exchange or NULL on error. 1717 * 1718 */ 1719 async_exch_t *async_exchange_begin(async_sess_t *sess) 1720 { 1721 if (sess == NULL) 1722 return NULL; 1723 1724 async_exch_t *exch; 1725 1726 fibril_mutex_lock(&async_sess_mutex); 1727 1728 if (!list_empty(&sess->exch_list)) { 1729 /* 1730 * There are inactive exchanges in the session. 1731 */ 1732 exch = (async_exch_t *) 1733 list_get_instance(list_first(&sess->exch_list), 1734 async_exch_t, sess_link); 1735 1736 list_remove(&exch->sess_link); 1737 list_remove(&exch->global_link); 1738 } else { 1739 /* 1740 * There are no available exchanges in the session. 1741 */ 1742 1743 if ((sess->mgmt == EXCHANGE_ATOMIC) || 1744 (sess->mgmt == EXCHANGE_SERIALIZE)) { 1745 exch = (async_exch_t *) malloc(sizeof(async_exch_t)); 1746 if (exch != NULL) { 1747 link_initialize(&exch->sess_link); 1748 link_initialize(&exch->global_link); 1749 exch->sess = sess; 1750 exch->phone = sess->phone; 1751 } 1752 } else { /* EXCHANGE_PARALLEL */ 1753 /* 1754 * Make a one-time attempt to connect a new data phone. 1755 */ 1756 1757 int phone; 1758 1759 retry: 1760 phone = async_connect_me_to_internal(sess->phone, sess->arg1, 1761 sess->arg2, sess->arg3, 0); 1762 if (phone >= 0) { 1763 exch = (async_exch_t *) malloc(sizeof(async_exch_t)); 1764 if (exch != NULL) { 1765 link_initialize(&exch->sess_link); 1766 link_initialize(&exch->global_link); 1767 exch->sess = sess; 1768 exch->phone = phone; 1769 } else 1770 async_hangup_internal(phone); 1771 } else if (!list_empty(&inactive_exch_list)) { 1772 /* 1773 * We did not manage to connect a new phone. But we 1774 * can try to close some of the currently inactive 1775 * connections in other sessions and try again. 1776 */ 1777 exch = (async_exch_t *) 1778 list_get_instance(list_first(&inactive_exch_list), 1779 async_exch_t, global_link); 1780 1781 list_remove(&exch->sess_link); 1782 list_remove(&exch->global_link); 1783 async_hangup_internal(exch->phone); 1784 free(exch); 1785 goto retry; 1786 } else { 1787 /* 1788 * Wait for a phone to become available. 1789 */ 1790 fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex); 1791 goto retry; 1792 } 1793 } 1794 } 1795 1796 fibril_mutex_unlock(&async_sess_mutex); 1797 1798 if (exch != NULL) { 1799 atomic_inc(&sess->refcnt); 1800 1801 if (sess->mgmt == EXCHANGE_SERIALIZE) 1802 fibril_mutex_lock(&sess->mutex); 1803 } 1804 1805 return exch; 1806 } 1807 1808 /** Finish an exchange. 1809 * 1810 * @param exch Exchange to finish. 1811 * 1812 */ 1813 void async_exchange_end(async_exch_t *exch) 1814 { 1815 if (exch == NULL) 1816 return; 1817 1818 async_sess_t *sess = exch->sess; 1819 1820 atomic_dec(&sess->refcnt); 1821 1822 if (sess->mgmt == EXCHANGE_SERIALIZE) 1823 fibril_mutex_unlock(&sess->mutex); 1824 1825 fibril_mutex_lock(&async_sess_mutex); 1826 1827 list_append(&exch->sess_link, &sess->exch_list); 1828 list_append(&exch->global_link, &inactive_exch_list); 1829 fibril_condvar_signal(&avail_phone_cv); 1830 1831 fibril_mutex_unlock(&async_sess_mutex); 1832 } 1833 1436 1834 /** Wrapper for IPC_M_SHARE_IN calls using the async framework. 1437 1835 * 1438 * @param phoneid Phone that will be used to contact the receiving side.1439 * @param dst 1440 * @param size 1441 * @param arg 1442 * @param flags 1836 * @param exch Exchange for sending the message. 1837 * @param dst Destination address space area base. 1838 * @param size Size of the destination address space area. 1839 * @param arg User defined argument. 1840 * @param flags Storage for the received flags. Can be NULL. 1443 1841 * 1444 1842 * @return Zero on success or a negative error code from errno.h. 1445 1843 * 1446 1844 */ 1447 int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg, 1448 unsigned int *flags) 1449 { 1845 int async_share_in_start(async_exch_t *exch, void *dst, size_t size, 1846 sysarg_t arg, unsigned int *flags) 1847 { 1848 if (exch == NULL) 1849 return ENOENT; 1850 1450 1851 sysarg_t tmp_flags; 1451 int res = async_req_3_2( phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,1852 int res = async_req_3_2(exch, IPC_M_SHARE_IN, (sysarg_t) dst, 1452 1853 (sysarg_t) size, arg, NULL, &tmp_flags); 1453 1854 … … 1507 1908 /** Wrapper for IPC_M_SHARE_OUT calls using the async framework. 1508 1909 * 1509 * @param phoneid Phone that will be used to contact the receiving side.1510 * @param src 1511 * @param flags 1910 * @param exch Exchange for sending the message. 1911 * @param src Source address space area base address. 1912 * @param flags Flags to be used for sharing. Bits can be only cleared. 1512 1913 * 1513 1914 * @return Zero on success or a negative error code from errno.h. 1514 1915 * 1515 1916 */ 1516 int async_share_out_start(int phoneid, void *src, unsigned int flags) 1517 { 1518 return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0, 1917 int async_share_out_start(async_exch_t *exch, void *src, unsigned int flags) 1918 { 1919 if (exch == NULL) 1920 return ENOENT; 1921 1922 return async_req_3_0(exch, IPC_M_SHARE_OUT, (sysarg_t) src, 0, 1519 1923 (sysarg_t) flags); 1520 1924 } … … 1569 1973 } 1570 1974 1975 /** Start IPC_M_DATA_READ using the async framework. 1976 * 1977 * @param exch Exchange for sending the message. 1978 * @param dst Address of the beginning of the destination buffer. 1979 * @param size Size of the destination buffer (in bytes). 1980 * @param dataptr Storage of call data (arg 2 holds actual data size). 1981 * 1982 * @return Hash of the sent message or 0 on error. 1983 * 1984 */ 1985 aid_t async_data_read(async_exch_t *exch, void *dst, size_t size, 1986 ipc_call_t *dataptr) 1987 { 1988 return async_send_2(exch, IPC_M_DATA_READ, (sysarg_t) dst, 1989 (sysarg_t) size, dataptr); 1990 } 1991 1571 1992 /** Wrapper for IPC_M_DATA_READ calls using the async framework. 1572 1993 * 1573 * @param phoneid Phone that will be used to contact the receiving side. 1574 * @param dst Address of the beginning of the destination buffer. 1575 * @param size Size of the destination buffer. 1576 * @param flags Flags to control the data transfer. 1994 * @param exch Exchange for sending the message. 1995 * @param dst Address of the beginning of the destination buffer. 1996 * @param size Size of the destination buffer. 1577 1997 * 1578 1998 * @return Zero on success or a negative error code from errno.h. 1579 1999 * 1580 2000 */ 1581 int 1582 async_data_read_start_generic(int phoneid, void *dst, size_t size, int flags) 1583 { 1584 return async_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst, 1585 (sysarg_t) size, (sysarg_t) flags); 2001 int async_data_read_start(async_exch_t *exch, void *dst, size_t size) 2002 { 2003 if (exch == NULL) 2004 return ENOENT; 2005 2006 return async_req_2_0(exch, IPC_M_DATA_READ, (sysarg_t) dst, 2007 (sysarg_t) size); 1586 2008 } 1587 2009 … … 1638 2060 * 1639 2061 */ 1640 int async_data_read_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1, 1641 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 1642 { 2062 int async_data_read_forward_fast(async_exch_t *exch, sysarg_t imethod, 2063 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, 2064 ipc_call_t *dataptr) 2065 { 2066 if (exch == NULL) 2067 return ENOENT; 2068 1643 2069 ipc_callid_t callid; 1644 2070 if (!async_data_read_receive(&callid, NULL)) { … … 1647 2073 } 1648 2074 1649 aid_t msg = async_send_fast( phoneid,method, arg1, arg2, arg3, arg4,2075 aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4, 1650 2076 dataptr); 1651 2077 if (msg == 0) { … … 1654 2080 } 1655 2081 1656 int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,2082 int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0, 1657 2083 IPC_FF_ROUTE_FROM_ME); 1658 2084 if (retval != EOK) { … … 1670 2096 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework. 1671 2097 * 1672 * @param phoneid Phone that will be used to contact the receiving side. 1673 * @param src Address of the beginning of the source buffer. 1674 * @param size Size of the source buffer. 1675 * @param flags Flags to control the data transfer. 2098 * @param exch Exchange for sending the message. 2099 * @param src Address of the beginning of the source buffer. 2100 * @param size Size of the source buffer. 1676 2101 * 1677 2102 * @return Zero on success or a negative error code from errno.h. 1678 2103 * 1679 2104 */ 1680 int 1681 async_data_write_start_generic(int phoneid, const void *src, size_t size, 1682 int flags) 1683 { 1684 return async_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src, 1685 (sysarg_t) size, (sysarg_t) flags); 2105 int async_data_write_start(async_exch_t *exch, const void *src, size_t size) 2106 { 2107 if (exch == NULL) 2108 return ENOENT; 2109 2110 return async_req_2_0(exch, IPC_M_DATA_WRITE, (sysarg_t) src, 2111 (sysarg_t) size); 1686 2112 } 1687 2113 … … 1759 2185 size_t *received) 1760 2186 { 2187 assert(data); 2188 1761 2189 ipc_callid_t callid; 1762 2190 size_t size; … … 1826 2254 * 1827 2255 */ 1828 int async_data_write_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1, 1829 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 1830 { 2256 int async_data_write_forward_fast(async_exch_t *exch, sysarg_t imethod, 2257 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, 2258 ipc_call_t *dataptr) 2259 { 2260 if (exch == NULL) 2261 return ENOENT; 2262 1831 2263 ipc_callid_t callid; 1832 2264 if (!async_data_write_receive(&callid, NULL)) { … … 1835 2267 } 1836 2268 1837 aid_t msg = async_send_fast( phoneid,method, arg1, arg2, arg3, arg4,2269 aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4, 1838 2270 dataptr); 1839 2271 if (msg == 0) { … … 1842 2274 } 1843 2275 1844 int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,2276 int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0, 1845 2277 IPC_FF_ROUTE_FROM_ME); 1846 2278 if (retval != EOK) { … … 1856 2288 } 1857 2289 2290 /** Wrapper for sending an exchange over different exchange for cloning 2291 * 2292 * @param exch Exchange to be used for sending. 2293 * @param clone_exch Exchange to be cloned. 2294 * 2295 */ 2296 int async_exchange_clone(async_exch_t *exch, async_exch_t *clone_exch) 2297 { 2298 return async_req_1_0(exch, IPC_M_CONNECTION_CLONE, clone_exch->phone); 2299 } 2300 2301 /** Wrapper for receiving the IPC_M_CONNECTION_CLONE calls. 2302 * 2303 * If the current call is IPC_M_CONNECTION_CLONE then a new 2304 * async session is created for the accepted phone. 2305 * 2306 * @param mgmt Exchange management style. 2307 * 2308 * @return New async session or NULL on failure. 2309 * 2310 */ 2311 async_sess_t *async_clone_receive(exch_mgmt_t mgmt) 2312 { 2313 /* Accept the phone */ 2314 ipc_call_t call; 2315 ipc_callid_t callid = async_get_call(&call); 2316 int phone = (int) IPC_GET_ARG1(call); 2317 2318 if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECTION_CLONE) || 2319 (phone < 0)) { 2320 async_answer_0(callid, EINVAL); 2321 return NULL; 2322 } 2323 2324 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 2325 if (sess == NULL) { 2326 async_answer_0(callid, ENOMEM); 2327 return NULL; 2328 } 2329 2330 sess->mgmt = mgmt; 2331 sess->phone = phone; 2332 sess->arg1 = 0; 2333 sess->arg2 = 0; 2334 sess->arg3 = 0; 2335 2336 list_initialize(&sess->exch_list); 2337 fibril_mutex_initialize(&sess->mutex); 2338 atomic_set(&sess->refcnt, 0); 2339 2340 /* Acknowledge the cloned phone */ 2341 async_answer_0(callid, EOK); 2342 2343 return sess; 2344 } 2345 2346 /** Wrapper for receiving the IPC_M_CONNECT_TO_ME calls. 2347 * 2348 * If the current call is IPC_M_CONNECT_TO_ME then a new 2349 * async session is created for the accepted phone. 2350 * 2351 * @param mgmt Exchange management style. 2352 * 2353 * @return New async session. 2354 * @return NULL on failure. 2355 * 2356 */ 2357 async_sess_t *async_callback_receive(exch_mgmt_t mgmt) 2358 { 2359 /* Accept the phone */ 2360 ipc_call_t call; 2361 ipc_callid_t callid = async_get_call(&call); 2362 int phone = (int) IPC_GET_ARG5(call); 2363 2364 if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) || 2365 (phone < 0)) { 2366 async_answer_0(callid, EINVAL); 2367 return NULL; 2368 } 2369 2370 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 2371 if (sess == NULL) { 2372 async_answer_0(callid, ENOMEM); 2373 return NULL; 2374 } 2375 2376 sess->mgmt = mgmt; 2377 sess->phone = phone; 2378 sess->arg1 = 0; 2379 sess->arg2 = 0; 2380 sess->arg3 = 0; 2381 2382 list_initialize(&sess->exch_list); 2383 fibril_mutex_initialize(&sess->mutex); 2384 atomic_set(&sess->refcnt, 0); 2385 2386 /* Acknowledge the connected phone */ 2387 async_answer_0(callid, EOK); 2388 2389 return sess; 2390 } 2391 2392 /** Wrapper for receiving the IPC_M_CONNECT_TO_ME calls. 2393 * 2394 * If the call is IPC_M_CONNECT_TO_ME then a new 2395 * async session is created. However, the phone is 2396 * not accepted automatically. 2397 * 2398 * @param mgmt Exchange management style. 2399 * @param call Call data. 2400 * 2401 * @return New async session. 2402 * @return NULL on failure. 2403 * @return NULL if the call is not IPC_M_CONNECT_TO_ME. 2404 * 2405 */ 2406 async_sess_t *async_callback_receive_start(exch_mgmt_t mgmt, ipc_call_t *call) 2407 { 2408 int phone = (int) IPC_GET_ARG5(*call); 2409 2410 if ((IPC_GET_IMETHOD(*call) != IPC_M_CONNECT_TO_ME) || 2411 (phone < 0)) 2412 return NULL; 2413 2414 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 2415 if (sess == NULL) 2416 return NULL; 2417 2418 sess->mgmt = mgmt; 2419 sess->phone = phone; 2420 sess->arg1 = 0; 2421 sess->arg2 = 0; 2422 sess->arg3 = 0; 2423 2424 list_initialize(&sess->exch_list); 2425 fibril_mutex_initialize(&sess->mutex); 2426 atomic_set(&sess->refcnt, 0); 2427 2428 return sess; 2429 } 2430 1858 2431 /** @} 1859 2432 */
Note:
See TracChangeset
for help on using the changeset viewer.