Changes in uspace/lib/c/generic/async.c [3815efb:c7bbf029] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
r3815efb rc7bbf029 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 of the synchronization 44 * problems. 42 * You should be able to write very simple multithreaded programs, the async 43 * framework will automatically take care of most synchronization problems. 45 44 * 46 45 * Example of use (pseudo C): … … 54 53 * int fibril1(void *arg) 55 54 * { 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 * 55 * conn = async_connect_me_to(); 56 * c1 = async_send(conn); 57 * c2 = async_send(conn); 66 58 * async_wait_for(c1); 67 59 * async_wait_for(c2); … … 102 94 #include <futex.h> 103 95 #include <fibril.h> 96 #include <stdio.h> 104 97 #include <adt/hash_table.h> 105 98 #include <adt/list.h> … … 109 102 #include <arch/barrier.h> 110 103 #include <bool.h> 104 #include <stdlib.h> 111 105 #include <malloc.h> 112 #include <mem.h>113 #include <stdlib.h>114 106 #include "private/async.h" 115 107 116 #define CLIENT_HASH_TABLE_BUCKETS 32117 #define CONN_HASH_TABLE_BUCKETS 32118 119 /** Async framework global futex */120 108 atomic_t async_futex = FUTEX_INITIALIZER; 121 109 … … 123 111 atomic_t threads_in_ipc_wait = { 0 }; 124 112 125 /** Naming service session */ 126 async_sess_t *session_ns; 127 128 /** Call data */ 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 */ 129 129 typedef struct { 130 130 link_t link; 131 132 131 ipc_callid_t callid; 133 132 ipc_call_t call; 134 133 } msg_t; 135 134 136 /* Client connection data */137 135 typedef struct { 136 sysarg_t in_task_hash; 138 137 link_t link; 139 140 sysarg_t in_task_hash; 141 atomic_t refcnt; 138 int refcnt; 142 139 void *data; 143 140 } client_t; 144 141 145 /* Server connection data */146 142 typedef struct { 147 143 awaiter_t wdata; … … 152 148 /** Incoming client task hash. */ 153 149 sysarg_t in_task_hash; 154 155 150 /** Incoming phone hash. */ 156 151 sysarg_t in_phone_hash; … … 160 155 161 156 /** Messages that should be delivered to this fibril. */ 162 li st_t msg_queue;157 link_t msg_queue; 163 158 164 159 /** Identification of the opening call. */ … … 166 161 /** Call data of the opening call. */ 167 162 ipc_call_t call; 168 /** Local argument or NULL if none. */169 void *carg;170 163 171 164 /** Identification of the closing call. */ … … 173 166 174 167 /** Fibril function that will be used to handle the connection. */ 175 async_client_conn_t cfibril;168 void (*cfibril)(ipc_callid_t, ipc_call_t *); 176 169 } connection_t; 177 170 178 171 /** Identifier of the incoming connection handled by the current fibril. */ 179 static fibril_local connection_t * fibril_connection;172 static fibril_local connection_t *FIBRIL_connection; 180 173 181 174 static void *default_client_data_constructor(void) … … 203 196 } 204 197 205 void *async_ get_client_data(void)206 { 207 assert( fibril_connection);208 return fibril_connection->client->data;198 void *async_client_data_get(void) 199 { 200 assert(FIBRIL_connection); 201 return FIBRIL_connection->client->data; 209 202 } 210 203 … … 215 208 * @param callid Hash of the incoming call. 216 209 * @param call Data of the incoming 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) 210 * 211 */ 212 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) 222 213 { 223 214 ipc_answer_0(callid, ENOENT); 224 215 } 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; 225 221 226 222 /** Default fibril function that gets called to handle interrupt notifications. … … 230 226 * @param callid Hash of the incoming call. 231 227 * @param call Data of the incoming call. 232 * @param arg Local argument.233 228 * 234 229 */ … … 237 232 } 238 233 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); 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; 276 239 277 240 static hash_table_t client_hash_table; … … 279 242 static LIST_INITIALIZE(timeout_list); 280 243 244 #define CLIENT_HASH_TABLE_BUCKETS 32 245 #define CONN_HASH_TABLE_BUCKETS 32 246 281 247 static hash_index_t client_hash(unsigned long key[]) 282 248 { 283 249 assert(key); 284 285 250 return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS); 286 251 } … … 288 253 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item) 289 254 { 290 assert(key);291 assert(item);292 293 255 client_t *client = hash_table_get_instance(item, client_t, link); 294 256 return (key[0] == client->in_task_hash); … … 316 278 { 317 279 assert(key); 318 319 280 return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS); 320 281 } … … 331 292 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) 332 293 { 333 assert(key);334 assert(item);335 336 294 connection_t *conn = hash_table_get_instance(item, connection_t, link); 337 295 return (key[0] == conn->in_phone_hash); … … 356 314 void async_insert_timeout(awaiter_t *wd) 357 315 { 358 assert(wd);359 360 316 wd->to_event.occurred = false; 361 317 wd->to_event.inlist = true; 362 318 363 link_t *tmp = timeout_list. head.next;364 while (tmp != &timeout_list .head) {319 link_t *tmp = timeout_list.next; 320 while (tmp != &timeout_list) { 365 321 awaiter_t *cur 366 322 = list_get_instance(tmp, awaiter_t, to_event.link); … … 372 328 } 373 329 374 list_ insert_before(&wd->to_event.link, tmp);330 list_append(&wd->to_event.link, tmp); 375 331 } 376 332 … … 390 346 static bool route_call(ipc_callid_t callid, ipc_call_t *call) 391 347 { 392 assert(call);393 394 348 futex_down(&async_futex); 395 349 … … 446 400 static int notification_fibril(void *arg) 447 401 { 448 assert(arg);449 450 402 msg_t *msg = (msg_t *) arg; 451 403 interrupt_received(msg->callid, &msg->call); … … 468 420 static bool process_notification(ipc_callid_t callid, ipc_call_t *call) 469 421 { 470 assert(call);471 472 422 futex_down(&async_futex); 473 423 … … 508 458 ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) 509 459 { 510 assert(call); 511 assert(fibril_connection); 460 assert(FIBRIL_connection); 512 461 513 462 /* Why doing this? 514 * GCC 4.1.0 coughs on fibril_connection-> dereference.463 * GCC 4.1.0 coughs on FIBRIL_connection-> dereference. 515 464 * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot. 516 465 * I would never expect to find so many errors in 517 466 * a compiler. 518 467 */ 519 connection_t *conn = fibril_connection;468 connection_t *conn = FIBRIL_connection; 520 469 521 470 futex_down(&async_futex); … … 569 518 } 570 519 571 msg_t *msg = list_get_instance( list_first(&conn->msg_queue), msg_t, link);520 msg_t *msg = list_get_instance(conn->msg_queue.next, msg_t, link); 572 521 list_remove(&msg->link); 573 522 … … 592 541 static int connection_fibril(void *arg) 593 542 { 594 assert(arg);595 596 543 /* 597 544 * Setup fibril-local connection pointer. 598 545 */ 599 fibril_connection = (connection_t *) arg;546 FIBRIL_connection = (connection_t *) arg; 600 547 601 548 futex_down(&async_futex); … … 607 554 */ 608 555 609 unsigned long key = fibril_connection->in_task_hash;556 unsigned long key = FIBRIL_connection->in_task_hash; 610 557 link_t *lnk = hash_table_find(&client_hash_table, &key); 611 558 … … 614 561 if (lnk) { 615 562 client = hash_table_get_instance(lnk, client_t, link); 616 atomic_inc(&client->refcnt);563 client->refcnt++; 617 564 } else { 618 565 client = malloc(sizeof(client_t)); 619 566 if (!client) { 620 ipc_answer_0( fibril_connection->callid, ENOMEM);567 ipc_answer_0(FIBRIL_connection->callid, ENOMEM); 621 568 futex_up(&async_futex); 622 569 return 0; 623 570 } 624 571 625 client->in_task_hash = fibril_connection->in_task_hash; 572 client->in_task_hash = FIBRIL_connection->in_task_hash; 573 574 async_serialize_start(); 626 575 client->data = async_client_data_create(); 627 628 atomic_set(&client->refcnt, 1); 576 async_serialize_end(); 577 578 client->refcnt = 1; 629 579 hash_table_insert(&client_hash_table, &key, &client->link); 630 580 } … … 632 582 futex_up(&async_futex); 633 583 634 fibril_connection->client = client;584 FIBRIL_connection->client = client; 635 585 636 586 /* 637 587 * Call the connection handler function. 638 588 */ 639 fibril_connection->cfibril(fibril_connection->callid,640 & fibril_connection->call, fibril_connection->carg);589 FIBRIL_connection->cfibril(FIBRIL_connection->callid, 590 &FIBRIL_connection->call); 641 591 642 592 /* … … 647 597 futex_down(&async_futex); 648 598 649 if ( atomic_predec(&client->refcnt)== 0) {599 if (--client->refcnt == 0) { 650 600 hash_table_remove(&client_hash_table, &key, 1); 651 601 destroy = true; … … 666 616 */ 667 617 futex_down(&async_futex); 668 key = fibril_connection->in_phone_hash;618 key = FIBRIL_connection->in_phone_hash; 669 619 hash_table_remove(&conn_hash_table, &key, 1); 670 620 futex_up(&async_futex); … … 673 623 * Answer all remaining messages with EHANGUP. 674 624 */ 675 while (!list_empty(& fibril_connection->msg_queue)) {625 while (!list_empty(&FIBRIL_connection->msg_queue)) { 676 626 msg_t *msg = 677 list_get_instance( list_first(&fibril_connection->msg_queue),678 msg_t,link);627 list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, 628 link); 679 629 680 630 list_remove(&msg->link); … … 687 637 * i.e. IPC_M_PHONE_HUNGUP. 688 638 */ 689 if ( fibril_connection->close_callid)690 ipc_answer_0( fibril_connection->close_callid, EOK);691 692 free( fibril_connection);639 if (FIBRIL_connection->close_callid) 640 ipc_answer_0(FIBRIL_connection->close_callid, EOK); 641 642 free(FIBRIL_connection); 693 643 return 0; 694 644 } … … 696 646 /** Create a new fibril for a new connection. 697 647 * 698 * Create new fibril for connection, fill in connection structures and insert 648 * Create new fibril for connection, fill in connection structures and inserts 699 649 * it into the hash table, so that later we can easily do routing of messages to 700 650 * particular fibrils. … … 709 659 * @param cfibril Fibril function that should be called upon opening the 710 660 * connection. 711 * @param carg Extra argument to pass to the connection fibril712 661 * 713 662 * @return New fibril id or NULL on failure. … … 716 665 fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash, 717 666 ipc_callid_t callid, ipc_call_t *call, 718 async_client_conn_t cfibril, void *carg)667 void (*cfibril)(ipc_callid_t, ipc_call_t *)) 719 668 { 720 669 connection_t *conn = malloc(sizeof(*conn)); … … 731 680 conn->callid = callid; 732 681 conn->close_callid = 0; 733 conn->carg = carg;734 682 735 683 if (call) … … 773 721 static void handle_call(ipc_callid_t callid, ipc_call_t *call) 774 722 { 775 assert(call);776 777 723 /* Unrouted call - take some default action */ 778 724 if ((callid & IPC_CALLID_NOTIFICATION)) { … … 786 732 /* Open new connection with fibril, etc. */ 787 733 async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call), 788 callid, call, client_connection , NULL);734 callid, call, client_connection); 789 735 return; 790 736 } … … 806 752 futex_down(&async_futex); 807 753 808 link_t *cur = list_first(&timeout_list);809 while (cur != NULL) {754 link_t *cur = timeout_list.next; 755 while (cur != &timeout_list) { 810 756 awaiter_t *waiter = 811 757 list_get_instance(cur, awaiter_t, to_event.link); … … 813 759 if (tv_gt(&waiter->to_event.expires, &tv)) 814 760 break; 761 762 cur = cur->next; 815 763 816 764 list_remove(&waiter->to_event.link); … … 826 774 fibril_add_ready(waiter->fid); 827 775 } 828 829 cur = list_first(&timeout_list);830 776 } 831 777 … … 854 800 suseconds_t timeout; 855 801 if (!list_empty(&timeout_list)) { 856 awaiter_t *waiter = list_get_instance( 857 list_first(&timeout_list),awaiter_t, to_event.link);802 awaiter_t *waiter = list_get_instance(timeout_list.next, 803 awaiter_t, to_event.link); 858 804 859 805 struct timeval tv; … … 932 878 void __async_init(void) 933 879 { 934 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 935 1,&client_hash_table_ops))880 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1, 881 &client_hash_table_ops)) 936 882 abort(); 937 883 938 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 939 1,&conn_hash_table_ops))884 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1, 885 &conn_hash_table_ops)) 940 886 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);955 887 } 956 888 … … 967 899 * 968 900 */ 969 void reply_received(void *arg, int retval, ipc_call_t *data) 970 { 971 assert(arg); 972 901 static void reply_received(void *arg, int retval, ipc_call_t *data) 902 { 973 903 futex_down(&async_futex); 974 904 … … 1000 930 * completion. 1001 931 * 1002 * @param exch Exchange for sending the message.1003 * @param imethod Service-defined interface and method.932 * @param phoneid Handle of the phone that will be used for the send. 933 * @param method Service-defined method. 1004 934 * @param arg1 Service-defined payload argument. 1005 935 * @param arg2 Service-defined payload argument. … … 1012 942 * 1013 943 */ 1014 aid_t async_send_fast( async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,944 aid_t async_send_fast(int phoneid, sysarg_t method, sysarg_t arg1, 1015 945 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 1016 946 { 1017 if (exch == NULL)1018 return 0;1019 1020 947 amsg_t *msg = malloc(sizeof(amsg_t)); 1021 if (msg == NULL) 948 949 if (!msg) 1022 950 return 0; 1023 951 … … 1033 961 msg->wdata.active = true; 1034 962 1035 ipc_call_async_4( exch->phone, imethod, arg1, arg2, arg3, arg4, msg,963 ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg, 1036 964 reply_received, true); 1037 965 … … 1044 972 * completion. 1045 973 * 1046 * @param exch Exchange for sending the message.1047 * @param imethod Service-defined interface and method.974 * @param phoneid Handle of the phone that will be used for the send. 975 * @param method Service-defined method. 1048 976 * @param arg1 Service-defined payload argument. 1049 977 * @param arg2 Service-defined payload argument. … … 1057 985 * 1058 986 */ 1059 aid_t async_send_slow( async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,987 aid_t async_send_slow(int phoneid, sysarg_t method, sysarg_t arg1, 1060 988 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 1061 989 ipc_call_t *dataptr) 1062 990 { 1063 if (exch == NULL)1064 return 0;1065 1066 991 amsg_t *msg = malloc(sizeof(amsg_t)); 1067 992 1068 if ( msg == NULL)993 if (!msg) 1069 994 return 0; 1070 995 … … 1080 1005 msg->wdata.active = true; 1081 1006 1082 ipc_call_async_5( exch->phone, imethod, arg1, arg2, arg3, arg4, arg5,1083 msg,reply_received, true);1007 ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg, 1008 reply_received, true); 1084 1009 1085 1010 return (aid_t) msg; … … 1095 1020 void async_wait_for(aid_t amsgid, sysarg_t *retval) 1096 1021 { 1097 assert(amsgid);1098 1099 1022 amsg_t *msg = (amsg_t *) amsgid; 1100 1023 … … 1133 1056 int async_wait_timeout(aid_t amsgid, sysarg_t *retval, suseconds_t timeout) 1134 1057 { 1135 assert(amsgid);1136 1137 1058 amsg_t *msg = (amsg_t *) amsgid; 1138 1059 … … 1203 1124 } 1204 1125 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 interrupt 1139 * notification fibril. 1140 */ 1141 void async_set_interrupt_received(async_client_conn_t intr) 1142 { 1143 interrupt_received = intr; 1144 } 1145 1205 1146 /** Pseudo-synchronous message sending - fast version. 1206 1147 * … … 1210 1151 * transferring more arguments, see the slower async_req_slow(). 1211 1152 * 1212 * @param exch Exchange for sending the message.1213 * @param imethod Interface and method of the call.1153 * @param phoneid Hash of the phone through which to make the call. 1154 * @param method Method of the call. 1214 1155 * @param arg1 Service-defined payload argument. 1215 1156 * @param arg2 Service-defined payload argument. … … 1225 1166 * 1226 1167 */ 1227 sysarg_t async_req_fast( async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,1168 sysarg_t async_req_fast(int phoneid, sysarg_t method, sysarg_t arg1, 1228 1169 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2, 1229 1170 sysarg_t *r3, sysarg_t *r4, sysarg_t *r5) 1230 1171 { 1231 if (exch == NULL)1232 return ENOENT;1233 1234 1172 ipc_call_t result; 1235 aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4,1173 aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4, 1236 1174 &result); 1237 1175 1238 1176 sysarg_t rc; 1239 async_wait_for( aid, &rc);1177 async_wait_for(eid, &rc); 1240 1178 1241 1179 if (r1) … … 1261 1199 * Send message asynchronously and return only after the reply arrives. 1262 1200 * 1263 * @param exch Exchange for sending the message.1264 * @param imethod Interface and method of the call.1201 * @param phoneid Hash of the phone through which to make the call. 1202 * @param method Method of the call. 1265 1203 * @param arg1 Service-defined payload argument. 1266 1204 * @param arg2 Service-defined payload argument. … … 1277 1215 * 1278 1216 */ 1279 sysarg_t async_req_slow( async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,1217 sysarg_t async_req_slow(int phoneid, sysarg_t method, sysarg_t arg1, 1280 1218 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1, 1281 1219 sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5) 1282 1220 { 1283 if (exch == NULL)1284 return ENOENT;1285 1286 1221 ipc_call_t result; 1287 aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5,1222 aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, 1288 1223 &result); 1289 1224 1290 1225 sysarg_t rc; 1291 async_wait_for( aid, &rc);1226 async_wait_for(eid, &rc); 1292 1227 1293 1228 if (r1) … … 1309 1244 } 1310 1245 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); 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); 1353 1279 } 1354 1280 … … 1387 1313 } 1388 1314 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); 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); 1407 1327 } 1408 1328 … … 1411 1331 * Ask through phone for a new connection to some service. 1412 1332 * 1413 * @param exch Exchange for sending the message.1333 * @param phone Phone handle used for contacting the other side. 1414 1334 * @param arg1 User defined argument. 1415 1335 * @param arg2 User defined argument. … … 1417 1337 * @param client_receiver Connection handing routine. 1418 1338 * 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 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 { 1428 1345 sysarg_t task_hash; 1429 1346 sysarg_t phone_hash; 1430 int rc = async_req_3_5( exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,1347 int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 1431 1348 NULL, NULL, NULL, &task_hash, &phone_hash); 1432 1349 if (rc != EOK) … … 1435 1352 if (client_receiver != NULL) 1436 1353 async_new_connection(task_hash, phone_hash, 0, NULL, 1437 client_receiver , carg);1354 client_receiver); 1438 1355 1439 1356 return EOK; 1440 1357 } 1441 1358 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); 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); 1543 1377 1544 1378 if (rc != EOK) 1545 1379 return rc; 1546 1380 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; 1381 return newphid; 1597 1382 } 1598 1383 … … 1602 1387 * success. 1603 1388 * 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; 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; 1647 1408 } 1648 1409 … … 1650 1411 * 1651 1412 */ 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) 1413 int async_connect_kbox(task_id_t id) 1414 { 1415 return ipc_connect_kbox(id); 1416 } 1417 1418 /** Wrapper for ipc_hangup. 1419 * 1420 * @param phone Phone handle to hung up. 1421 * 1422 * @return Zero on success or a negative error code. 1423 * 1424 */ 1425 int async_hangup(int phone) 1681 1426 { 1682 1427 return ipc_hangup(phone); 1683 }1684 1685 /** Wrapper for ipc_hangup.1686 *1687 * @param sess Session to hung up.1688 *1689 * @return Zero on success or a negative error code.1690 *1691 */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;1704 1428 } 1705 1429 … … 1710 1434 } 1711 1435 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 } else1770 async_hangup_internal(phone);1771 } else if (!list_empty(&inactive_exch_list)) {1772 /*1773 * We did not manage to connect a new phone. But we1774 * can try to close some of the currently inactive1775 * 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 1834 1436 /** Wrapper for IPC_M_SHARE_IN calls using the async framework. 1835 1437 * 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.1438 * @param phoneid Phone that will be used to contact the receiving side. 1439 * @param dst Destination address space area base. 1440 * @param size Size of the destination address space area. 1441 * @param arg User defined argument. 1442 * @param flags Storage for the received flags. Can be NULL. 1841 1443 * 1842 1444 * @return Zero on success or a negative error code from errno.h. 1843 1445 * 1844 1446 */ 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 1447 int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg, 1448 unsigned int *flags) 1449 { 1851 1450 sysarg_t tmp_flags; 1852 int res = async_req_3_2( exch, IPC_M_SHARE_IN, (sysarg_t) dst,1451 int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst, 1853 1452 (sysarg_t) size, arg, NULL, &tmp_flags); 1854 1453 … … 1908 1507 /** Wrapper for IPC_M_SHARE_OUT calls using the async framework. 1909 1508 * 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.1509 * @param phoneid Phone that will be used to contact the receiving side. 1510 * @param src Source address space area base address. 1511 * @param flags Flags to be used for sharing. Bits can be only cleared. 1913 1512 * 1914 1513 * @return Zero on success or a negative error code from errno.h. 1915 1514 * 1916 1515 */ 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, 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, 1923 1519 (sysarg_t) flags); 1924 1520 } … … 1973 1569 } 1974 1570 1975 /** Start IPC_M_DATA_READusing the async framework.1976 * 1977 * @param exch Exchange for sending the message.1571 /** Wrapper for IPC_M_DATA_READ calls using the async framework. 1572 * 1573 * @param phoneid Phone that will be used to contact the receiving side. 1978 1574 * @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 1992 /** Wrapper for IPC_M_DATA_READ calls using the async framework. 1993 * 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. 1575 * @param size Size of the destination buffer. 1576 * @param flags Flags to control the data transfer. 1997 1577 * 1998 1578 * @return Zero on success or a negative error code from errno.h. 1999 1579 * 2000 1580 */ 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); 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); 2008 1586 } 2009 1587 … … 2060 1638 * 2061 1639 */ 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 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 { 2069 1643 ipc_callid_t callid; 2070 1644 if (!async_data_read_receive(&callid, NULL)) { … … 2073 1647 } 2074 1648 2075 aid_t msg = async_send_fast( exch, imethod, arg1, arg2, arg3, arg4,1649 aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4, 2076 1650 dataptr); 2077 1651 if (msg == 0) { … … 2080 1654 } 2081 1655 2082 int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,1656 int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0, 2083 1657 IPC_FF_ROUTE_FROM_ME); 2084 1658 if (retval != EOK) { … … 2096 1670 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework. 2097 1671 * 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. 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. 2101 1676 * 2102 1677 * @return Zero on success or a negative error code from errno.h. 2103 1678 * 2104 1679 */ 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); 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); 2112 1686 } 2113 1687 … … 2185 1759 size_t *received) 2186 1760 { 2187 assert(data);2188 2189 1761 ipc_callid_t callid; 2190 1762 size_t size; … … 2254 1826 * 2255 1827 */ 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 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 { 2263 1831 ipc_callid_t callid; 2264 1832 if (!async_data_write_receive(&callid, NULL)) { … … 2267 1835 } 2268 1836 2269 aid_t msg = async_send_fast( exch, imethod, arg1, arg2, arg3, arg4,1837 aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4, 2270 1838 dataptr); 2271 1839 if (msg == 0) { … … 2274 1842 } 2275 1843 2276 int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,1844 int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0, 2277 1845 IPC_FF_ROUTE_FROM_ME); 2278 1846 if (retval != EOK) { … … 2288 1856 } 2289 1857 2290 /** Wrapper for sending an exchange over different exchange for cloning2291 *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 new2304 * 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 new2349 * 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 new2395 * async session is created. However, the phone is2396 * 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 2431 1858 /** @} 2432 1859 */
Note:
See TracChangeset
for help on using the changeset viewer.