Changes in uspace/lib/c/generic/async.c [ae6021d:df956b9b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
rae6021d rdf956b9b 77 77 * } 78 78 * 79 * port_handler(icallid, *icall)79 * my_client_connection(icallid, *icall) 80 80 * { 81 81 * if (want_refuse) { … … 101 101 #undef LIBC_ASYNC_C_ 102 102 103 #include <ipc/irq.h>104 #include <ipc/event.h>105 103 #include <futex.h> 106 104 #include <fibril.h> … … 116 114 #include <stdlib.h> 117 115 #include <macros.h> 118 #include <as.h>119 #include <abi/mm/as.h>120 116 #include "private/libc.h" 117 121 118 122 119 /** Session data */ … … 125 122 list_t exch_list; 126 123 127 /** Session interface */128 iface_t iface;129 130 124 /** Exchange management style */ 131 125 exch_mgmt_t mgmt; … … 172 166 173 167 /** Async framework global futex */ 174 futex_t async_futex = FUTEX_INITIALIZER;168 atomic_t async_futex = FUTEX_INITIALIZER; 175 169 176 170 /** Number of threads waiting for IPC in the kernel. */ … … 194 188 /** If reply was received. */ 195 189 bool done; 196 190 197 191 /** If the message / reply should be discarded on arrival. */ 198 192 bool forget; 199 193 200 194 /** If already destroyed. */ 201 195 bool destroyed; … … 237 231 /** Identification of the opening call. */ 238 232 ipc_callid_t callid; 239 240 233 /** Call data of the opening call. */ 241 234 ipc_call_t call; 235 /** Local argument or NULL if none. */ 236 void *carg; 242 237 243 238 /** Identification of the closing call. */ … … 245 240 246 241 /** Fibril function that will be used to handle the connection. */ 247 async_port_handler_t handler; 248 249 /** Client data */ 250 void *data; 242 async_client_conn_t cfibril; 251 243 } connection_t; 252 253 /** Interface data */254 typedef struct {255 ht_link_t link;256 257 /** Interface ID */258 iface_t iface;259 260 /** Futex protecting the hash table */261 futex_t futex;262 263 /** Interface ports */264 hash_table_t port_hash_table;265 266 /** Next available port ID */267 port_id_t port_id_avail;268 } interface_t;269 270 /* Port data */271 typedef struct {272 ht_link_t link;273 274 /** Port ID */275 port_id_t id;276 277 /** Port connection handler */278 async_port_handler_t handler;279 280 /** Client data */281 void *data;282 } port_t;283 284 /* Notification data */285 typedef struct {286 ht_link_t link;287 288 /** Notification method */289 sysarg_t imethod;290 291 /** Notification handler */292 async_notification_handler_t handler;293 294 /** Notification data */295 void *data;296 } notification_t;297 244 298 245 /** Identifier of the incoming connection handled by the current fibril. */ … … 302 249 { 303 250 struct timeval tv = { 0, 0 }; 304 251 305 252 to->inlist = false; 306 253 to->occurred = false; … … 325 272 static amsg_t *amsg_create(void) 326 273 { 327 amsg_t *msg = malloc(sizeof(amsg_t)); 274 amsg_t *msg; 275 276 msg = malloc(sizeof(amsg_t)); 328 277 if (msg) { 329 278 msg->done = false; … … 334 283 awaiter_initialize(&msg->wdata); 335 284 } 336 285 337 286 return msg; 338 287 } … … 371 320 } 372 321 373 /** Default fallback fibril function. 374 * 375 * This fallback fibril function gets called on incomming 376 * connections that do not have a specific handler defined. 322 /** Default fibril function that gets called to handle new connection. 323 * 324 * This function is defined as a weak symbol - to be redefined in user code. 377 325 * 378 326 * @param callid Hash of the incoming call. … … 381 329 * 382 330 */ 383 static void default_ fallback_port_handler(ipc_callid_t callid, ipc_call_t *call,331 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call, 384 332 void *arg) 385 333 { … … 387 335 } 388 336 389 static async_port_handler_t fallback_port_handler = 390 default_fallback_port_handler; 391 static void *fallback_port_data = NULL; 392 393 static hash_table_t interface_hash_table; 394 395 static size_t interface_key_hash(void *key) 396 { 397 iface_t iface = *(iface_t *) key; 398 return iface; 399 } 400 401 static size_t interface_hash(const ht_link_t *item) 402 { 403 interface_t *interface = hash_table_get_inst(item, interface_t, link); 404 return interface_key_hash(&interface->iface); 405 } 406 407 static bool interface_key_equal(void *key, const ht_link_t *item) 408 { 409 iface_t iface = *(iface_t *) key; 410 interface_t *interface = hash_table_get_inst(item, interface_t, link); 411 return iface == interface->iface; 412 } 413 414 /** Operations for the port hash table. */ 415 static hash_table_ops_t interface_hash_table_ops = { 416 .hash = interface_hash, 417 .key_hash = interface_key_hash, 418 .key_equal = interface_key_equal, 419 .equal = NULL, 420 .remove_callback = NULL 421 }; 422 423 static size_t port_key_hash(void *key) 424 { 425 port_id_t port_id = *(port_id_t *) key; 426 return port_id; 427 } 428 429 static size_t port_hash(const ht_link_t *item) 430 { 431 port_t *port = hash_table_get_inst(item, port_t, link); 432 return port_key_hash(&port->id); 433 } 434 435 static bool port_key_equal(void *key, const ht_link_t *item) 436 { 437 port_id_t port_id = *(port_id_t *) key; 438 port_t *port = hash_table_get_inst(item, port_t, link); 439 return port_id == port->id; 440 } 441 442 /** Operations for the port hash table. */ 443 static hash_table_ops_t port_hash_table_ops = { 444 .hash = port_hash, 445 .key_hash = port_key_hash, 446 .key_equal = port_key_equal, 447 .equal = NULL, 448 .remove_callback = NULL 449 }; 450 451 static interface_t *async_new_interface(iface_t iface) 452 { 453 interface_t *interface = 454 (interface_t *) malloc(sizeof(interface_t)); 455 if (!interface) 456 return NULL; 457 458 bool ret = hash_table_create(&interface->port_hash_table, 0, 0, 459 &port_hash_table_ops); 460 if (!ret) { 461 free(interface); 462 return NULL; 463 } 464 465 interface->iface = iface; 466 futex_initialize(&interface->futex, 1); 467 interface->port_id_avail = 0; 468 469 hash_table_insert(&interface_hash_table, &interface->link); 470 471 return interface; 472 } 473 474 static port_t *async_new_port(interface_t *interface, 475 async_port_handler_t handler, void *data) 476 { 477 port_t *port = (port_t *) malloc(sizeof(port_t)); 478 if (!port) 479 return NULL; 480 481 futex_down(&interface->futex); 482 483 port_id_t id = interface->port_id_avail; 484 interface->port_id_avail++; 485 486 port->id = id; 487 port->handler = handler; 488 port->data = data; 489 490 hash_table_insert(&interface->port_hash_table, &port->link); 491 492 futex_up(&interface->futex); 493 494 return port; 337 /** Default fibril function that gets called to handle interrupt notifications. 338 * 339 * This function is defined as a weak symbol - to be redefined in user code. 340 * 341 * @param callid Hash of the incoming call. 342 * @param call Data of the incoming call. 343 * @param arg Local argument. 344 * 345 */ 346 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call) 347 { 348 } 349 350 static async_client_conn_t client_connection = default_client_connection; 351 static async_interrupt_handler_t interrupt_received = default_interrupt_received; 352 static size_t interrupt_handler_stksz = FIBRIL_DFLT_STK_SIZE; 353 354 /** Setter for client_connection function pointer. 355 * 356 * @param conn Function that will implement a new connection fibril. 357 * 358 */ 359 void async_set_client_connection(async_client_conn_t conn) 360 { 361 assert(client_connection == default_client_connection); 362 client_connection = conn; 363 } 364 365 /** Setter for interrupt_received function pointer. 366 * 367 * @param intr Function that will implement a new interrupt 368 * notification fibril. 369 */ 370 void async_set_interrupt_received(async_interrupt_handler_t intr) 371 { 372 interrupt_received = intr; 373 } 374 375 /** Set the stack size for the interrupt handler notification fibrils. 376 * 377 * @param size Stack size in bytes. 378 */ 379 void async_set_interrupt_handler_stack_size(size_t size) 380 { 381 interrupt_handler_stksz = size; 495 382 } 496 383 … … 509 396 */ 510 397 static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv); 511 512 int async_create_port(iface_t iface, async_port_handler_t handler,513 void *data, port_id_t *port_id)514 {515 if ((iface & IFACE_MOD_MASK) == IFACE_MOD_CALLBACK)516 return EINVAL;517 518 interface_t *interface;519 520 futex_down(&async_futex);521 522 ht_link_t *link = hash_table_find(&interface_hash_table, &iface);523 if (link)524 interface = hash_table_get_inst(link, interface_t, link);525 else526 interface = async_new_interface(iface);527 528 if (!interface) {529 futex_up(&async_futex);530 return ENOMEM;531 }532 533 port_t *port = async_new_port(interface, handler, data);534 if (!port) {535 futex_up(&async_futex);536 return ENOMEM;537 }538 539 *port_id = port->id;540 541 futex_up(&async_futex);542 543 return EOK;544 }545 546 void async_set_fallback_port_handler(async_port_handler_t handler, void *data)547 {548 assert(handler != NULL);549 550 fallback_port_handler = handler;551 fallback_port_data = data;552 }553 398 554 399 static hash_table_t client_hash_table; 555 400 static hash_table_t conn_hash_table; 556 static hash_table_t notification_hash_table;557 401 static LIST_INITIALIZE(timeout_list); 558 402 559 static sysarg_t notification_avail = 0; 560 561 static size_t client_key_hash(void *key) 562 { 563 task_id_t in_task_id = *(task_id_t *) key; 564 return in_task_id; 403 static size_t client_key_hash(void *k) 404 { 405 task_id_t key = *(task_id_t*)k; 406 return key; 565 407 } 566 408 … … 571 413 } 572 414 573 static bool client_key_equal(void *k ey, const ht_link_t *item)574 { 575 task_id_t in_task_id = *(task_id_t *) key;415 static bool client_key_equal(void *k, const ht_link_t *item) 416 { 417 task_id_t key = *(task_id_t*)k; 576 418 client_t *client = hash_table_get_inst(item, client_t, link); 577 return in_task_id == client->in_task_id; 578 } 419 return key == client->in_task_id; 420 } 421 579 422 580 423 /** Operations for the client hash table. */ … … 596 439 static size_t conn_key_hash(void *key) 597 440 { 598 sysarg_t in_phone_hash = *(sysarg_t *)key;599 return in_phone_hash ;441 sysarg_t in_phone_hash = *(sysarg_t*)key; 442 return in_phone_hash ; 600 443 } 601 444 … … 608 451 static bool conn_key_equal(void *key, const ht_link_t *item) 609 452 { 610 sysarg_t in_phone_hash = *(sysarg_t *)key;453 sysarg_t in_phone_hash = *(sysarg_t*)key; 611 454 connection_t *conn = hash_table_get_inst(item, connection_t, link); 612 455 return (in_phone_hash == conn->in_phone_hash); 613 456 } 457 614 458 615 459 /** Operations for the connection hash table. */ … … 622 466 }; 623 467 624 static client_t *async_client_get(task_id_t client_id, bool create)625 {626 client_t *client = NULL;627 628 futex_down(&async_futex);629 ht_link_t *link = hash_table_find(&client_hash_table, &client_id);630 if (link) {631 client = hash_table_get_inst(link, client_t, link);632 atomic_inc(&client->refcnt);633 } else if (create) {634 client = malloc(sizeof(client_t));635 if (client) {636 client->in_task_id = client_id;637 client->data = async_client_data_create();638 639 atomic_set(&client->refcnt, 1);640 hash_table_insert(&client_hash_table, &client->link);641 }642 }643 644 futex_up(&async_futex);645 return client;646 }647 648 static void async_client_put(client_t *client)649 {650 bool destroy;651 652 futex_down(&async_futex);653 654 if (atomic_predec(&client->refcnt) == 0) {655 hash_table_remove(&client_hash_table, &client->in_task_id);656 destroy = true;657 } else658 destroy = false;659 660 futex_up(&async_futex);661 662 if (destroy) {663 if (client->data)664 async_client_data_destroy(client->data);665 666 free(client);667 }668 }669 670 /** Wrapper for client connection fibril.671 *672 * When a new connection arrives, a fibril with this implementing673 * function is created.674 *675 * @param arg Connection structure pointer.676 *677 * @return Always zero.678 *679 */680 static int connection_fibril(void *arg)681 {682 assert(arg);683 684 /*685 * Setup fibril-local connection pointer.686 */687 fibril_connection = (connection_t *) arg;688 689 /*690 * Add our reference for the current connection in the client task691 * tracking structure. If this is the first reference, create and692 * hash in a new tracking structure.693 */694 695 client_t *client = async_client_get(fibril_connection->in_task_id, true);696 if (!client) {697 ipc_answer_0(fibril_connection->callid, ENOMEM);698 return 0;699 }700 701 fibril_connection->client = client;702 703 /*704 * Call the connection handler function.705 */706 fibril_connection->handler(fibril_connection->callid,707 &fibril_connection->call, fibril_connection->data);708 709 /*710 * Remove the reference for this client task connection.711 */712 async_client_put(client);713 714 /*715 * Remove myself from the connection hash table.716 */717 futex_down(&async_futex);718 hash_table_remove(&conn_hash_table, &fibril_connection->in_phone_hash);719 futex_up(&async_futex);720 721 /*722 * Answer all remaining messages with EHANGUP.723 */724 while (!list_empty(&fibril_connection->msg_queue)) {725 msg_t *msg =726 list_get_instance(list_first(&fibril_connection->msg_queue),727 msg_t, link);728 729 list_remove(&msg->link);730 ipc_answer_0(msg->callid, EHANGUP);731 free(msg);732 }733 734 /*735 * If the connection was hung-up, answer the last call,736 * i.e. IPC_M_PHONE_HUNGUP.737 */738 if (fibril_connection->close_callid)739 ipc_answer_0(fibril_connection->close_callid, EOK);740 741 free(fibril_connection);742 return 0;743 }744 745 /** Create a new fibril for a new connection.746 *747 * Create new fibril for connection, fill in connection structures748 * and insert it into the hash table, so that later we can easily749 * do routing of messages to particular fibrils.750 *751 * @param in_task_id Identification of the incoming connection.752 * @param in_phone_hash Identification of the incoming connection.753 * @param callid Hash of the opening IPC_M_CONNECT_ME_TO call.754 * If callid is zero, the connection was opened by755 * accepting the IPC_M_CONNECT_TO_ME call and this756 * function is called directly by the server.757 * @param call Call data of the opening call.758 * @param handler Connection handler.759 * @param data Client argument to pass to the connection handler.760 *761 * @return New fibril id or NULL on failure.762 *763 */764 static fid_t async_new_connection(task_id_t in_task_id, sysarg_t in_phone_hash,765 ipc_callid_t callid, ipc_call_t *call, async_port_handler_t handler,766 void *data)767 {768 connection_t *conn = malloc(sizeof(*conn));769 if (!conn) {770 if (callid)771 ipc_answer_0(callid, ENOMEM);772 773 return (uintptr_t) NULL;774 }775 776 conn->in_task_id = in_task_id;777 conn->in_phone_hash = in_phone_hash;778 list_initialize(&conn->msg_queue);779 conn->callid = callid;780 conn->close_callid = 0;781 conn->handler = handler;782 conn->data = data;783 784 if (call)785 conn->call = *call;786 787 /* We will activate the fibril ASAP */788 conn->wdata.active = true;789 conn->wdata.fid = fibril_create(connection_fibril, conn);790 791 if (conn->wdata.fid == 0) {792 free(conn);793 794 if (callid)795 ipc_answer_0(callid, ENOMEM);796 797 return (uintptr_t) NULL;798 }799 800 /* Add connection to the connection hash table */801 802 futex_down(&async_futex);803 hash_table_insert(&conn_hash_table, &conn->link);804 futex_up(&async_futex);805 806 fibril_add_ready(conn->wdata.fid);807 808 return conn->wdata.fid;809 }810 811 /** Wrapper for making IPC_M_CONNECT_TO_ME calls using the async framework.812 *813 * Ask through phone for a new connection to some service.814 *815 * @param exch Exchange for sending the message.816 * @param iface Callback interface.817 * @param arg1 User defined argument.818 * @param arg2 User defined argument.819 * @param handler Callback handler.820 * @param data Handler data.821 * @param port_id ID of the newly created port.822 *823 * @return Zero on success or a negative error code.824 *825 */826 int async_create_callback_port(async_exch_t *exch, iface_t iface, sysarg_t arg1,827 sysarg_t arg2, async_port_handler_t handler, void *data, port_id_t *port_id)828 {829 if ((iface & IFACE_MOD_CALLBACK) != IFACE_MOD_CALLBACK)830 return EINVAL;831 832 if (exch == NULL)833 return ENOENT;834 835 ipc_call_t answer;836 aid_t req = async_send_3(exch, IPC_M_CONNECT_TO_ME, iface, arg1, arg2,837 &answer);838 839 sysarg_t ret;840 async_wait_for(req, &ret);841 if (ret != EOK)842 return (int) ret;843 844 sysarg_t phone_hash = IPC_GET_ARG5(answer);845 interface_t *interface;846 847 futex_down(&async_futex);848 849 ht_link_t *link = hash_table_find(&interface_hash_table, &iface);850 if (link)851 interface = hash_table_get_inst(link, interface_t, link);852 else853 interface = async_new_interface(iface);854 855 if (!interface) {856 futex_up(&async_futex);857 return ENOMEM;858 }859 860 port_t *port = async_new_port(interface, handler, data);861 if (!port) {862 futex_up(&async_futex);863 return ENOMEM;864 }865 866 *port_id = port->id;867 868 futex_up(&async_futex);869 870 fid_t fid = async_new_connection(answer.in_task_id, phone_hash,871 0, NULL, handler, data);872 if (fid == (uintptr_t) NULL)873 return ENOMEM;874 875 return EOK;876 }877 878 static size_t notification_key_hash(void *key)879 {880 sysarg_t id = *(sysarg_t *) key;881 return id;882 }883 884 static size_t notification_hash(const ht_link_t *item)885 {886 notification_t *notification =887 hash_table_get_inst(item, notification_t, link);888 return notification_key_hash(¬ification->imethod);889 }890 891 static bool notification_key_equal(void *key, const ht_link_t *item)892 {893 sysarg_t id = *(sysarg_t *) key;894 notification_t *notification =895 hash_table_get_inst(item, notification_t, link);896 return id == notification->imethod;897 }898 899 /** Operations for the notification hash table. */900 static hash_table_ops_t notification_hash_table_ops = {901 .hash = notification_hash,902 .key_hash = notification_key_hash,903 .key_equal = notification_key_equal,904 .equal = NULL,905 .remove_callback = NULL906 };907 908 468 /** Sort in current fibril's timeout request. 909 469 * … … 951 511 futex_down(&async_futex); 952 512 953 ht_link_t *link = hash_table_find(&conn_hash_table, &call->in_phone_hash); 954 if (!link) { 513 ht_link_t *hlp = hash_table_find(&conn_hash_table, &call->in_phone_hash); 514 515 if (!hlp) { 955 516 futex_up(&async_futex); 956 517 return false; 957 518 } 958 519 959 connection_t *conn = hash_table_get_inst( link, connection_t, link);520 connection_t *conn = hash_table_get_inst(hlp, connection_t, link); 960 521 961 522 msg_t *msg = malloc(sizeof(*msg)); … … 989 550 } 990 551 991 /** Process notification. 552 /** Notification fibril. 553 * 554 * When a notification arrives, a fibril with this implementing function is 555 * created. It calls interrupt_received() and does the final cleanup. 556 * 557 * @param arg Message structure pointer. 558 * 559 * @return Always zero. 560 * 561 */ 562 static int notification_fibril(void *arg) 563 { 564 assert(arg); 565 566 msg_t *msg = (msg_t *) arg; 567 interrupt_received(msg->callid, &msg->call); 568 569 free(msg); 570 return 0; 571 } 572 573 /** Process interrupt notification. 574 * 575 * A new fibril is created which would process the notification. 992 576 * 993 577 * @param callid Hash of the incoming call. 994 578 * @param call Data of the incoming call. 995 579 * 996 * /997 static void process_notification(ipc_callid_t callid, ipc_call_t *call) 998 { 999 async_notification_handler_t handler = NULL; 1000 void *data = NULL; 1001 580 * @return False if an error occured. 581 * True if the call was passed to the notification fibril. 582 * 583 */ 584 static bool process_notification(ipc_callid_t callid, ipc_call_t *call) 585 { 1002 586 assert(call); 1003 587 1004 588 futex_down(&async_futex); 1005 589 1006 ht_link_t *link = hash_table_find(¬ification_hash_table, 1007 &IPC_GET_IMETHOD(*call)); 1008 if (link) { 1009 notification_t *notification = 1010 hash_table_get_inst(link, notification_t, link); 1011 handler = notification->handler; 1012 data = notification->data; 1013 } 590 msg_t *msg = malloc(sizeof(*msg)); 591 if (!msg) { 592 futex_up(&async_futex); 593 return false; 594 } 595 596 msg->callid = callid; 597 msg->call = *call; 598 599 fid_t fid = fibril_create_generic(notification_fibril, msg, 600 interrupt_handler_stksz); 601 if (fid == 0) { 602 free(msg); 603 futex_up(&async_futex); 604 return false; 605 } 606 607 fibril_add_ready(fid); 1014 608 1015 609 futex_up(&async_futex); 1016 1017 if (handler) 1018 handler(callid, call, data); 1019 } 1020 1021 /** Subscribe to IRQ notification. 1022 * 1023 * @param inr IRQ number. 1024 * @param devno Device number of the device generating inr. 1025 * @param handler Notification handler. 1026 * @param data Notification handler client data. 1027 * @param ucode Top-half pseudocode handler. 1028 * 1029 * @return Zero on success or a negative error code. 1030 * 1031 */ 1032 int async_irq_subscribe(int inr, int devno, 1033 async_notification_handler_t handler, void *data, const irq_code_t *ucode) 1034 { 1035 notification_t *notification = 1036 (notification_t *) malloc(sizeof(notification_t)); 1037 if (!notification) 1038 return ENOMEM; 1039 1040 futex_down(&async_futex); 1041 1042 sysarg_t imethod = notification_avail; 1043 notification_avail++; 1044 1045 notification->imethod = imethod; 1046 notification->handler = handler; 1047 notification->data = data; 1048 1049 hash_table_insert(¬ification_hash_table, ¬ification->link); 1050 1051 futex_up(&async_futex); 1052 1053 return ipc_irq_subscribe(inr, devno, imethod, ucode); 1054 } 1055 1056 /** Unsubscribe from IRQ notification. 1057 * 1058 * @param inr IRQ number. 1059 * @param devno Device number of the device generating inr. 1060 * 1061 * @return Zero on success or a negative error code. 1062 * 1063 */ 1064 int async_irq_unsubscribe(int inr, int devno) 1065 { 1066 // TODO: Remove entry from hash table 1067 // to avoid memory leak 1068 1069 return ipc_irq_unsubscribe(inr, devno); 1070 } 1071 1072 /** Subscribe to event notifications. 1073 * 1074 * @param evno Event type to subscribe. 1075 * @param handler Notification handler. 1076 * @param data Notification handler client data. 1077 * 1078 * @return Zero on success or a negative error code. 1079 * 1080 */ 1081 int async_event_subscribe(event_type_t evno, 1082 async_notification_handler_t handler, void *data) 1083 { 1084 notification_t *notification = 1085 (notification_t *) malloc(sizeof(notification_t)); 1086 if (!notification) 1087 return ENOMEM; 1088 1089 futex_down(&async_futex); 1090 1091 sysarg_t imethod = notification_avail; 1092 notification_avail++; 1093 1094 notification->imethod = imethod; 1095 notification->handler = handler; 1096 notification->data = data; 1097 1098 hash_table_insert(¬ification_hash_table, ¬ification->link); 1099 1100 futex_up(&async_futex); 1101 1102 return ipc_event_subscribe(evno, imethod); 1103 } 1104 1105 /** Subscribe to task event notifications. 1106 * 1107 * @param evno Event type to subscribe. 1108 * @param handler Notification handler. 1109 * @param data Notification handler client data. 1110 * 1111 * @return Zero on success or a negative error code. 1112 * 1113 */ 1114 int async_event_task_subscribe(event_task_type_t evno, 1115 async_notification_handler_t handler, void *data) 1116 { 1117 notification_t *notification = 1118 (notification_t *) malloc(sizeof(notification_t)); 1119 if (!notification) 1120 return ENOMEM; 1121 1122 futex_down(&async_futex); 1123 1124 sysarg_t imethod = notification_avail; 1125 notification_avail++; 1126 1127 notification->imethod = imethod; 1128 notification->handler = handler; 1129 notification->data = data; 1130 1131 hash_table_insert(¬ification_hash_table, ¬ification->link); 1132 1133 futex_up(&async_futex); 1134 1135 return ipc_event_task_subscribe(evno, imethod); 1136 } 1137 1138 /** Unmask event notifications. 1139 * 1140 * @param evno Event type to unmask. 1141 * 1142 * @return Value returned by the kernel. 1143 * 1144 */ 1145 int async_event_unmask(event_type_t evno) 1146 { 1147 return ipc_event_unmask(evno); 1148 } 1149 1150 /** Unmask task event notifications. 1151 * 1152 * @param evno Event type to unmask. 1153 * 1154 * @return Value returned by the kernel. 1155 * 1156 */ 1157 int async_event_task_unmask(event_task_type_t evno) 1158 { 1159 return ipc_event_task_unmask(evno); 610 return true; 1160 611 } 1161 612 … … 1189 640 if (usecs) { 1190 641 getuptime(&conn->wdata.to_event.expires); 1191 tv_add _diff(&conn->wdata.to_event.expires, usecs);642 tv_add(&conn->wdata.to_event.expires, usecs); 1192 643 } else 1193 644 conn->wdata.to_event.inlist = false; … … 1235 686 } 1236 687 1237 msg_t *msg = list_get_instance(list_first(&conn->msg_queue), 1238 msg_t, link); 688 msg_t *msg = list_get_instance(list_first(&conn->msg_queue), msg_t, link); 1239 689 list_remove(&msg->link); 1240 690 … … 1247 697 } 1248 698 699 static client_t *async_client_get(task_id_t client_id, bool create) 700 { 701 client_t *client = NULL; 702 703 futex_down(&async_futex); 704 ht_link_t *lnk = hash_table_find(&client_hash_table, &client_id); 705 if (lnk) { 706 client = hash_table_get_inst(lnk, client_t, link); 707 atomic_inc(&client->refcnt); 708 } else if (create) { 709 client = malloc(sizeof(client_t)); 710 if (client) { 711 client->in_task_id = client_id; 712 client->data = async_client_data_create(); 713 714 atomic_set(&client->refcnt, 1); 715 hash_table_insert(&client_hash_table, &client->link); 716 } 717 } 718 719 futex_up(&async_futex); 720 return client; 721 } 722 723 static void async_client_put(client_t *client) 724 { 725 bool destroy; 726 727 futex_down(&async_futex); 728 729 if (atomic_predec(&client->refcnt) == 0) { 730 hash_table_remove(&client_hash_table, &client->in_task_id); 731 destroy = true; 732 } else 733 destroy = false; 734 735 futex_up(&async_futex); 736 737 if (destroy) { 738 if (client->data) 739 async_client_data_destroy(client->data); 740 741 free(client); 742 } 743 } 744 1249 745 void *async_get_client_data(void) 1250 746 { … … 1258 754 if (!client) 1259 755 return NULL; 1260 1261 756 if (!client->data) { 1262 757 async_client_put(client); 1263 758 return NULL; 1264 759 } 1265 760 1266 761 return client->data; 1267 762 } … … 1270 765 { 1271 766 client_t *client = async_client_get(client_id, false); 1272 767 1273 768 assert(client); 1274 769 assert(client->data); 1275 770 1276 771 /* Drop the reference we got in async_get_client_data_by_hash(). */ 1277 772 async_client_put(client); 1278 773 1279 774 /* Drop our own reference we got at the beginning of this function. */ 1280 775 async_client_put(client); 1281 776 } 1282 777 1283 static port_t *async_find_port(iface_t iface, port_id_t port_id) 1284 { 1285 port_t *port = NULL; 1286 778 /** Wrapper for client connection fibril. 779 * 780 * When a new connection arrives, a fibril with this implementing function is 781 * created. It calls client_connection() and does the final cleanup. 782 * 783 * @param arg Connection structure pointer. 784 * 785 * @return Always zero. 786 * 787 */ 788 static int connection_fibril(void *arg) 789 { 790 assert(arg); 791 792 /* 793 * Setup fibril-local connection pointer. 794 */ 795 fibril_connection = (connection_t *) arg; 796 797 /* 798 * Add our reference for the current connection in the client task 799 * tracking structure. If this is the first reference, create and 800 * hash in a new tracking structure. 801 */ 802 803 client_t *client = async_client_get(fibril_connection->in_task_id, true); 804 if (!client) { 805 ipc_answer_0(fibril_connection->callid, ENOMEM); 806 return 0; 807 } 808 809 fibril_connection->client = client; 810 811 /* 812 * Call the connection handler function. 813 */ 814 fibril_connection->cfibril(fibril_connection->callid, 815 &fibril_connection->call, fibril_connection->carg); 816 817 /* 818 * Remove the reference for this client task connection. 819 */ 820 async_client_put(client); 821 822 /* 823 * Remove myself from the connection hash table. 824 */ 1287 825 futex_down(&async_futex); 1288 1289 ht_link_t *link = hash_table_find(&interface_hash_table, &iface); 1290 if (link) { 1291 interface_t *interface = 1292 hash_table_get_inst(link, interface_t, link); 1293 1294 link = hash_table_find(&interface->port_hash_table, &port_id); 1295 if (link) 1296 port = hash_table_get_inst(link, port_t, link); 1297 } 1298 826 hash_table_remove(&conn_hash_table, &fibril_connection->in_phone_hash); 1299 827 futex_up(&async_futex); 1300 828 1301 return port; 829 /* 830 * Answer all remaining messages with EHANGUP. 831 */ 832 while (!list_empty(&fibril_connection->msg_queue)) { 833 msg_t *msg = 834 list_get_instance(list_first(&fibril_connection->msg_queue), 835 msg_t, link); 836 837 list_remove(&msg->link); 838 ipc_answer_0(msg->callid, EHANGUP); 839 free(msg); 840 } 841 842 /* 843 * If the connection was hung-up, answer the last call, 844 * i.e. IPC_M_PHONE_HUNGUP. 845 */ 846 if (fibril_connection->close_callid) 847 ipc_answer_0(fibril_connection->close_callid, EOK); 848 849 free(fibril_connection); 850 return 0; 851 } 852 853 /** Create a new fibril for a new connection. 854 * 855 * Create new fibril for connection, fill in connection structures and insert 856 * it into the hash table, so that later we can easily do routing of messages to 857 * particular fibrils. 858 * 859 * @param in_task_id Identification of the incoming connection. 860 * @param in_phone_hash Identification of the incoming connection. 861 * @param callid Hash of the opening IPC_M_CONNECT_ME_TO call. 862 * If callid is zero, the connection was opened by 863 * accepting the IPC_M_CONNECT_TO_ME call and this function 864 * is called directly by the server. 865 * @param call Call data of the opening call. 866 * @param cfibril Fibril function that should be called upon opening the 867 * connection. 868 * @param carg Extra argument to pass to the connection fibril 869 * 870 * @return New fibril id or NULL on failure. 871 * 872 */ 873 fid_t async_new_connection(task_id_t in_task_id, sysarg_t in_phone_hash, 874 ipc_callid_t callid, ipc_call_t *call, 875 async_client_conn_t cfibril, void *carg) 876 { 877 connection_t *conn = malloc(sizeof(*conn)); 878 if (!conn) { 879 if (callid) 880 ipc_answer_0(callid, ENOMEM); 881 882 return (uintptr_t) NULL; 883 } 884 885 conn->in_task_id = in_task_id; 886 conn->in_phone_hash = in_phone_hash; 887 list_initialize(&conn->msg_queue); 888 conn->callid = callid; 889 conn->close_callid = 0; 890 conn->carg = carg; 891 892 if (call) 893 conn->call = *call; 894 895 /* We will activate the fibril ASAP */ 896 conn->wdata.active = true; 897 conn->cfibril = cfibril; 898 conn->wdata.fid = fibril_create(connection_fibril, conn); 899 900 if (conn->wdata.fid == 0) { 901 free(conn); 902 903 if (callid) 904 ipc_answer_0(callid, ENOMEM); 905 906 return (uintptr_t) NULL; 907 } 908 909 /* Add connection to the connection hash table */ 910 911 futex_down(&async_futex); 912 hash_table_insert(&conn_hash_table, &conn->link); 913 futex_up(&async_futex); 914 915 fibril_add_ready(conn->wdata.fid); 916 917 return conn->wdata.fid; 1302 918 } 1303 919 … … 1315 931 assert(call); 1316 932 1317 /* Kernel notification */933 /* Unrouted call - take some default action */ 1318 934 if ((callid & IPC_CALLID_NOTIFICATION)) { 1319 fibril_t *fibril = (fibril_t *) __tcb_get()->fibril_data;1320 unsigned oldsw = fibril->switches;1321 1322 935 process_notification(callid, call); 1323 1324 if (oldsw != fibril->switches) {1325 /*1326 * The notification handler did not execute atomically1327 * and so the current manager fibril assumed the role of1328 * a notification fibril. While waiting for its1329 * resources, it switched to another manager fibril that1330 * had already existed or it created a new one. We1331 * therefore know there is at least yet another1332 * manager fibril that can take over. We now kill the1333 * current 'notification' fibril to prevent fibril1334 * population explosion.1335 */1336 futex_down(&async_futex);1337 fibril_switch(FIBRIL_FROM_DEAD);1338 }1339 1340 936 return; 1341 937 } 1342 938 1343 /* New connection */ 1344 if (IPC_GET_IMETHOD(*call) == IPC_M_CONNECT_ME_TO) { 1345 iface_t iface = (iface_t) IPC_GET_ARG1(*call); 1346 sysarg_t in_phone_hash = IPC_GET_ARG5(*call); 1347 1348 async_notification_handler_t handler = fallback_port_handler; 1349 void *data = fallback_port_data; 1350 1351 // TODO: Currently ignores all ports but the first one 1352 port_t *port = async_find_port(iface, 0); 1353 if (port) { 1354 handler = port->handler; 1355 data = port->data; 1356 } 1357 1358 async_new_connection(call->in_task_id, in_phone_hash, callid, 1359 call, handler, data); 1360 return; 1361 } 1362 1363 /* Cloned connection */ 1364 if (IPC_GET_IMETHOD(*call) == IPC_M_CLONE_ESTABLISH) { 1365 // TODO: Currently ignores ports altogether 1366 939 switch (IPC_GET_IMETHOD(*call)) { 940 case IPC_M_CLONE_ESTABLISH: 941 case IPC_M_CONNECT_ME_TO: 1367 942 /* Open new connection with fibril, etc. */ 1368 943 async_new_connection(call->in_task_id, IPC_GET_ARG5(*call), 1369 callid, call, fallback_port_handler, fallback_port_data);944 callid, call, client_connection, NULL); 1370 945 return; 1371 946 } … … 1459 1034 1460 1035 } else { 1461 timeout = tv_sub_diff(&waiter->to_event.expires, 1462 &tv); 1036 timeout = tv_sub(&waiter->to_event.expires, &tv); 1463 1037 futex_up(&async_futex); 1464 1038 } … … 1512 1086 void async_create_manager(void) 1513 1087 { 1514 fid_t fid = fibril_create _generic(async_manager_fibril, NULL, PAGE_SIZE);1088 fid_t fid = fibril_create(async_manager_fibril, NULL); 1515 1089 if (fid != 0) 1516 1090 fibril_add_manager(fid); … … 1528 1102 void __async_init(void) 1529 1103 { 1530 if (!hash_table_create(&interface_hash_table, 0, 0,1531 &interface_hash_table_ops))1532 abort();1533 1534 1104 if (!hash_table_create(&client_hash_table, 0, 0, &client_hash_table_ops)) 1535 1105 abort(); 1536 1106 1537 1107 if (!hash_table_create(&conn_hash_table, 0, 0, &conn_hash_table_ops)) 1538 abort();1539 1540 if (!hash_table_create(¬ification_hash_table, 0, 0,1541 ¬ification_hash_table_ops))1542 1108 abort(); 1543 1109 … … 1546 1112 abort(); 1547 1113 1548 session_ns->iface = 0;1549 1114 session_ns->mgmt = EXCHANGE_ATOMIC; 1550 1115 session_ns->phone = PHONE_NS; … … 1593 1158 1594 1159 msg->done = true; 1595 1160 1596 1161 if (msg->forget) { 1597 1162 assert(msg->wdata.active); … … 1601 1166 fibril_add_ready(msg->wdata.fid); 1602 1167 } 1603 1168 1604 1169 futex_up(&async_futex); 1605 1170 } … … 1636 1201 1637 1202 ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, msg, 1638 reply_received );1203 reply_received, true); 1639 1204 1640 1205 return (aid_t) msg; … … 1674 1239 1675 1240 ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, arg5, 1676 msg, reply_received );1241 msg, reply_received, true); 1677 1242 1678 1243 return (aid_t) msg; … … 1693 1258 1694 1259 futex_down(&async_futex); 1695 1260 1696 1261 assert(!msg->forget); 1697 1262 assert(!msg->destroyed); 1698 1263 1699 1264 if (msg->done) { 1700 1265 futex_up(&async_futex); … … 1737 1302 1738 1303 amsg_t *msg = (amsg_t *) amsgid; 1739 1304 1740 1305 futex_down(&async_futex); 1741 1306 1742 1307 assert(!msg->forget); 1743 1308 assert(!msg->destroyed); 1744 1309 1745 1310 if (msg->done) { 1746 1311 futex_up(&async_futex); … … 1754 1319 if (timeout < 0) 1755 1320 timeout = 0; 1756 1321 1757 1322 getuptime(&msg->wdata.to_event.expires); 1758 tv_add _diff(&msg->wdata.to_event.expires, timeout);1323 tv_add(&msg->wdata.to_event.expires, timeout); 1759 1324 1760 1325 /* … … 1807 1372 { 1808 1373 amsg_t *msg = (amsg_t *) amsgid; 1809 1374 1810 1375 assert(msg); 1811 1376 assert(!msg->forget); 1812 1377 assert(!msg->destroyed); 1813 1378 1814 1379 futex_down(&async_futex); 1815 1816 1380 if (msg->done) { 1817 1381 amsg_destroy(msg); … … 1820 1384 msg->forget = true; 1821 1385 } 1822 1823 1386 futex_up(&async_futex); 1824 1387 } … … 1840 1403 1841 1404 getuptime(&msg->wdata.to_event.expires); 1842 tv_add _diff(&msg->wdata.to_event.expires, timeout);1405 tv_add(&msg->wdata.to_event.expires, timeout); 1843 1406 1844 1407 futex_down(&async_futex); … … 1963 1526 { 1964 1527 if (exch != NULL) 1965 ipc_call_async_0(exch->phone, imethod, NULL, NULL );1528 ipc_call_async_0(exch->phone, imethod, NULL, NULL, true); 1966 1529 } 1967 1530 … … 1969 1532 { 1970 1533 if (exch != NULL) 1971 ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL );1534 ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL, true); 1972 1535 } 1973 1536 … … 1976 1539 { 1977 1540 if (exch != NULL) 1978 ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL); 1541 ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL, 1542 true); 1979 1543 } 1980 1544 … … 1984 1548 if (exch != NULL) 1985 1549 ipc_call_async_3(exch->phone, imethod, arg1, arg2, arg3, NULL, 1986 NULL );1550 NULL, true); 1987 1551 } 1988 1552 … … 1992 1556 if (exch != NULL) 1993 1557 ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, 1994 NULL, NULL );1558 NULL, NULL, true); 1995 1559 } 1996 1560 … … 2000 1564 if (exch != NULL) 2001 1565 ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, 2002 arg5, NULL, NULL );1566 arg5, NULL, NULL, true); 2003 1567 } 2004 1568 … … 2065 1629 * @param arg2 User defined argument. 2066 1630 * @param arg3 User defined argument. 1631 * @param client_receiver Connection handing routine. 2067 1632 * 2068 1633 * @return Zero on success or a negative error code. … … 2070 1635 */ 2071 1636 int async_connect_to_me(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2, 2072 sysarg_t arg3 )1637 sysarg_t arg3, async_client_conn_t client_receiver, void *carg) 2073 1638 { 2074 1639 if (exch == NULL) 2075 1640 return ENOENT; 2076 1641 1642 sysarg_t phone_hash; 1643 sysarg_t rc; 1644 1645 aid_t req; 2077 1646 ipc_call_t answer; 2078 aid_treq = async_send_3(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,1647 req = async_send_3(exch, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 2079 1648 &answer); 2080 2081 sysarg_t rc;2082 1649 async_wait_for(req, &rc); 2083 1650 if (rc != EOK) 2084 1651 return (int) rc; 1652 1653 phone_hash = IPC_GET_ARG5(answer); 1654 1655 if (client_receiver != NULL) 1656 async_new_connection(answer.in_task_id, phone_hash, 0, NULL, 1657 client_receiver, carg); 2085 1658 2086 1659 return EOK; … … 2123 1696 2124 1697 ipc_call_async_0(exch->phone, IPC_M_CLONE_ESTABLISH, msg, 2125 reply_received );1698 reply_received, true); 2126 1699 2127 1700 sysarg_t rc; … … 2142 1715 } 2143 1716 2144 sess->iface = 0;2145 1717 sess->mgmt = mgmt; 2146 1718 sess->phone = phone; … … 2172 1744 2173 1745 ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, arg4, 2174 msg, reply_received );1746 msg, reply_received, true); 2175 1747 2176 1748 sysarg_t rc; … … 2212 1784 int phone = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3, 2213 1785 0); 1786 2214 1787 if (phone < 0) { 2215 1788 errno = phone; … … 2218 1791 } 2219 1792 2220 sess->iface = 0;2221 1793 sess->mgmt = mgmt; 2222 1794 sess->phone = phone; … … 2235 1807 } 2236 1808 2237 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.2238 *2239 * Ask through phone for a new connection to some service and block until2240 * success.2241 *2242 * @param exch Exchange for sending the message.2243 * @param iface Connection interface.2244 * @param arg2 User defined argument.2245 * @param arg3 User defined argument.2246 *2247 * @return New session on success or NULL on error.2248 *2249 */2250 async_sess_t *async_connect_me_to_iface(async_exch_t *exch, iface_t iface,2251 sysarg_t arg2, sysarg_t arg3)2252 {2253 if (exch == NULL) {2254 errno = ENOENT;2255 return NULL;2256 }2257 2258 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));2259 if (sess == NULL) {2260 errno = ENOMEM;2261 return NULL;2262 }2263 2264 int phone = async_connect_me_to_internal(exch->phone, iface, arg2,2265 arg3, 0);2266 if (phone < 0) {2267 errno = phone;2268 free(sess);2269 return NULL;2270 }2271 2272 sess->iface = iface;2273 sess->phone = phone;2274 sess->arg1 = iface;2275 sess->arg2 = arg2;2276 sess->arg3 = arg3;2277 2278 fibril_mutex_initialize(&sess->remote_state_mtx);2279 sess->remote_state_data = NULL;2280 2281 list_initialize(&sess->exch_list);2282 fibril_mutex_initialize(&sess->mutex);2283 atomic_set(&sess->refcnt, 0);2284 2285 return sess;2286 }2287 2288 1809 /** Set arguments for new connections. 2289 1810 * … … 2341 1862 } 2342 1863 2343 sess->iface = 0;2344 1864 sess->mgmt = mgmt; 2345 1865 sess->phone = phone; … … 2358 1878 } 2359 1879 2360 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.2361 *2362 * Ask through phone for a new connection to some service and block until2363 * success.2364 *2365 * @param exch Exchange for sending the message.2366 * @param iface Connection interface.2367 * @param arg2 User defined argument.2368 * @param arg3 User defined argument.2369 *2370 * @return New session on success or NULL on error.2371 *2372 */2373 async_sess_t *async_connect_me_to_blocking_iface(async_exch_t *exch, iface_t iface,2374 sysarg_t arg2, sysarg_t arg3)2375 {2376 if (exch == NULL) {2377 errno = ENOENT;2378 return NULL;2379 }2380 2381 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));2382 if (sess == NULL) {2383 errno = ENOMEM;2384 return NULL;2385 }2386 2387 int phone = async_connect_me_to_internal(exch->phone, iface, arg2,2388 arg3, IPC_FLAG_BLOCKING);2389 if (phone < 0) {2390 errno = phone;2391 free(sess);2392 return NULL;2393 }2394 2395 sess->iface = iface;2396 sess->phone = phone;2397 sess->arg1 = iface;2398 sess->arg2 = arg2;2399 sess->arg3 = arg3;2400 2401 fibril_mutex_initialize(&sess->remote_state_mtx);2402 sess->remote_state_data = NULL;2403 2404 list_initialize(&sess->exch_list);2405 fibril_mutex_initialize(&sess->mutex);2406 atomic_set(&sess->refcnt, 0);2407 2408 return sess;2409 }2410 2411 1880 /** Connect to a task specified by id. 2412 1881 * … … 2427 1896 } 2428 1897 2429 sess->iface = 0;2430 1898 sess->mgmt = EXCHANGE_ATOMIC; 2431 1899 sess->phone = phone; … … 2505 1973 return NULL; 2506 1974 2507 exch_mgmt_t mgmt = sess->mgmt; 2508 if (sess->iface != 0) 2509 mgmt = sess->iface & IFACE_EXCHANGE_MASK; 2510 2511 async_exch_t *exch = NULL; 1975 async_exch_t *exch; 2512 1976 2513 1977 fibril_mutex_lock(&async_sess_mutex); … … 2528 1992 */ 2529 1993 2530 if (( mgmt == EXCHANGE_ATOMIC) ||2531 ( mgmt == EXCHANGE_SERIALIZE)) {1994 if ((sess->mgmt == EXCHANGE_ATOMIC) || 1995 (sess->mgmt == EXCHANGE_SERIALIZE)) { 2532 1996 exch = (async_exch_t *) malloc(sizeof(async_exch_t)); 2533 1997 if (exch != NULL) { … … 2537 2001 exch->phone = sess->phone; 2538 2002 } 2539 } else if (mgmt == EXCHANGE_PARALLEL) { 2540 int phone; 2541 2542 retry: 2003 } else { /* EXCHANGE_PARALLEL */ 2543 2004 /* 2544 2005 * Make a one-time attempt to connect a new data phone. 2545 2006 */ 2007 2008 int phone; 2009 2010 retry: 2546 2011 phone = async_connect_me_to_internal(sess->phone, sess->arg1, 2547 2012 sess->arg2, sess->arg3, 0); … … 2585 2050 atomic_inc(&sess->refcnt); 2586 2051 2587 if ( mgmt == EXCHANGE_SERIALIZE)2052 if (sess->mgmt == EXCHANGE_SERIALIZE) 2588 2053 fibril_mutex_lock(&sess->mutex); 2589 2054 } … … 2605 2070 assert(sess != NULL); 2606 2071 2607 exch_mgmt_t mgmt = sess->mgmt;2608 if (sess->iface != 0)2609 mgmt = sess->iface & IFACE_EXCHANGE_MASK;2610 2611 2072 atomic_dec(&sess->refcnt); 2612 2073 2613 if ( mgmt == EXCHANGE_SERIALIZE)2074 if (sess->mgmt == EXCHANGE_SERIALIZE) 2614 2075 fibril_mutex_unlock(&sess->mutex); 2615 2076 … … 2820 2281 bool async_data_read_receive(ipc_callid_t *callid, size_t *size) 2821 2282 { 2283 assert(callid); 2284 2822 2285 ipc_call_t data; 2823 return async_data_read_receive_call(callid, &data, size); 2824 } 2825 2826 /** Wrapper for receiving the IPC_M_DATA_READ calls using the async framework. 2827 * 2828 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ 2829 * calls so that the user doesn't have to remember the meaning of each IPC 2830 * argument. 2831 * 2832 * So far, this wrapper is to be used from within a connection fibril. 2833 * 2834 * @param callid Storage for the hash of the IPC_M_DATA_READ. 2835 * @param size Storage for the maximum size. Can be NULL. 2836 * 2837 * @return True on success, false on failure. 2838 * 2839 */ 2840 bool async_data_read_receive_call(ipc_callid_t *callid, ipc_call_t *data, 2841 size_t *size) 2842 { 2843 assert(callid); 2844 assert(data); 2845 2846 *callid = async_get_call(data); 2847 2848 if (IPC_GET_IMETHOD(*data) != IPC_M_DATA_READ) 2286 *callid = async_get_call(&data); 2287 2288 if (IPC_GET_IMETHOD(data) != IPC_M_DATA_READ) 2849 2289 return false; 2850 2290 2851 2291 if (size) 2852 *size = (size_t) IPC_GET_ARG2( *data);2292 *size = (size_t) IPC_GET_ARG2(data); 2853 2293 2854 2294 return true; … … 2945 2385 bool async_data_write_receive(ipc_callid_t *callid, size_t *size) 2946 2386 { 2387 assert(callid); 2388 2947 2389 ipc_call_t data; 2948 return async_data_write_receive_call(callid, &data, size); 2949 } 2950 2951 /** Wrapper for receiving the IPC_M_DATA_WRITE calls using the async framework. 2952 * 2953 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE 2954 * calls so that the user doesn't have to remember the meaning of each IPC 2955 * argument. 2956 * 2957 * So far, this wrapper is to be used from within a connection fibril. 2958 * 2959 * @param callid Storage for the hash of the IPC_M_DATA_WRITE. 2960 * @param data Storage for the ipc call data. 2961 * @param size Storage for the suggested size. May be NULL. 2962 * 2963 * @return True on success, false on failure. 2964 * 2965 */ 2966 bool async_data_write_receive_call(ipc_callid_t *callid, ipc_call_t *data, 2967 size_t *size) 2968 { 2969 assert(callid); 2970 assert(data); 2971 2972 *callid = async_get_call(data); 2973 2974 if (IPC_GET_IMETHOD(*data) != IPC_M_DATA_WRITE) 2390 *callid = async_get_call(&data); 2391 2392 if (IPC_GET_IMETHOD(data) != IPC_M_DATA_WRITE) 2975 2393 return false; 2976 2394 2977 2395 if (size) 2978 *size = (size_t) IPC_GET_ARG2( *data);2396 *size = (size_t) IPC_GET_ARG2(data); 2979 2397 2980 2398 return true; … … 3048 2466 } 3049 2467 3050 void * arg_data;2468 void *_data; 3051 2469 3052 2470 if (nullterm) 3053 arg_data = malloc(size + 1);2471 _data = malloc(size + 1); 3054 2472 else 3055 arg_data = malloc(size);3056 3057 if ( arg_data == NULL) {2473 _data = malloc(size); 2474 2475 if (_data == NULL) { 3058 2476 ipc_answer_0(callid, ENOMEM); 3059 2477 return ENOMEM; 3060 2478 } 3061 2479 3062 int rc = async_data_write_finalize(callid, arg_data, size);2480 int rc = async_data_write_finalize(callid, _data, size); 3063 2481 if (rc != EOK) { 3064 free( arg_data);2482 free(_data); 3065 2483 return rc; 3066 2484 } 3067 2485 3068 2486 if (nullterm) 3069 ((char *) arg_data)[size] = 0;3070 3071 *data = arg_data;2487 ((char *) _data)[size] = 0; 2488 2489 *data = _data; 3072 2490 if (received != NULL) 3073 2491 *received = size; … … 3167 2585 } 3168 2586 3169 sess->iface = 0;3170 2587 sess->mgmt = mgmt; 3171 2588 sess->phone = phone; … … 3217 2634 } 3218 2635 3219 sess->iface = 0;3220 2636 sess->mgmt = mgmt; 3221 2637 sess->phone = phone; … … 3263 2679 return NULL; 3264 2680 3265 sess->iface = 0;3266 2681 sess->mgmt = mgmt; 3267 2682 sess->phone = phone; … … 3291 2706 { 3292 2707 assert(callid); 3293 2708 3294 2709 ipc_call_t call; 3295 2710 *callid = async_get_call(&call); 3296 2711 3297 2712 if (IPC_GET_IMETHOD(call) != IPC_M_STATE_CHANGE_AUTHORIZE) 3298 2713 return false; … … 3304 2719 if (arg3) 3305 2720 *arg3 = IPC_GET_ARG3(call); 3306 2721 3307 2722 return true; 3308 2723 } … … 3383 2798 } 3384 2799 3385 void *async_as_area_create(void *base, size_t size, unsigned int flags,3386 async_sess_t *pager, sysarg_t id1, sysarg_t id2, sysarg_t id3)3387 {3388 as_area_pager_info_t pager_info = {3389 .pager = pager->phone,3390 .id1 = id1,3391 .id2 = id2,3392 .id3 = id33393 };3394 return as_area_create(base, size, flags, &pager_info);3395 }3396 3397 2800 /** @} 3398 2801 */
Note:
See TracChangeset
for help on using the changeset viewer.