Changes in uspace/lib/c/generic/async.c [79ae36dd:8e80d3f] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
r79ae36dd r8e80d3f 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> 111 #include <malloc.h>112 #include <mem.h>113 #include <stdlib.h>114 104 #include "private/async.h" 115 105 116 #define CLIENT_HASH_TABLE_BUCKETS 32117 #define CONN_HASH_TABLE_BUCKETS 32118 119 /** Async framework global futex */120 106 atomic_t async_futex = FUTEX_INITIALIZER; 121 107 … … 123 109 atomic_t threads_in_ipc_wait = { 0 }; 124 110 125 /** Naming service session */ 126 async_sess_t *session_ns; 127 128 /** Call data */ 111 typedef struct { 112 awaiter_t wdata; 113 114 /** If reply was received. */ 115 bool done; 116 117 /** Pointer to where the answer data is stored. */ 118 ipc_call_t *dataptr; 119 120 sysarg_t retval; 121 } amsg_t; 122 123 /** 124 * Structures of this type are used to group information about 125 * a call and about a message queue link. 126 */ 129 127 typedef struct { 130 128 link_t link; 131 132 129 ipc_callid_t callid; 133 130 ipc_call_t call; 134 131 } msg_t; 135 132 136 /* Client connection data */137 133 typedef struct { 134 sysarg_t in_task_hash; 138 135 link_t link; 139 140 sysarg_t in_task_hash; 141 atomic_t refcnt; 136 int refcnt; 142 137 void *data; 143 138 } client_t; 144 139 145 /* Server connection data */146 140 typedef struct { 147 141 awaiter_t wdata; … … 152 146 /** Incoming client task hash. */ 153 147 sysarg_t in_task_hash; 154 155 148 /** Incoming phone hash. */ 156 149 sysarg_t in_phone_hash; … … 175 168 176 169 /** Identifier of the incoming connection handled by the current fibril. */ 177 static fibril_local connection_t * fibril_connection;170 static fibril_local connection_t *FIBRIL_connection; 178 171 179 172 static void *default_client_data_constructor(void) … … 201 194 } 202 195 203 void *async_ get_client_data(void)204 { 205 assert( fibril_connection);206 return fibril_connection->client->data;196 void *async_client_data_get(void) 197 { 198 assert(FIBRIL_connection); 199 return FIBRIL_connection->client->data; 207 200 } 208 201 … … 220 213 } 221 214 215 /** 216 * Pointer to a fibril function that will be used to handle connections. 217 */ 218 static async_client_conn_t client_connection = default_client_connection; 219 222 220 /** Default fibril function that gets called to handle interrupt notifications. 223 221 * … … 232 230 } 233 231 234 static async_client_conn_t client_connection = default_client_connection; 232 /** 233 * Pointer to a fibril function that will be used to handle interrupt 234 * notifications. 235 */ 235 236 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 interrupt250 * 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);271 237 272 238 static hash_table_t client_hash_table; … … 274 240 static LIST_INITIALIZE(timeout_list); 275 241 242 #define CLIENT_HASH_TABLE_BUCKETS 32 243 #define CONN_HASH_TABLE_BUCKETS 32 244 276 245 static hash_index_t client_hash(unsigned long key[]) 277 246 { 278 247 assert(key); 279 280 248 return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS); 281 249 } … … 283 251 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item) 284 252 { 285 assert(key);286 assert(item);287 288 253 client_t *client = hash_table_get_instance(item, client_t, link); 289 254 return (key[0] == client->in_task_hash); … … 311 276 { 312 277 assert(key); 313 314 278 return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS); 315 279 } … … 326 290 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) 327 291 { 328 assert(key);329 assert(item);330 331 292 connection_t *conn = hash_table_get_instance(item, connection_t, link); 332 293 return (key[0] == conn->in_phone_hash); … … 351 312 void async_insert_timeout(awaiter_t *wd) 352 313 { 353 assert(wd);354 355 314 wd->to_event.occurred = false; 356 315 wd->to_event.inlist = true; … … 385 344 static bool route_call(ipc_callid_t callid, ipc_call_t *call) 386 345 { 387 assert(call);388 389 346 futex_down(&async_futex); 390 347 … … 441 398 static int notification_fibril(void *arg) 442 399 { 443 assert(arg);444 445 400 msg_t *msg = (msg_t *) arg; 446 401 interrupt_received(msg->callid, &msg->call); … … 463 418 static bool process_notification(ipc_callid_t callid, ipc_call_t *call) 464 419 { 465 assert(call);466 467 420 futex_down(&async_futex); 468 421 … … 503 456 ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) 504 457 { 505 assert(call); 506 assert(fibril_connection); 458 assert(FIBRIL_connection); 507 459 508 460 /* Why doing this? 509 * GCC 4.1.0 coughs on fibril_connection-> dereference.461 * GCC 4.1.0 coughs on FIBRIL_connection-> dereference. 510 462 * GCC 4.1.1 happilly puts the rdhwr instruction in delay slot. 511 463 * I would never expect to find so many errors in 512 464 * a compiler. 513 465 */ 514 connection_t *conn = fibril_connection;466 connection_t *conn = FIBRIL_connection; 515 467 516 468 futex_down(&async_futex); … … 587 539 static int connection_fibril(void *arg) 588 540 { 589 assert(arg);590 591 541 /* 592 542 * Setup fibril-local connection pointer. 593 543 */ 594 fibril_connection = (connection_t *) arg;544 FIBRIL_connection = (connection_t *) arg; 595 545 596 546 futex_down(&async_futex); … … 602 552 */ 603 553 604 unsigned long key = fibril_connection->in_task_hash;554 unsigned long key = FIBRIL_connection->in_task_hash; 605 555 link_t *lnk = hash_table_find(&client_hash_table, &key); 606 556 … … 609 559 if (lnk) { 610 560 client = hash_table_get_instance(lnk, client_t, link); 611 atomic_inc(&client->refcnt);561 client->refcnt++; 612 562 } else { 613 563 client = malloc(sizeof(client_t)); 614 564 if (!client) { 615 ipc_answer_0( fibril_connection->callid, ENOMEM);565 ipc_answer_0(FIBRIL_connection->callid, ENOMEM); 616 566 futex_up(&async_futex); 617 567 return 0; 618 568 } 619 569 620 client->in_task_hash = fibril_connection->in_task_hash; 570 client->in_task_hash = FIBRIL_connection->in_task_hash; 571 572 async_serialize_start(); 621 573 client->data = async_client_data_create(); 622 623 atomic_set(&client->refcnt, 1); 574 async_serialize_end(); 575 576 client->refcnt = 1; 624 577 hash_table_insert(&client_hash_table, &key, &client->link); 625 578 } … … 627 580 futex_up(&async_futex); 628 581 629 fibril_connection->client = client;582 FIBRIL_connection->client = client; 630 583 631 584 /* 632 585 * Call the connection handler function. 633 586 */ 634 fibril_connection->cfibril(fibril_connection->callid,635 & fibril_connection->call);587 FIBRIL_connection->cfibril(FIBRIL_connection->callid, 588 &FIBRIL_connection->call); 636 589 637 590 /* … … 642 595 futex_down(&async_futex); 643 596 644 if ( atomic_predec(&client->refcnt)== 0) {597 if (--client->refcnt == 0) { 645 598 hash_table_remove(&client_hash_table, &key, 1); 646 599 destroy = true; … … 661 614 */ 662 615 futex_down(&async_futex); 663 key = fibril_connection->in_phone_hash;616 key = FIBRIL_connection->in_phone_hash; 664 617 hash_table_remove(&conn_hash_table, &key, 1); 665 618 futex_up(&async_futex); … … 668 621 * Answer all remaining messages with EHANGUP. 669 622 */ 670 while (!list_empty(& fibril_connection->msg_queue)) {623 while (!list_empty(&FIBRIL_connection->msg_queue)) { 671 624 msg_t *msg = 672 list_get_instance( fibril_connection->msg_queue.next, msg_t,625 list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, 673 626 link); 674 627 … … 682 635 * i.e. IPC_M_PHONE_HUNGUP. 683 636 */ 684 if ( fibril_connection->close_callid)685 ipc_answer_0( fibril_connection->close_callid, EOK);686 687 free( fibril_connection);637 if (FIBRIL_connection->close_callid) 638 ipc_answer_0(FIBRIL_connection->close_callid, EOK); 639 640 free(FIBRIL_connection); 688 641 return 0; 689 642 } … … 691 644 /** Create a new fibril for a new connection. 692 645 * 693 * Create new fibril for connection, fill in connection structures and insert 646 * Create new fibril for connection, fill in connection structures and inserts 694 647 * it into the hash table, so that later we can easily do routing of messages to 695 648 * particular fibrils. … … 710 663 fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash, 711 664 ipc_callid_t callid, ipc_call_t *call, 712 async_client_conn_t cfibril)665 void (*cfibril)(ipc_callid_t, ipc_call_t *)) 713 666 { 714 667 connection_t *conn = malloc(sizeof(*conn)); … … 766 719 static void handle_call(ipc_callid_t callid, ipc_call_t *call) 767 720 { 768 assert(call);769 770 721 /* Unrouted call - take some default action */ 771 722 if ((callid & IPC_CALLID_NOTIFICATION)) { … … 925 876 void __async_init(void) 926 877 { 927 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 928 1,&client_hash_table_ops))878 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1, 879 &client_hash_table_ops)) 929 880 abort(); 930 881 931 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 932 1,&conn_hash_table_ops))882 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1, 883 &conn_hash_table_ops)) 933 884 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);948 885 } 949 886 … … 960 897 * 961 898 */ 962 void reply_received(void *arg, int retval, ipc_call_t *data) 963 { 964 assert(arg); 965 899 static void reply_received(void *arg, int retval, ipc_call_t *data) 900 { 966 901 futex_down(&async_futex); 967 902 … … 993 928 * completion. 994 929 * 995 * @param exch Exchange for sending the message.996 * @param imethod Service-defined interface and method.930 * @param phoneid Handle of the phone that will be used for the send. 931 * @param method Service-defined method. 997 932 * @param arg1 Service-defined payload argument. 998 933 * @param arg2 Service-defined payload argument. … … 1005 940 * 1006 941 */ 1007 aid_t async_send_fast( async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,942 aid_t async_send_fast(int phoneid, sysarg_t method, sysarg_t arg1, 1008 943 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 1009 944 { 1010 if (exch == NULL)1011 return 0;1012 1013 945 amsg_t *msg = malloc(sizeof(amsg_t)); 1014 if (msg == NULL) 946 947 if (!msg) 1015 948 return 0; 1016 949 … … 1026 959 msg->wdata.active = true; 1027 960 1028 ipc_call_async_4( exch->phone, imethod, arg1, arg2, arg3, arg4, msg,961 ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg, 1029 962 reply_received, true); 1030 963 … … 1037 970 * completion. 1038 971 * 1039 * @param exch Exchange for sending the message.1040 * @param imethod Service-defined interface and method.972 * @param phoneid Handle of the phone that will be used for the send. 973 * @param method Service-defined method. 1041 974 * @param arg1 Service-defined payload argument. 1042 975 * @param arg2 Service-defined payload argument. … … 1050 983 * 1051 984 */ 1052 aid_t async_send_slow( async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,985 aid_t async_send_slow(int phoneid, sysarg_t method, sysarg_t arg1, 1053 986 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 1054 987 ipc_call_t *dataptr) 1055 988 { 1056 if (exch == NULL)1057 return 0;1058 1059 989 amsg_t *msg = malloc(sizeof(amsg_t)); 1060 990 1061 if ( msg == NULL)991 if (!msg) 1062 992 return 0; 1063 993 … … 1073 1003 msg->wdata.active = true; 1074 1004 1075 ipc_call_async_5( exch->phone, imethod, arg1, arg2, arg3, arg4, arg5,1076 msg,reply_received, true);1005 ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg, 1006 reply_received, true); 1077 1007 1078 1008 return (aid_t) msg; … … 1088 1018 void async_wait_for(aid_t amsgid, sysarg_t *retval) 1089 1019 { 1090 assert(amsgid);1091 1092 1020 amsg_t *msg = (amsg_t *) amsgid; 1093 1021 … … 1126 1054 int async_wait_timeout(aid_t amsgid, sysarg_t *retval, suseconds_t timeout) 1127 1055 { 1128 assert(amsgid);1129 1130 1056 amsg_t *msg = (amsg_t *) amsgid; 1131 1057 … … 1196 1122 } 1197 1123 1124 /** Setter for client_connection function pointer. 1125 * 1126 * @param conn Function that will implement a new connection fibril. 1127 * 1128 */ 1129 void async_set_client_connection(async_client_conn_t conn) 1130 { 1131 client_connection = conn; 1132 } 1133 1134 /** Setter for interrupt_received function pointer. 1135 * 1136 * @param intr Function that will implement a new interrupt 1137 * notification fibril. 1138 */ 1139 void async_set_interrupt_received(async_client_conn_t intr) 1140 { 1141 interrupt_received = intr; 1142 } 1143 1198 1144 /** Pseudo-synchronous message sending - fast version. 1199 1145 * … … 1203 1149 * transferring more arguments, see the slower async_req_slow(). 1204 1150 * 1205 * @param exch Exchange for sending the message.1206 * @param imethod Interface and method of the call.1151 * @param phoneid Hash of the phone through which to make the call. 1152 * @param method Method of the call. 1207 1153 * @param arg1 Service-defined payload argument. 1208 1154 * @param arg2 Service-defined payload argument. … … 1218 1164 * 1219 1165 */ 1220 sysarg_t async_req_fast( async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,1166 sysarg_t async_req_fast(int phoneid, sysarg_t method, sysarg_t arg1, 1221 1167 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2, 1222 1168 sysarg_t *r3, sysarg_t *r4, sysarg_t *r5) 1223 1169 { 1224 if (exch == NULL)1225 return ENOENT;1226 1227 1170 ipc_call_t result; 1228 aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4,1171 aid_t eid = async_send_4(phoneid, method, arg1, arg2, arg3, arg4, 1229 1172 &result); 1230 1173 1231 1174 sysarg_t rc; 1232 async_wait_for( aid, &rc);1175 async_wait_for(eid, &rc); 1233 1176 1234 1177 if (r1) … … 1254 1197 * Send message asynchronously and return only after the reply arrives. 1255 1198 * 1256 * @param exch Exchange for sending the message.1257 * @param imethod Interface and method of the call.1199 * @param phoneid Hash of the phone through which to make the call. 1200 * @param method Method of the call. 1258 1201 * @param arg1 Service-defined payload argument. 1259 1202 * @param arg2 Service-defined payload argument. … … 1270 1213 * 1271 1214 */ 1272 sysarg_t async_req_slow( async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,1215 sysarg_t async_req_slow(int phoneid, sysarg_t method, sysarg_t arg1, 1273 1216 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1, 1274 1217 sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5) 1275 1218 { 1276 if (exch == NULL)1277 return ENOENT;1278 1279 1219 ipc_call_t result; 1280 aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5,1220 aid_t eid = async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, 1281 1221 &result); 1282 1222 1283 1223 sysarg_t rc; 1284 async_wait_for( aid, &rc);1224 async_wait_for(eid, &rc); 1285 1225 1286 1226 if (r1) … … 1302 1242 } 1303 1243 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); 1244 void async_msg_0(int phone, sysarg_t imethod) 1245 { 1246 ipc_call_async_0(phone, imethod, NULL, NULL, true); 1247 } 1248 1249 void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1) 1250 { 1251 ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true); 1252 } 1253 1254 void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2) 1255 { 1256 ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true); 1257 } 1258 1259 void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1260 sysarg_t arg3) 1261 { 1262 ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true); 1263 } 1264 1265 void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1266 sysarg_t arg3, sysarg_t arg4) 1267 { 1268 ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL, 1269 true); 1270 } 1271 1272 void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1273 sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 1274 { 1275 ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL, 1276 NULL, true); 1346 1277 } 1347 1278 … … 1380 1311 } 1381 1312 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); 1313 int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod, 1314 sysarg_t arg1, sysarg_t arg2, unsigned int mode) 1315 { 1316 return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode); 1317 } 1318 1319 int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod, 1320 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 1321 unsigned int mode) 1322 { 1323 return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4, 1324 arg5, mode); 1400 1325 } 1401 1326 … … 1404 1329 * Ask through phone for a new connection to some service. 1405 1330 * 1406 * @param exch Exchange for sending the message.1331 * @param phone Phone handle used for contacting the other side. 1407 1332 * @param arg1 User defined argument. 1408 1333 * @param arg2 User defined argument. … … 1410 1335 * @param client_receiver Connection handing routine. 1411 1336 * 1412 * @return Zeroon success or a negative error code.1413 * 1414 */ 1415 int async_connect_to_me( async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,1337 * @return New phone handle on success or a negative error code. 1338 * 1339 */ 1340 int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2, 1416 1341 sysarg_t arg3, async_client_conn_t client_receiver) 1417 1342 { 1418 if (exch == NULL)1419 return ENOENT;1420 1421 1343 sysarg_t task_hash; 1422 1344 sysarg_t phone_hash; 1423 int rc = async_req_3_5( exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,1345 int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 1424 1346 NULL, NULL, NULL, &task_hash, &phone_hash); 1425 1347 if (rc != EOK) … … 1433 1355 } 1434 1356 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); 1357 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1358 * 1359 * Ask through phone for a new connection to some service. 1360 * 1361 * @param phone Phone handle used for contacting the other side. 1362 * @param arg1 User defined argument. 1363 * @param arg2 User defined argument. 1364 * @param arg3 User defined argument. 1365 * 1366 * @return New phone handle on success or a negative error code. 1367 * 1368 */ 1369 int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2, 1370 sysarg_t arg3) 1371 { 1372 sysarg_t newphid; 1373 int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1374 NULL, NULL, NULL, NULL, &newphid); 1536 1375 1537 1376 if (rc != EOK) 1538 1377 return rc; 1539 1378 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; 1379 return newphid; 1590 1380 } 1591 1381 … … 1595 1385 * success. 1596 1386 * 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; 1387 * @param phoneid Phone handle used for contacting the other side. 1388 * @param arg1 User defined argument. 1389 * @param arg2 User defined argument. 1390 * @param arg3 User defined argument. 1391 * 1392 * @return New phone handle on success or a negative error code. 1393 * 1394 */ 1395 int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2, 1396 sysarg_t arg3) 1397 { 1398 sysarg_t newphid; 1399 int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1400 IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); 1401 1402 if (rc != EOK) 1403 return rc; 1404 1405 return newphid; 1640 1406 } 1641 1407 … … 1643 1409 * 1644 1410 */ 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) 1411 int async_connect_kbox(task_id_t id) 1412 { 1413 return ipc_connect_kbox(id); 1414 } 1415 1416 /** Wrapper for ipc_hangup. 1417 * 1418 * @param phone Phone handle to hung up. 1419 * 1420 * @return Zero on success or a negative error code. 1421 * 1422 */ 1423 int async_hangup(int phone) 1674 1424 { 1675 1425 return ipc_hangup(phone); 1676 }1677 1678 /** Wrapper for ipc_hangup.1679 *1680 * @param sess Session to hung up.1681 *1682 * @return Zero on success or a negative error code.1683 *1684 */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;1697 1426 } 1698 1427 … … 1703 1432 } 1704 1433 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 } else1761 async_hangup_internal(phone);1762 } else if (!list_empty(&inactive_exch_list)) {1763 /*1764 * We did not manage to connect a new phone. But we1765 * can try to close some of the currently inactive1766 * 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 1822 1434 /** Wrapper for IPC_M_SHARE_IN calls using the async framework. 1823 1435 * 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.1436 * @param phoneid Phone that will be used to contact the receiving side. 1437 * @param dst Destination address space area base. 1438 * @param size Size of the destination address space area. 1439 * @param arg User defined argument. 1440 * @param flags Storage for the received flags. Can be NULL. 1829 1441 * 1830 1442 * @return Zero on success or a negative error code from errno.h. 1831 1443 * 1832 1444 */ 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 1445 int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg, 1446 unsigned int *flags) 1447 { 1839 1448 sysarg_t tmp_flags; 1840 int res = async_req_3_2( exch, IPC_M_SHARE_IN, (sysarg_t) dst,1449 int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst, 1841 1450 (sysarg_t) size, arg, NULL, &tmp_flags); 1842 1451 … … 1896 1505 /** Wrapper for IPC_M_SHARE_OUT calls using the async framework. 1897 1506 * 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.1507 * @param phoneid Phone that will be used to contact the receiving side. 1508 * @param src Source address space area base address. 1509 * @param flags Flags to be used for sharing. Bits can be only cleared. 1901 1510 * 1902 1511 * @return Zero on success or a negative error code from errno.h. 1903 1512 * 1904 1513 */ 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, 1514 int async_share_out_start(int phoneid, void *src, unsigned int flags) 1515 { 1516 return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0, 1911 1517 (sysarg_t) flags); 1912 1518 } … … 1961 1567 } 1962 1568 1963 /** Start IPC_M_DATA_READusing the async framework.1964 * 1965 * @param exch Exchange for sending the message.1569 /** Wrapper for IPC_M_DATA_READ calls using the async framework. 1570 * 1571 * @param phoneid Phone that will be used to contact the receiving side. 1966 1572 * @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 1980 /** Wrapper for IPC_M_DATA_READ calls using the async framework. 1981 * 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. 1573 * @param size Size of the destination buffer. 1574 * @param flags Flags to control the data transfer. 1985 1575 * 1986 1576 * @return Zero on success or a negative error code from errno.h. 1987 1577 * 1988 1578 */ 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); 1579 int 1580 async_data_read_start_generic(int phoneid, void *dst, size_t size, int flags) 1581 { 1582 return async_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst, 1583 (sysarg_t) size, (sysarg_t) flags); 1996 1584 } 1997 1585 … … 2048 1636 * 2049 1637 */ 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 1638 int async_data_read_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1, 1639 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 1640 { 2057 1641 ipc_callid_t callid; 2058 1642 if (!async_data_read_receive(&callid, NULL)) { … … 2061 1645 } 2062 1646 2063 aid_t msg = async_send_fast( exch, imethod, arg1, arg2, arg3, arg4,1647 aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4, 2064 1648 dataptr); 2065 1649 if (msg == 0) { … … 2068 1652 } 2069 1653 2070 int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,1654 int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0, 2071 1655 IPC_FF_ROUTE_FROM_ME); 2072 1656 if (retval != EOK) { … … 2084 1668 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework. 2085 1669 * 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. 1670 * @param phoneid Phone that will be used to contact the receiving side. 1671 * @param src Address of the beginning of the source buffer. 1672 * @param size Size of the source buffer. 1673 * @param flags Flags to control the data transfer. 2089 1674 * 2090 1675 * @return Zero on success or a negative error code from errno.h. 2091 1676 * 2092 1677 */ 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); 1678 int 1679 async_data_write_start_generic(int phoneid, const void *src, size_t size, 1680 int flags) 1681 { 1682 return async_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src, 1683 (sysarg_t) size, (sysarg_t) flags); 2100 1684 } 2101 1685 … … 2173 1757 size_t *received) 2174 1758 { 2175 assert(data);2176 2177 1759 ipc_callid_t callid; 2178 1760 size_t size; … … 2242 1824 * 2243 1825 */ 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 1826 int async_data_write_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1, 1827 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 1828 { 2251 1829 ipc_callid_t callid; 2252 1830 if (!async_data_write_receive(&callid, NULL)) { … … 2255 1833 } 2256 1834 2257 aid_t msg = async_send_fast( exch, imethod, arg1, arg2, arg3, arg4,1835 aid_t msg = async_send_fast(phoneid, method, arg1, arg2, arg3, arg4, 2258 1836 dataptr); 2259 1837 if (msg == 0) { … … 2262 1840 } 2263 1841 2264 int retval = ipc_forward_fast(callid, exch->phone, 0, 0, 0,1842 int retval = ipc_forward_fast(callid, phoneid, 0, 0, 0, 2265 1843 IPC_FF_ROUTE_FROM_ME); 2266 1844 if (retval != EOK) { … … 2276 1854 } 2277 1855 2278 /** Wrapper for sending an exchange over different exchange for cloning2279 *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 new2292 * 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 new2337 * async session is created for the accepted phone.2338 *2339 * @param mgmt Exchange management style.2340 *2341 * @return New async session or NULL on failure.2342 *2343 */2344 async_sess_t *async_callback_receive(exch_mgmt_t mgmt)2345 {2346 /* Accept the phone */2347 ipc_call_t call;2348 ipc_callid_t callid = async_get_call(&call);2349 int phone = (int) IPC_GET_ARG5(call);2350 2351 if ((IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) ||2352 (phone < 0)) {2353 async_answer_0(callid, EINVAL);2354 return NULL;2355 }2356 2357 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));2358 if (sess == NULL) {2359 async_answer_0(callid, ENOMEM);2360 return NULL;2361 }2362 2363 sess->mgmt = mgmt;2364 sess->phone = phone;2365 sess->arg1 = 0;2366 sess->arg2 = 0;2367 sess->arg3 = 0;2368 2369 list_initialize(&sess->exch_list);2370 fibril_mutex_initialize(&sess->mutex);2371 atomic_set(&sess->refcnt, 0);2372 2373 /* Acknowledge the connected phone */2374 async_answer_0(callid, EOK);2375 2376 return sess;2377 }2378 2379 1856 /** @} 2380 1857 */
Note:
See TracChangeset
for help on using the changeset viewer.