Changeset 41811af in mainline for uspace/lib/c/generic/async.c
- Timestamp:
- 2011-06-10T10:14:26Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ab547063
- Parents:
- 9536e6e (diff), 390d80d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
r9536e6e r41811af 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; … … 170 175 171 176 /** Identifier of the incoming connection handled by the current fibril. */ 172 static fibril_local connection_t * FIBRIL_connection;177 static fibril_local connection_t *fibril_connection; 173 178 174 179 static void *default_client_data_constructor(void) … … 196 201 } 197 202 198 void *async_ client_data_get(void)199 { 200 assert( FIBRIL_connection);201 return FIBRIL_connection->client->data;203 void *async_get_client_data(void) 204 { 205 assert(fibril_connection); 206 return fibril_connection->client->data; 202 207 } 203 208 … … 215 220 } 216 221 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 222 222 /** Default fibril function that gets called to handle interrupt notifications. 223 223 * … … 232 232 } 233 233 234 /** 235 * Pointer to a fibril function that will be used to handle interrupt 236 * notifications. 237 */ 234 static async_client_conn_t client_connection = default_client_connection; 238 235 static async_client_conn_t interrupt_received = default_interrupt_received; 236 237 /** Setter for client_connection function pointer. 238 * 239 * @param conn Function that will implement a new connection fibril. 240 * 241 */ 242 void async_set_client_connection(async_client_conn_t conn) 243 { 244 client_connection = conn; 245 } 246 247 /** Setter for interrupt_received function pointer. 248 * 249 * @param intr Function that will implement a new interrupt 250 * notification fibril. 251 */ 252 void async_set_interrupt_received(async_client_conn_t intr) 253 { 254 interrupt_received = intr; 255 } 256 257 /** Mutex protecting inactive_exch_list and avail_phone_cv. 258 * 259 */ 260 static FIBRIL_MUTEX_INITIALIZE(async_sess_mutex); 261 262 /** List of all currently inactive exchanges. 263 * 264 */ 265 static LIST_INITIALIZE(inactive_exch_list); 266 267 /** Condition variable to wait for a phone to become available. 268 * 269 */ 270 static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv); 239 271 240 272 static hash_table_t client_hash_table; … … 242 274 static LIST_INITIALIZE(timeout_list); 243 275 244 #define CLIENT_HASH_TABLE_BUCKETS 32245 #define CONN_HASH_TABLE_BUCKETS 32246 247 276 static hash_index_t client_hash(unsigned long key[]) 248 277 { 249 278 assert(key); 279 250 280 return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS); 251 281 } … … 253 283 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item) 254 284 { 285 assert(key); 286 assert(item); 287 255 288 client_t *client = hash_table_get_instance(item, client_t, link); 256 289 return (key[0] == client->in_task_hash); … … 278 311 { 279 312 assert(key); 313 280 314 return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS); 281 315 } … … 292 326 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) 293 327 { 328 assert(key); 329 assert(item); 330 294 331 connection_t *conn = hash_table_get_instance(item, connection_t, link); 295 332 return (key[0] == conn->in_phone_hash); … … 314 351 void async_insert_timeout(awaiter_t *wd) 315 352 { 353 assert(wd); 354 316 355 wd->to_event.occurred = false; 317 356 wd->to_event.inlist = true; … … 346 385 static bool route_call(ipc_callid_t callid, ipc_call_t *call) 347 386 { 387 assert(call); 388 348 389 futex_down(&async_futex); 349 390 … … 400 441 static int notification_fibril(void *arg) 401 442 { 443 assert(arg); 444 402 445 msg_t *msg = (msg_t *) arg; 403 446 interrupt_received(msg->callid, &msg->call); … … 420 463 static bool process_notification(ipc_callid_t callid, ipc_call_t *call) 421 464 { 465 assert(call); 466 422 467 futex_down(&async_futex); 423 468 … … 458 503 ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) 459 504 { 460 assert(FIBRIL_connection); 505 assert(call); 506 assert(fibril_connection); 461 507 462 508 /* Why doing this? 463 * GCC 4.1.0 coughs on FIBRIL_connection-> dereference.509 * GCC 4.1.0 coughs on fibril_connection-> dereference. 464 510 * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot. 465 511 * I would never expect to find so many errors in 466 512 * a compiler. 467 513 */ 468 connection_t *conn = FIBRIL_connection;514 connection_t *conn = fibril_connection; 469 515 470 516 futex_down(&async_futex); … … 541 587 static int connection_fibril(void *arg) 542 588 { 589 assert(arg); 590 543 591 /* 544 592 * Setup fibril-local connection pointer. 545 593 */ 546 FIBRIL_connection = (connection_t *) arg;594 fibril_connection = (connection_t *) arg; 547 595 548 596 futex_down(&async_futex); … … 554 602 */ 555 603 556 unsigned long key = FIBRIL_connection->in_task_hash;604 unsigned long key = fibril_connection->in_task_hash; 557 605 link_t *lnk = hash_table_find(&client_hash_table, &key); 558 606 … … 561 609 if (lnk) { 562 610 client = hash_table_get_instance(lnk, client_t, link); 563 client->refcnt++;611 atomic_inc(&client->refcnt); 564 612 } else { 565 613 client = malloc(sizeof(client_t)); 566 614 if (!client) { 567 ipc_answer_0( FIBRIL_connection->callid, ENOMEM);615 ipc_answer_0(fibril_connection->callid, ENOMEM); 568 616 futex_up(&async_futex); 569 617 return 0; 570 618 } 571 619 572 client->in_task_hash = FIBRIL_connection->in_task_hash; 573 574 async_serialize_start(); 620 client->in_task_hash = fibril_connection->in_task_hash; 575 621 client->data = async_client_data_create(); 576 async_serialize_end(); 577 578 client->refcnt = 1; 622 623 atomic_set(&client->refcnt, 1); 579 624 hash_table_insert(&client_hash_table, &key, &client->link); 580 625 } … … 582 627 futex_up(&async_futex); 583 628 584 FIBRIL_connection->client = client;629 fibril_connection->client = client; 585 630 586 631 /* 587 632 * Call the connection handler function. 588 633 */ 589 FIBRIL_connection->cfibril(FIBRIL_connection->callid,590 & FIBRIL_connection->call);634 fibril_connection->cfibril(fibril_connection->callid, 635 &fibril_connection->call); 591 636 592 637 /* … … 597 642 futex_down(&async_futex); 598 643 599 if ( --client->refcnt== 0) {644 if (atomic_predec(&client->refcnt) == 0) { 600 645 hash_table_remove(&client_hash_table, &key, 1); 601 646 destroy = true; … … 616 661 */ 617 662 futex_down(&async_futex); 618 key = FIBRIL_connection->in_phone_hash;663 key = fibril_connection->in_phone_hash; 619 664 hash_table_remove(&conn_hash_table, &key, 1); 620 665 futex_up(&async_futex); … … 623 668 * Answer all remaining messages with EHANGUP. 624 669 */ 625 while (!list_empty(& FIBRIL_connection->msg_queue)) {670 while (!list_empty(&fibril_connection->msg_queue)) { 626 671 msg_t *msg = 627 list_get_instance( FIBRIL_connection->msg_queue.next, msg_t,672 list_get_instance(fibril_connection->msg_queue.next, msg_t, 628 673 link); 629 674 … … 637 682 * i.e. IPC_M_PHONE_HUNGUP. 638 683 */ 639 if ( FIBRIL_connection->close_callid)640 ipc_answer_0( FIBRIL_connection->close_callid, EOK);641 642 free( FIBRIL_connection);684 if (fibril_connection->close_callid) 685 ipc_answer_0(fibril_connection->close_callid, EOK); 686 687 free(fibril_connection); 643 688 return 0; 644 689 } … … 646 691 /** Create a new fibril for a new connection. 647 692 * 648 * Create new fibril for connection, fill in connection structures and insert s693 * Create new fibril for connection, fill in connection structures and insert 649 694 * it into the hash table, so that later we can easily do routing of messages to 650 695 * particular fibrils. … … 665 710 fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash, 666 711 ipc_callid_t callid, ipc_call_t *call, 667 void (*cfibril)(ipc_callid_t, ipc_call_t *))712 async_client_conn_t cfibril) 668 713 { 669 714 connection_t *conn = malloc(sizeof(*conn)); … … 721 766 static void handle_call(ipc_callid_t callid, ipc_call_t *call) 722 767 { 768 assert(call); 769 723 770 /* Unrouted call - take some default action */ 724 771 if ((callid & IPC_CALLID_NOTIFICATION)) { … … 878 925 void __async_init(void) 879 926 { 880 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,881 &client_hash_table_ops))927 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 928 1, &client_hash_table_ops)) 882 929 abort(); 883 930 884 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1,885 &conn_hash_table_ops))931 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 932 1, &conn_hash_table_ops)) 886 933 abort(); 934 935 session_ns = (async_sess_t *) malloc(sizeof(async_sess_t)); 936 if (session_ns == NULL) 937 abort(); 938 939 session_ns->mgmt = EXCHANGE_ATOMIC; 940 session_ns->phone = PHONE_NS; 941 session_ns->arg1 = 0; 942 session_ns->arg2 = 0; 943 session_ns->arg3 = 0; 944 945 list_initialize(&session_ns->exch_list); 946 fibril_mutex_initialize(&session_ns->mutex); 947 atomic_set(&session_ns->refcnt, 0); 887 948 } 888 949 … … 899 960 * 900 961 */ 901 static void reply_received(void *arg, int retval, ipc_call_t *data) 902 { 962 void reply_received(void *arg, int retval, ipc_call_t *data) 963 { 964 assert(arg); 965 903 966 futex_down(&async_futex); 904 967 … … 930 993 * completion. 931 994 * 932 * @param phoneid Handle of the phone that will be used for the send.933 * @param method Service-defined method.995 * @param exch Exchange for sending the message. 996 * @param imethod Service-defined interface and method. 934 997 * @param arg1 Service-defined payload argument. 935 998 * @param arg2 Service-defined payload argument. … … 942 1005 * 943 1006 */ 944 aid_t async_send_fast( int phoneid, sysarg_tmethod, sysarg_t arg1,1007 aid_t async_send_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 945 1008 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 946 1009 { 1010 if (exch == NULL) 1011 return 0; 1012 947 1013 amsg_t *msg = malloc(sizeof(amsg_t)); 948 949 if (!msg) 1014 if (msg == NULL) 950 1015 return 0; 951 1016 … … 961 1026 msg->wdata.active = true; 962 1027 963 ipc_call_async_4( phoneid,method, arg1, arg2, arg3, arg4, msg,1028 ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, msg, 964 1029 reply_received, true); 965 1030 … … 972 1037 * completion. 973 1038 * 974 * @param phoneid Handle of the phone that will be used for the send.975 * @param method Service-defined method.1039 * @param exch Exchange for sending the message. 1040 * @param imethod Service-defined interface and method. 976 1041 * @param arg1 Service-defined payload argument. 977 1042 * @param arg2 Service-defined payload argument. … … 985 1050 * 986 1051 */ 987 aid_t async_send_slow( int phoneid, sysarg_tmethod, sysarg_t arg1,1052 aid_t async_send_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 988 1053 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 989 1054 ipc_call_t *dataptr) 990 1055 { 1056 if (exch == NULL) 1057 return 0; 1058 991 1059 amsg_t *msg = malloc(sizeof(amsg_t)); 992 1060 993 if ( !msg)1061 if (msg == NULL) 994 1062 return 0; 995 1063 … … 1005 1073 msg->wdata.active = true; 1006 1074 1007 ipc_call_async_5( phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,1008 reply_received, true);1075 ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, arg5, 1076 msg, reply_received, true); 1009 1077 1010 1078 return (aid_t) msg; … … 1020 1088 void async_wait_for(aid_t amsgid, sysarg_t *retval) 1021 1089 { 1090 assert(amsgid); 1091 1022 1092 amsg_t *msg = (amsg_t *) amsgid; 1023 1093 … … 1056 1126 int async_wait_timeout(aid_t amsgid, sysarg_t *retval, suseconds_t timeout) 1057 1127 { 1128 assert(amsgid); 1129 1058 1130 amsg_t *msg = (amsg_t *) amsgid; 1059 1131 … … 1124 1196 } 1125 1197 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 1198 /** Pseudo-synchronous message sending - fast version. 1147 1199 * … … 1151 1203 * transferring more arguments, see the slower async_req_slow(). 1152 1204 * 1153 * @param phoneid Hash of the phone through which to make the call.1154 * @param method Method of the call.1205 * @param exch Exchange for sending the message. 1206 * @param imethod Interface and method of the call. 1155 1207 * @param arg1 Service-defined payload argument. 1156 1208 * @param arg2 Service-defined payload argument. … … 1166 1218 * 1167 1219 */ 1168 sysarg_t async_req_fast( int phoneid, sysarg_tmethod, sysarg_t arg1,1220 sysarg_t async_req_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1169 1221 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2, 1170 1222 sysarg_t *r3, sysarg_t *r4, sysarg_t *r5) 1171 1223 { 1224 if (exch == NULL) 1225 return ENOENT; 1226 1172 1227 ipc_call_t result; 1173 aid_t eid = async_send_4(phoneid,method, arg1, arg2, arg3, arg4,1228 aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4, 1174 1229 &result); 1175 1230 1176 1231 sysarg_t rc; 1177 async_wait_for( eid, &rc);1232 async_wait_for(aid, &rc); 1178 1233 1179 1234 if (r1) … … 1199 1254 * Send message asynchronously and return only after the reply arrives. 1200 1255 * 1201 * @param phoneid Hash of the phone through which to make the call.1202 * @param method Method of the call.1256 * @param exch Exchange for sending the message. 1257 * @param imethod Interface and method of the call. 1203 1258 * @param arg1 Service-defined payload argument. 1204 1259 * @param arg2 Service-defined payload argument. … … 1215 1270 * 1216 1271 */ 1217 sysarg_t async_req_slow( int phoneid, sysarg_tmethod, sysarg_t arg1,1272 sysarg_t async_req_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1218 1273 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1, 1219 1274 sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5) 1220 1275 { 1276 if (exch == NULL) 1277 return ENOENT; 1278 1221 1279 ipc_call_t result; 1222 aid_t eid = async_send_5(phoneid,method, arg1, arg2, arg3, arg4, arg5,1280 aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5, 1223 1281 &result); 1224 1282 1225 1283 sysarg_t rc; 1226 async_wait_for( eid, &rc);1284 async_wait_for(aid, &rc); 1227 1285 1228 1286 if (r1) … … 1244 1302 } 1245 1303 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); 1304 void async_msg_0(async_exch_t *exch, sysarg_t imethod) 1305 { 1306 if (exch != NULL) 1307 ipc_call_async_0(exch->phone, imethod, NULL, NULL, true); 1308 } 1309 1310 void async_msg_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1) 1311 { 1312 if (exch != NULL) 1313 ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL, true); 1314 } 1315 1316 void async_msg_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1317 sysarg_t arg2) 1318 { 1319 if (exch != NULL) 1320 ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL, 1321 true); 1322 } 1323 1324 void async_msg_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1325 sysarg_t arg2, sysarg_t arg3) 1326 { 1327 if (exch != NULL) 1328 ipc_call_async_3(exch->phone, imethod, arg1, arg2, arg3, NULL, 1329 NULL, true); 1330 } 1331 1332 void async_msg_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1333 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4) 1334 { 1335 if (exch != NULL) 1336 ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, 1337 NULL, NULL, true); 1338 } 1339 1340 void async_msg_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1, 1341 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 1342 { 1343 if (exch != NULL) 1344 ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, 1345 arg5, NULL, NULL, true); 1279 1346 } 1280 1347 … … 1313 1380 } 1314 1381 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); 1382 int async_forward_fast(ipc_callid_t callid, async_exch_t *exch, 1383 sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode) 1384 { 1385 if (exch == NULL) 1386 return ENOENT; 1387 1388 return ipc_forward_fast(callid, exch->phone, imethod, arg1, arg2, mode); 1389 } 1390 1391 int async_forward_slow(ipc_callid_t callid, async_exch_t *exch, 1392 sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, 1393 sysarg_t arg4, sysarg_t arg5, unsigned int mode) 1394 { 1395 if (exch == NULL) 1396 return ENOENT; 1397 1398 return ipc_forward_slow(callid, exch->phone, imethod, arg1, arg2, arg3, 1399 arg4, arg5, mode); 1327 1400 } 1328 1401 … … 1331 1404 * Ask through phone for a new connection to some service. 1332 1405 * 1333 * @param phone Phone handle used for contacting the other side.1406 * @param exch Exchange for sending the message. 1334 1407 * @param arg1 User defined argument. 1335 1408 * @param arg2 User defined argument. … … 1337 1410 * @param client_receiver Connection handing routine. 1338 1411 * 1339 * @return New phone handleon success or a negative error code.1340 * 1341 */ 1342 int async_connect_to_me( int phone, sysarg_t arg1, sysarg_t arg2,1412 * @return Zero on success or a negative error code. 1413 * 1414 */ 1415 int async_connect_to_me(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2, 1343 1416 sysarg_t arg3, async_client_conn_t client_receiver) 1344 1417 { 1418 if (exch == NULL) 1419 return ENOENT; 1420 1345 1421 sysarg_t task_hash; 1346 1422 sysarg_t phone_hash; 1347 int rc = async_req_3_5( phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,1423 int rc = async_req_3_5(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 1348 1424 NULL, NULL, NULL, &task_hash, &phone_hash); 1349 1425 if (rc != EOK) … … 1357 1433 } 1358 1434 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); 1435 /** Wrapper for making IPC_M_CONNECT_ME calls using the async framework. 1436 * 1437 * Ask through for a cloned connection to some service. 1438 * 1439 * @param mgmt Exchange management style. 1440 * @param exch Exchange for sending the message. 1441 * 1442 * @return New session on success or NULL on error. 1443 * 1444 */ 1445 async_sess_t *async_connect_me(exch_mgmt_t mgmt, async_exch_t *exch) 1446 { 1447 if (exch == NULL) { 1448 errno = ENOENT; 1449 return NULL; 1450 } 1451 1452 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 1453 if (sess == NULL) { 1454 errno = ENOMEM; 1455 return NULL; 1456 } 1457 1458 ipc_call_t result; 1459 1460 amsg_t *msg = malloc(sizeof(amsg_t)); 1461 if (msg == NULL) { 1462 free(sess); 1463 errno = ENOMEM; 1464 return NULL; 1465 } 1466 1467 msg->done = false; 1468 msg->dataptr = &result; 1469 1470 msg->wdata.to_event.inlist = false; 1471 1472 /* 1473 * We may sleep in the next method, 1474 * but it will use its own means 1475 */ 1476 msg->wdata.active = true; 1477 1478 ipc_call_async_0(exch->phone, IPC_M_CONNECT_ME, msg, 1479 reply_received, true); 1480 1481 sysarg_t rc; 1482 async_wait_for((aid_t) msg, &rc); 1483 1484 if (rc != EOK) { 1485 errno = rc; 1486 free(sess); 1487 return NULL; 1488 } 1489 1490 int phone = (int) IPC_GET_ARG5(result); 1491 1492 if (phone < 0) { 1493 errno = phone; 1494 free(sess); 1495 return NULL; 1496 } 1497 1498 sess->mgmt = mgmt; 1499 sess->phone = phone; 1500 sess->arg1 = 0; 1501 sess->arg2 = 0; 1502 sess->arg3 = 0; 1503 1504 list_initialize(&sess->exch_list); 1505 fibril_mutex_initialize(&sess->mutex); 1506 atomic_set(&sess->refcnt, 0); 1507 1508 return sess; 1509 } 1510 1511 static int async_connect_me_to_internal(int phone, sysarg_t arg1, sysarg_t arg2, 1512 sysarg_t arg3, sysarg_t arg4) 1513 { 1514 ipc_call_t result; 1515 1516 amsg_t *msg = malloc(sizeof(amsg_t)); 1517 if (msg == NULL) 1518 return ENOENT; 1519 1520 msg->done = false; 1521 msg->dataptr = &result; 1522 1523 msg->wdata.to_event.inlist = false; 1524 1525 /* 1526 * We may sleep in the next method, 1527 * but it will use its own means 1528 */ 1529 msg->wdata.active = true; 1530 1531 ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, arg4, 1532 msg, reply_received, true); 1533 1534 sysarg_t rc; 1535 async_wait_for((aid_t) msg, &rc); 1377 1536 1378 1537 if (rc != EOK) 1379 1538 return rc; 1380 1539 1381 return newphid; 1540 return (int) IPC_GET_ARG5(result); 1541 } 1542 1543 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1544 * 1545 * Ask through for a new connection to some service. 1546 * 1547 * @param mgmt Exchange management style. 1548 * @param exch Exchange for sending the message. 1549 * @param arg1 User defined argument. 1550 * @param arg2 User defined argument. 1551 * @param arg3 User defined argument. 1552 * 1553 * @return New session on success or NULL on error. 1554 * 1555 */ 1556 async_sess_t *async_connect_me_to(exch_mgmt_t mgmt, async_exch_t *exch, 1557 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) 1558 { 1559 if (exch == NULL) { 1560 errno = ENOENT; 1561 return NULL; 1562 } 1563 1564 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 1565 if (sess == NULL) { 1566 errno = ENOMEM; 1567 return NULL; 1568 } 1569 1570 int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3, 1571 0); 1572 1573 if (phone < 0) { 1574 errno = phone; 1575 free(sess); 1576 return NULL; 1577 } 1578 1579 sess->mgmt = mgmt; 1580 sess->phone = phone; 1581 sess->arg1 = arg1; 1582 sess->arg2 = arg2; 1583 sess->arg3 = arg3; 1584 1585 list_initialize(&sess->exch_list); 1586 fibril_mutex_initialize(&sess->mutex); 1587 atomic_set(&sess->refcnt, 0); 1588 1589 return sess; 1382 1590 } 1383 1591 … … 1387 1595 * success. 1388 1596 * 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; 1597 * @param mgmt Exchange management style. 1598 * @param exch Exchange for sending the message. 1599 * @param arg1 User defined argument. 1600 * @param arg2 User defined argument. 1601 * @param arg3 User defined argument. 1602 * 1603 * @return New session on success or NULL on error. 1604 * 1605 */ 1606 async_sess_t *async_connect_me_to_blocking(exch_mgmt_t mgmt, async_exch_t *exch, 1607 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) 1608 { 1609 if (exch == NULL) { 1610 errno = ENOENT; 1611 return NULL; 1612 } 1613 1614 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 1615 if (sess == NULL) { 1616 errno = ENOMEM; 1617 return NULL; 1618 } 1619 1620 int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3, 1621 IPC_FLAG_BLOCKING); 1622 1623 if (phone < 0) { 1624 errno = phone; 1625 free(sess); 1626 return NULL; 1627 } 1628 1629 sess->mgmt = mgmt; 1630 sess->phone = phone; 1631 sess->arg1 = arg1; 1632 sess->arg2 = arg2; 1633 sess->arg3 = arg3; 1634 1635 list_initialize(&sess->exch_list); 1636 fibril_mutex_initialize(&sess->mutex); 1637 atomic_set(&sess->refcnt, 0); 1638 1639 return sess; 1408 1640 } 1409 1641 … … 1411 1643 * 1412 1644 */ 1413 int async_connect_kbox(task_id_t id) 1414 { 1415 return ipc_connect_kbox(id); 1645 async_sess_t *async_connect_kbox(task_id_t id) 1646 { 1647 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 1648 if (sess == NULL) { 1649 errno = ENOMEM; 1650 return NULL; 1651 } 1652 1653 int phone = ipc_connect_kbox(id); 1654 if (phone < 0) { 1655 errno = phone; 1656 free(sess); 1657 return NULL; 1658 } 1659 1660 sess->mgmt = EXCHANGE_ATOMIC; 1661 sess->phone = phone; 1662 sess->arg1 = 0; 1663 sess->arg2 = 0; 1664 sess->arg3 = 0; 1665 1666 list_initialize(&sess->exch_list); 1667 fibril_mutex_initialize(&sess->mutex); 1668 atomic_set(&sess->refcnt, 0); 1669 1670 return sess; 1671 } 1672 1673 static int async_hangup_internal(int phone) 1674 { 1675 return ipc_hangup(phone); 1416 1676 } 1417 1677 1418 1678 /** Wrapper for ipc_hangup. 1419 1679 * 1420 * @param phone Phone handleto hung up.1680 * @param sess Session to hung up. 1421 1681 * 1422 1682 * @return Zero on success or a negative error code. 1423 1683 * 1424 1684 */ 1425 int async_hangup(int phone) 1426 { 1427 return ipc_hangup(phone); 1685 int async_hangup(async_sess_t *sess) 1686 { 1687 assert(sess); 1688 1689 if (atomic_get(&sess->refcnt) > 0) 1690 return EBUSY; 1691 1692 int rc = async_hangup_internal(sess->phone); 1693 if (rc == EOK) 1694 free(sess); 1695 1696 return rc; 1428 1697 } 1429 1698 … … 1434 1703 } 1435 1704 1705 /** Start new exchange in a session. 1706 * 1707 * @param session Session. 1708 * 1709 * @return New exchange or NULL on error. 1710 * 1711 */ 1712 async_exch_t *async_exchange_begin(async_sess_t *sess) 1713 { 1714 if (sess == NULL) 1715 return NULL; 1716 1717 async_exch_t *exch; 1718 1719 fibril_mutex_lock(&async_sess_mutex); 1720 1721 if (!list_empty(&sess->exch_list)) { 1722 /* 1723 * There are inactive exchanges in the session. 1724 */ 1725 exch = (async_exch_t *) 1726 list_get_instance(sess->exch_list.next, async_exch_t, sess_link); 1727 list_remove(&exch->sess_link); 1728 list_remove(&exch->global_link); 1729 } else { 1730 /* 1731 * There are no available exchanges in the session. 1732 */ 1733 1734 if ((sess->mgmt == EXCHANGE_ATOMIC) || 1735 (sess->mgmt == EXCHANGE_SERIALIZE)) { 1736 exch = (async_exch_t *) malloc(sizeof(async_exch_t)); 1737 if (exch != NULL) { 1738 list_initialize(&exch->sess_link); 1739 list_initialize(&exch->global_link); 1740 exch->sess = sess; 1741 exch->phone = sess->phone; 1742 } 1743 } else { /* EXCHANGE_PARALLEL */ 1744 /* 1745 * Make a one-time attempt to connect a new data phone. 1746 */ 1747 1748 int phone; 1749 1750 retry: 1751 phone = async_connect_me_to_internal(sess->phone, sess->arg1, 1752 sess->arg2, sess->arg3, 0); 1753 if (phone >= 0) { 1754 exch = (async_exch_t *) malloc(sizeof(async_exch_t)); 1755 if (exch != NULL) { 1756 list_initialize(&exch->sess_link); 1757 list_initialize(&exch->global_link); 1758 exch->sess = sess; 1759 exch->phone = phone; 1760 } else 1761 async_hangup_internal(phone); 1762 } else if (!list_empty(&inactive_exch_list)) { 1763 /* 1764 * We did not manage to connect a new phone. But we 1765 * can try to close some of the currently inactive 1766 * connections in other sessions and try again. 1767 */ 1768 exch = (async_exch_t *) 1769 list_get_instance(inactive_exch_list.next, async_exch_t, 1770 global_link); 1771 list_remove(&exch->sess_link); 1772 list_remove(&exch->global_link); 1773 async_hangup_internal(exch->phone); 1774 free(exch); 1775 goto retry; 1776 } else { 1777 /* 1778 * Wait for a phone to become available. 1779 */ 1780 fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex); 1781 goto retry; 1782 } 1783 } 1784 } 1785 1786 fibril_mutex_unlock(&async_sess_mutex); 1787 1788 if (exch != NULL) { 1789 atomic_inc(&sess->refcnt); 1790 1791 if (sess->mgmt == EXCHANGE_SERIALIZE) 1792 fibril_mutex_lock(&sess->mutex); 1793 } 1794 1795 return exch; 1796 } 1797 1798 /** Finish an exchange. 1799 * 1800 * @param exch Exchange to finish. 1801 * 1802 */ 1803 void async_exchange_end(async_exch_t *exch) 1804 { 1805 if (exch == NULL) 1806 return; 1807 1808 async_sess_t *sess = exch->sess; 1809 1810 if (sess->mgmt == EXCHANGE_SERIALIZE) 1811 fibril_mutex_unlock(&sess->mutex); 1812 1813 fibril_mutex_lock(&async_sess_mutex); 1814 1815 list_append(&exch->sess_link, &sess->exch_list); 1816 list_append(&exch->global_link, &inactive_exch_list); 1817 fibril_condvar_signal(&avail_phone_cv); 1818 1819 fibril_mutex_unlock(&async_sess_mutex); 1820 } 1821 1436 1822 /** Wrapper for IPC_M_SHARE_IN calls using the async framework. 1437 1823 * 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 1824 * @param exch Exchange for sending the message. 1825 * @param dst Destination address space area base. 1826 * @param size Size of the destination address space area. 1827 * @param arg User defined argument. 1828 * @param flags Storage for the received flags. Can be NULL. 1443 1829 * 1444 1830 * @return Zero on success or a negative error code from errno.h. 1445 1831 * 1446 1832 */ 1447 int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg, 1448 unsigned int *flags) 1449 { 1833 int async_share_in_start(async_exch_t *exch, void *dst, size_t size, 1834 sysarg_t arg, unsigned int *flags) 1835 { 1836 if (exch == NULL) 1837 return ENOENT; 1838 1450 1839 sysarg_t tmp_flags; 1451 int res = async_req_3_2( phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,1840 int res = async_req_3_2(exch, IPC_M_SHARE_IN, (sysarg_t) dst, 1452 1841 (sysarg_t) size, arg, NULL, &tmp_flags); 1453 1842 … … 1507 1896 /** Wrapper for IPC_M_SHARE_OUT calls using the async framework. 1508 1897 * 1509 * @param phoneid Phone that will be used to contact the receiving side.1510 * @param src 1511 * @param flags 1898 * @param exch Exchange for sending the message. 1899 * @param src Source address space area base address. 1900 * @param flags Flags to be used for sharing. Bits can be only cleared. 1512 1901 * 1513 1902 * @return Zero on success or a negative error code from errno.h. 1514 1903 * 1515 1904 */ 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, 1905 int async_share_out_start(async_exch_t *exch, void *src, unsigned int flags) 1906 { 1907 if (exch == NULL) 1908 return ENOENT; 1909 1910 return async_req_3_0(exch, IPC_M_SHARE_OUT, (sysarg_t) src, 0, 1519 1911 (sysarg_t) flags); 1520 1912 } … … 1569 1961 } 1570 1962 1963 /** Start IPC_M_DATA_READ using the async framework. 1964 * 1965 * @param exch Exchange for sending the message. 1966 * @param dst Address of the beginning of the destination buffer. 1967 * @param size Size of the destination buffer (in bytes). 1968 * @param dataptr Storage of call data (arg 2 holds actual data size). 1969 * 1970 * @return Hash of the sent message or 0 on error. 1971 * 1972 */ 1973 aid_t async_data_read(async_exch_t *exch, void *dst, size_t size, 1974 ipc_call_t *dataptr) 1975 { 1976 return async_send_2(exch, IPC_M_DATA_READ, (sysarg_t) dst, 1977 (sysarg_t) size, dataptr); 1978 } 1979 1571 1980 /** Wrapper for IPC_M_DATA_READ calls using the async framework. 1572 1981 * 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. 1982 * @param exch Exchange for sending the message. 1983 * @param dst Address of the beginning of the destination buffer. 1984 * @param size Size of the destination buffer. 1577 1985 * 1578 1986 * @return Zero on success or a negative error code from errno.h. 1579 1987 * 1580 1988 */ 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); 1989 int async_data_read_start(async_exch_t *exch, void *dst, size_t size) 1990 { 1991 if (exch == NULL) 1992 return ENOENT; 1993 1994 return async_req_2_0(exch, IPC_M_DATA_READ, (sysarg_t) dst, 1995 (sysarg_t) size); 1586 1996 } 1587 1997 … … 1638 2048 * 1639 2049 */ 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 { 2050 int async_data_read_forward_fast(async_exch_t *exch, sysarg_t imethod, 2051 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, 2052 ipc_call_t *dataptr) 2053 { 2054 if (exch == NULL) 2055 return ENOENT; 2056 1643 2057 ipc_callid_t callid; 1644 2058 if (!async_data_read_receive(&callid, NULL)) { … … 1647 2061 } 1648 2062 1649 aid_t msg = async_send_fast( phoneid,method, arg1, arg2, arg3, arg4,2063 aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4, 1650 2064 dataptr); 1651 2065 if (msg == 0) { … … 1654 2068 } 1655 2069 1656 int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,2070 int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0, 1657 2071 IPC_FF_ROUTE_FROM_ME); 1658 2072 if (retval != EOK) { … … 1670 2084 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework. 1671 2085 * 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. 2086 * @param exch Exchange for sending the message. 2087 * @param src Address of the beginning of the source buffer. 2088 * @param size Size of the source buffer. 1676 2089 * 1677 2090 * @return Zero on success or a negative error code from errno.h. 1678 2091 * 1679 2092 */ 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); 2093 int async_data_write_start(async_exch_t *exch, const void *src, size_t size) 2094 { 2095 if (exch == NULL) 2096 return ENOENT; 2097 2098 return async_req_2_0(exch, IPC_M_DATA_WRITE, (sysarg_t) src, 2099 (sysarg_t) size); 1686 2100 } 1687 2101 … … 1759 2173 size_t *received) 1760 2174 { 2175 assert(data); 2176 1761 2177 ipc_callid_t callid; 1762 2178 size_t size; … … 1826 2242 * 1827 2243 */ 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 { 2244 int async_data_write_forward_fast(async_exch_t *exch, sysarg_t imethod, 2245 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, 2246 ipc_call_t *dataptr) 2247 { 2248 if (exch == NULL) 2249 return ENOENT; 2250 1831 2251 ipc_callid_t callid; 1832 2252 if (!async_data_write_receive(&callid, NULL)) { … … 1835 2255 } 1836 2256 1837 aid_t msg = async_send_fast( phoneid,method, arg1, arg2, arg3, arg4,2257 aid_t msg = async_send_fast(exch, imethod, arg1, arg2, arg3, arg4, 1838 2258 dataptr); 1839 2259 if (msg == 0) { … … 1842 2262 } 1843 2263 1844 int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0,2264 int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0, 1845 2265 IPC_FF_ROUTE_FROM_ME); 1846 2266 if (retval != EOK) { … … 1856 2276 } 1857 2277 2278 /** Wrapper for sending an exchange over different exchange for cloning 2279 * 2280 * @param exch Exchange to be used for sending. 2281 * @param clone_exch Exchange to be cloned. 2282 * 2283 */ 2284 int async_exchange_clone(async_exch_t *exch, async_exch_t *clone_exch) 2285 { 2286 return async_req_1_0(exch, IPC_M_CONNECTION_CLONE, clone_exch->phone); 2287 } 2288 2289 /** Wrapper for receiving the IPC_M_CONNECTION_CLONE calls. 2290 * 2291 * If the current call is IPC_M_CONNECTION_CLONE then a new 2292 * async session is created for the accepted phone. 2293 * 2294 * @param mgmt Exchange management style. 2295 * 2296 * @return New async session or NULL on failure. 2297 * 2298 */ 2299 async_sess_t *async_clone_receive(exch_mgmt_t mgmt) 2300 { 2301 /* Accept the phone */ 2302 ipc_call_t call; 2303 ipc_callid_t callid = async_get_call(&call); 2304 int phone = (int) IPC_GET_ARG1(call); 2305 2306 if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECTION_CLONE) || 2307 (phone < 0)) { 2308 async_answer_0(callid, EINVAL); 2309 return NULL; 2310 } 2311 2312 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 2313 if (sess == NULL) { 2314 async_answer_0(callid, ENOMEM); 2315 return NULL; 2316 } 2317 2318 sess->mgmt = mgmt; 2319 sess->phone = phone; 2320 sess->arg1 = 0; 2321 sess->arg2 = 0; 2322 sess->arg3 = 0; 2323 2324 list_initialize(&sess->exch_list); 2325 fibril_mutex_initialize(&sess->mutex); 2326 atomic_set(&sess->refcnt, 0); 2327 2328 /* Acknowledge the cloned phone */ 2329 async_answer_0(callid, EOK); 2330 2331 return sess; 2332 } 2333 2334 /** Wrapper for receiving the IPC_M_CONNECT_TO_ME calls. 2335 * 2336 * If the current call is IPC_M_CONNECT_TO_ME then a new 2337 * async session is created for the accepted phone. 2338 * 2339 * @param mgmt Exchange management style. 2340 * 2341 * @return New async session. 2342 * @return NULL on failure. 2343 * 2344 */ 2345 async_sess_t *async_callback_receive(exch_mgmt_t mgmt) 2346 { 2347 /* Accept the phone */ 2348 ipc_call_t call; 2349 ipc_callid_t callid = async_get_call(&call); 2350 int phone = (int) IPC_GET_ARG5(call); 2351 2352 if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) || 2353 (phone < 0)) { 2354 async_answer_0(callid, EINVAL); 2355 return NULL; 2356 } 2357 2358 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 2359 if (sess == NULL) { 2360 async_answer_0(callid, ENOMEM); 2361 return NULL; 2362 } 2363 2364 sess->mgmt = mgmt; 2365 sess->phone = phone; 2366 sess->arg1 = 0; 2367 sess->arg2 = 0; 2368 sess->arg3 = 0; 2369 2370 list_initialize(&sess->exch_list); 2371 fibril_mutex_initialize(&sess->mutex); 2372 atomic_set(&sess->refcnt, 0); 2373 2374 /* Acknowledge the connected phone */ 2375 async_answer_0(callid, EOK); 2376 2377 return sess; 2378 } 2379 2380 /** Wrapper for receiving the IPC_M_CONNECT_TO_ME calls. 2381 * 2382 * If the call is IPC_M_CONNECT_TO_ME then a new 2383 * async session is created. However, the phone is 2384 * not accepted automatically. 2385 * 2386 * @param mgmt Exchange management style. 2387 * @param call Call data. 2388 * 2389 * @return New async session. 2390 * @return NULL on failure. 2391 * @return NULL if the call is not IPC_M_CONNECT_TO_ME. 2392 * 2393 */ 2394 async_sess_t *async_callback_receive_start(exch_mgmt_t mgmt, ipc_call_t *call) 2395 { 2396 int phone = (int) IPC_GET_ARG5(*call); 2397 2398 if ((IPC_GET_IMETHOD(*call) != IPC_M_CONNECT_TO_ME) || 2399 (phone < 0)) 2400 return NULL; 2401 2402 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t)); 2403 if (sess == NULL) 2404 return NULL; 2405 2406 sess->mgmt = mgmt; 2407 sess->phone = phone; 2408 sess->arg1 = 0; 2409 sess->arg2 = 0; 2410 sess->arg3 = 0; 2411 2412 list_initialize(&sess->exch_list); 2413 fibril_mutex_initialize(&sess->mutex); 2414 atomic_set(&sess->refcnt, 0); 2415 2416 return sess; 2417 } 2418 1858 2419 /** @} 1859 2420 */
Note:
See TracChangeset
for help on using the changeset viewer.