Changeset 49a796f1 in mainline
- Timestamp:
- 2018-05-31T16:11:01Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c8afd5a
- Parents:
- fda19b8
- git-author:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-05-31 15:19:10)
- git-committer:
- Jiří Zárevúcky <jiri.zarevucky@…> (2018-05-31 16:11:01)
- Location:
- uspace/lib/c
- Files:
-
- 2 added
- 5 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/Makefile
rfda19b8 r49a796f1 134 134 generic/ipc.c \ 135 135 generic/ns.c \ 136 generic/async.c \ 136 generic/async/client.c \ 137 generic/async/server.c \ 138 generic/async/ports.c \ 137 139 generic/loader.c \ 138 140 generic/getopt.c \ -
uspace/lib/c/generic/async/server.c
rfda19b8 r49a796f1 98 98 #include <ipc/ipc.h> 99 99 #include <async.h> 100 #include " private/async.h"100 #include "../private/async.h" 101 101 #undef LIBC_ASYNC_C_ 102 102 … … 119 119 #include <as.h> 120 120 #include <abi/mm/as.h> 121 #include "private/libc.h" 122 123 /** Session data */ 124 struct async_sess { 125 /** List of inactive exchanges */ 126 list_t exch_list; 127 128 /** Session interface */ 129 iface_t iface; 130 131 /** Exchange management style */ 132 exch_mgmt_t mgmt; 133 134 /** Session identification */ 135 cap_phone_handle_t phone; 136 137 /** First clone connection argument */ 138 sysarg_t arg1; 139 140 /** Second clone connection argument */ 141 sysarg_t arg2; 142 143 /** Third clone connection argument */ 144 sysarg_t arg3; 145 146 /** Exchange mutex */ 147 fibril_mutex_t mutex; 148 149 /** Number of opened exchanges */ 150 atomic_t refcnt; 151 152 /** Mutex for stateful connections */ 153 fibril_mutex_t remote_state_mtx; 154 155 /** Data for stateful connections */ 156 void *remote_state_data; 157 }; 158 159 /** Exchange data */ 160 struct async_exch { 161 /** Link into list of inactive exchanges */ 162 link_t sess_link; 163 164 /** Link into global list of inactive exchanges */ 165 link_t global_link; 166 167 /** Session pointer */ 168 async_sess_t *sess; 169 170 /** Exchange identification */ 171 cap_phone_handle_t phone; 172 }; 121 #include "../private/libc.h" 173 122 174 123 /** Async framework global futex */ … … 177 126 /** Number of threads waiting for IPC in the kernel. */ 178 127 atomic_t threads_in_ipc_wait = { 0 }; 179 180 /** Naming service session */181 async_sess_t *session_ns;182 128 183 129 /** Call data */ … … 188 134 ipc_call_t call; 189 135 } msg_t; 190 191 /** Message data */192 typedef struct {193 awaiter_t wdata;194 195 /** If reply was received. */196 bool done;197 198 /** If the message / reply should be discarded on arrival. */199 bool forget;200 201 /** If already destroyed. */202 bool destroyed;203 204 /** Pointer to where the answer data is stored. */205 ipc_call_t *dataptr;206 207 errno_t retval;208 } amsg_t;209 136 210 137 /* Client connection data */ … … 252 179 } connection_t; 253 180 254 /** Interface data */255 typedef struct {256 ht_link_t link;257 258 /** Interface ID */259 iface_t iface;260 261 /** Futex protecting the hash table */262 futex_t futex;263 264 /** Interface ports */265 hash_table_t port_hash_table;266 267 /** Next available port ID */268 port_id_t port_id_avail;269 } interface_t;270 271 /* Port data */272 typedef struct {273 ht_link_t link;274 275 /** Port ID */276 port_id_t id;277 278 /** Port connection handler */279 async_port_handler_t handler;280 281 /** Client data */282 void *data;283 } port_t;284 285 181 /* Notification data */ 286 182 typedef struct { … … 299 195 /** Identifier of the incoming connection handled by the current fibril. */ 300 196 static fibril_local connection_t *fibril_connection; 301 302 static void to_event_initialize(to_event_t *to)303 {304 struct timeval tv = { 0, 0 };305 306 to->inlist = false;307 to->occurred = false;308 link_initialize(&to->link);309 to->expires = tv;310 }311 312 static void wu_event_initialize(wu_event_t *wu)313 {314 wu->inlist = false;315 link_initialize(&wu->link);316 }317 318 void awaiter_initialize(awaiter_t *aw)319 {320 aw->fid = 0;321 aw->active = false;322 to_event_initialize(&aw->to_event);323 wu_event_initialize(&aw->wu_event);324 }325 326 static amsg_t *amsg_create(void)327 {328 amsg_t *msg = malloc(sizeof(amsg_t));329 if (msg) {330 msg->done = false;331 msg->forget = false;332 msg->destroyed = false;333 msg->dataptr = NULL;334 msg->retval = EINVAL;335 awaiter_initialize(&msg->wdata);336 }337 338 return msg;339 }340 341 static void amsg_destroy(amsg_t *msg)342 {343 assert(!msg->destroyed);344 msg->destroyed = true;345 free(msg);346 }347 197 348 198 static void *default_client_data_constructor(void) … … 370 220 assert(async_client_data_destroy == default_client_data_destructor); 371 221 async_client_data_destroy = dtor; 372 }373 374 /** Default fallback fibril function.375 *376 * This fallback fibril function gets called on incomming connections that do377 * not have a specific handler defined.378 *379 * @param chandle Handle of the incoming call.380 * @param call Data of the incoming call.381 * @param arg Local argument382 *383 */384 static void default_fallback_port_handler(cap_call_handle_t chandle,385 ipc_call_t *call, void *arg)386 {387 ipc_answer_0(chandle, ENOENT);388 }389 390 static async_port_handler_t fallback_port_handler =391 default_fallback_port_handler;392 static void *fallback_port_data = NULL;393 394 static hash_table_t interface_hash_table;395 396 static size_t interface_key_hash(void *key)397 {398 iface_t iface = *(iface_t *) key;399 return iface;400 }401 402 static size_t interface_hash(const ht_link_t *item)403 {404 interface_t *interface = hash_table_get_inst(item, interface_t, link);405 return interface_key_hash(&interface->iface);406 }407 408 static bool interface_key_equal(void *key, const ht_link_t *item)409 {410 iface_t iface = *(iface_t *) key;411 interface_t *interface = hash_table_get_inst(item, interface_t, link);412 return iface == interface->iface;413 }414 415 /** Operations for the port hash table. */416 static hash_table_ops_t interface_hash_table_ops = {417 .hash = interface_hash,418 .key_hash = interface_key_hash,419 .key_equal = interface_key_equal,420 .equal = NULL,421 .remove_callback = NULL422 };423 424 static size_t port_key_hash(void *key)425 {426 port_id_t port_id = *(port_id_t *) key;427 return port_id;428 }429 430 static size_t port_hash(const ht_link_t *item)431 {432 port_t *port = hash_table_get_inst(item, port_t, link);433 return port_key_hash(&port->id);434 }435 436 static bool port_key_equal(void *key, const ht_link_t *item)437 {438 port_id_t port_id = *(port_id_t *) key;439 port_t *port = hash_table_get_inst(item, port_t, link);440 return port_id == port->id;441 }442 443 /** Operations for the port hash table. */444 static hash_table_ops_t port_hash_table_ops = {445 .hash = port_hash,446 .key_hash = port_key_hash,447 .key_equal = port_key_equal,448 .equal = NULL,449 .remove_callback = NULL450 };451 452 static interface_t *async_new_interface(iface_t iface)453 {454 interface_t *interface =455 (interface_t *) malloc(sizeof(interface_t));456 if (!interface)457 return NULL;458 459 bool ret = hash_table_create(&interface->port_hash_table, 0, 0,460 &port_hash_table_ops);461 if (!ret) {462 free(interface);463 return NULL;464 }465 466 interface->iface = iface;467 futex_initialize(&interface->futex, 1);468 interface->port_id_avail = 0;469 470 hash_table_insert(&interface_hash_table, &interface->link);471 472 return interface;473 }474 475 static port_t *async_new_port(interface_t *interface,476 async_port_handler_t handler, void *data)477 {478 port_t *port = (port_t *) malloc(sizeof(port_t));479 if (!port)480 return NULL;481 482 futex_down(&interface->futex);483 484 port_id_t id = interface->port_id_avail;485 interface->port_id_avail++;486 487 port->id = id;488 port->handler = handler;489 port->data = data;490 491 hash_table_insert(&interface->port_hash_table, &port->link);492 493 futex_up(&interface->futex);494 495 return port;496 }497 498 /** Mutex protecting inactive_exch_list and avail_phone_cv.499 *500 */501 static FIBRIL_MUTEX_INITIALIZE(async_sess_mutex);502 503 /** List of all currently inactive exchanges.504 *505 */506 static LIST_INITIALIZE(inactive_exch_list);507 508 /** Condition variable to wait for a phone to become available.509 *510 */511 static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);512 513 static errno_t async_create_port_internal(iface_t iface,514 async_port_handler_t handler, void *data, port_id_t *port_id)515 {516 interface_t *interface;517 518 futex_down(&async_futex);519 520 ht_link_t *link = hash_table_find(&interface_hash_table, &iface);521 if (link)522 interface = hash_table_get_inst(link, interface_t, link);523 else524 interface = async_new_interface(iface);525 526 if (!interface) {527 futex_up(&async_futex);528 return ENOMEM;529 }530 531 port_t *port = async_new_port(interface, handler, data);532 if (!port) {533 futex_up(&async_futex);534 return ENOMEM;535 }536 537 *port_id = port->id;538 539 futex_up(&async_futex);540 541 return EOK;542 }543 544 errno_t async_create_port(iface_t iface, async_port_handler_t handler,545 void *data, port_id_t *port_id)546 {547 if ((iface & IFACE_MOD_MASK) == IFACE_MOD_CALLBACK)548 return EINVAL;549 550 return async_create_port_internal(iface, handler, data, port_id);551 }552 553 void async_set_fallback_port_handler(async_port_handler_t handler, void *data)554 {555 assert(handler != NULL);556 557 fallback_port_handler = handler;558 fallback_port_data = data;559 222 } 560 223 … … 1295 958 } 1296 959 1297 static port_t *async_find_port(iface_t iface, port_id_t port_id)1298 {1299 port_t *port = NULL;1300 1301 futex_down(&async_futex);1302 1303 ht_link_t *link = hash_table_find(&interface_hash_table, &iface);1304 if (link) {1305 interface_t *interface =1306 hash_table_get_inst(link, interface_t, link);1307 1308 link = hash_table_find(&interface->port_hash_table, &port_id);1309 if (link)1310 port = hash_table_get_inst(link, port_t, link);1311 }1312 1313 futex_up(&async_futex);1314 1315 return port;1316 }1317 1318 960 /** Handle a call that was received. 1319 961 * … … 1360 1002 sysarg_t in_phone_hash = IPC_GET_ARG5(*call); 1361 1003 1362 async_port_handler_t handler = fallback_port_handler; 1363 void *data = fallback_port_data; 1364 1365 // TODO: Currently ignores all ports but the first one 1366 port_t *port = async_find_port(iface, 0); 1367 if (port) { 1368 handler = port->handler; 1369 data = port->data; 1370 } 1004 // TODO: Currently ignores all ports but the first one. 1005 void *data; 1006 async_port_handler_t handler = 1007 async_get_port_handler(iface, 0, &data); 1371 1008 1372 1009 async_new_connection(call->in_task_id, in_phone_hash, chandle, … … 1536 1173 * 1537 1174 */ 1538 void __async_init(void) 1539 { 1540 if (!hash_table_create(&interface_hash_table, 0, 0, 1541 &interface_hash_table_ops)) 1542 abort(); 1543 1175 void __async_server_init(void) 1176 { 1544 1177 if (!hash_table_create(&client_hash_table, 0, 0, &client_hash_table_ops)) 1545 1178 abort(); … … 1551 1184 ¬ification_hash_table_ops)) 1552 1185 abort(); 1553 1554 session_ns = (async_sess_t *) malloc(sizeof(async_sess_t));1555 if (session_ns == NULL)1556 abort();1557 1558 session_ns->iface = 0;1559 session_ns->mgmt = EXCHANGE_ATOMIC;1560 session_ns->phone = PHONE_NS;1561 session_ns->arg1 = 0;1562 session_ns->arg2 = 0;1563 session_ns->arg3 = 0;1564 1565 fibril_mutex_initialize(&session_ns->remote_state_mtx);1566 session_ns->remote_state_data = NULL;1567 1568 list_initialize(&session_ns->exch_list);1569 fibril_mutex_initialize(&session_ns->mutex);1570 atomic_set(&session_ns->refcnt, 0);1571 }1572 1573 /** Reply received callback.1574 *1575 * This function is called whenever a reply for an asynchronous message sent out1576 * by the asynchronous framework is received.1577 *1578 * Notify the fibril which is waiting for this message that it has arrived.1579 *1580 * @param arg Pointer to the asynchronous message record.1581 * @param retval Value returned in the answer.1582 * @param data Call data of the answer.1583 *1584 */1585 void reply_received(void *arg, errno_t retval, ipc_call_t *data)1586 {1587 assert(arg);1588 1589 futex_down(&async_futex);1590 1591 amsg_t *msg = (amsg_t *) arg;1592 msg->retval = retval;1593 1594 /* Copy data after futex_down, just in case the call was detached */1595 if ((msg->dataptr) && (data))1596 *msg->dataptr = *data;1597 1598 write_barrier();1599 1600 /* Remove message from timeout list */1601 if (msg->wdata.to_event.inlist)1602 list_remove(&msg->wdata.to_event.link);1603 1604 msg->done = true;1605 1606 if (msg->forget) {1607 assert(msg->wdata.active);1608 amsg_destroy(msg);1609 } else if (!msg->wdata.active) {1610 msg->wdata.active = true;1611 fibril_add_ready(msg->wdata.fid);1612 }1613 1614 futex_up(&async_futex);1615 }1616 1617 /** Send message and return id of the sent message.1618 *1619 * The return value can be used as input for async_wait() to wait for1620 * completion.1621 *1622 * @param exch Exchange for sending the message.1623 * @param imethod Service-defined interface and method.1624 * @param arg1 Service-defined payload argument.1625 * @param arg2 Service-defined payload argument.1626 * @param arg3 Service-defined payload argument.1627 * @param arg4 Service-defined payload argument.1628 * @param dataptr If non-NULL, storage where the reply data will be stored.1629 *1630 * @return Hash of the sent message or 0 on error.1631 *1632 */1633 aid_t async_send_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,1634 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)1635 {1636 if (exch == NULL)1637 return 0;1638 1639 amsg_t *msg = amsg_create();1640 if (msg == NULL)1641 return 0;1642 1643 msg->dataptr = dataptr;1644 msg->wdata.active = true;1645 1646 ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, msg,1647 reply_received);1648 1649 return (aid_t) msg;1650 }1651 1652 /** Send message and return id of the sent message1653 *1654 * The return value can be used as input for async_wait() to wait for1655 * completion.1656 *1657 * @param exch Exchange for sending the message.1658 * @param imethod Service-defined interface and method.1659 * @param arg1 Service-defined payload argument.1660 * @param arg2 Service-defined payload argument.1661 * @param arg3 Service-defined payload argument.1662 * @param arg4 Service-defined payload argument.1663 * @param arg5 Service-defined payload argument.1664 * @param dataptr If non-NULL, storage where the reply data will be1665 * stored.1666 *1667 * @return Hash of the sent message or 0 on error.1668 *1669 */1670 aid_t async_send_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,1671 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,1672 ipc_call_t *dataptr)1673 {1674 if (exch == NULL)1675 return 0;1676 1677 amsg_t *msg = amsg_create();1678 if (msg == NULL)1679 return 0;1680 1681 msg->dataptr = dataptr;1682 msg->wdata.active = true;1683 1684 ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, arg5,1685 msg, reply_received);1686 1687 return (aid_t) msg;1688 }1689 1690 /** Wait for a message sent by the async framework.1691 *1692 * @param amsgid Hash of the message to wait for.1693 * @param retval Pointer to storage where the retval of the answer will1694 * be stored.1695 *1696 */1697 void async_wait_for(aid_t amsgid, errno_t *retval)1698 {1699 assert(amsgid);1700 1701 amsg_t *msg = (amsg_t *) amsgid;1702 1703 futex_down(&async_futex);1704 1705 assert(!msg->forget);1706 assert(!msg->destroyed);1707 1708 if (msg->done) {1709 futex_up(&async_futex);1710 goto done;1711 }1712 1713 msg->wdata.fid = fibril_get_id();1714 msg->wdata.active = false;1715 msg->wdata.to_event.inlist = false;1716 1717 /* Leave the async_futex locked when entering this function */1718 fibril_switch(FIBRIL_TO_MANAGER);1719 1720 /* Futex is up automatically after fibril_switch */1721 1722 done:1723 if (retval)1724 *retval = msg->retval;1725 1726 amsg_destroy(msg);1727 }1728 1729 /** Wait for a message sent by the async framework, timeout variant.1730 *1731 * If the wait times out, the caller may choose to either wait again by calling1732 * async_wait_for() or async_wait_timeout(), or forget the message via1733 * async_forget().1734 *1735 * @param amsgid Hash of the message to wait for.1736 * @param retval Pointer to storage where the retval of the answer will1737 * be stored.1738 * @param timeout Timeout in microseconds.1739 *1740 * @return Zero on success, ETIMEOUT if the timeout has expired.1741 *1742 */1743 errno_t async_wait_timeout(aid_t amsgid, errno_t *retval, suseconds_t timeout)1744 {1745 assert(amsgid);1746 1747 amsg_t *msg = (amsg_t *) amsgid;1748 1749 futex_down(&async_futex);1750 1751 assert(!msg->forget);1752 assert(!msg->destroyed);1753 1754 if (msg->done) {1755 futex_up(&async_futex);1756 goto done;1757 }1758 1759 /*1760 * Negative timeout is converted to zero timeout to avoid1761 * using tv_add with negative augmenter.1762 */1763 if (timeout < 0)1764 timeout = 0;1765 1766 getuptime(&msg->wdata.to_event.expires);1767 tv_add_diff(&msg->wdata.to_event.expires, timeout);1768 1769 /*1770 * Current fibril is inserted as waiting regardless of the1771 * "size" of the timeout.1772 *1773 * Checking for msg->done and immediately bailing out when1774 * timeout == 0 would mean that the manager fibril would never1775 * run (consider single threaded program).1776 * Thus the IPC answer would be never retrieved from the kernel.1777 *1778 * Notice that the actual delay would be very small because we1779 * - switch to manager fibril1780 * - the manager sees expired timeout1781 * - and thus adds us back to ready queue1782 * - manager switches back to some ready fibril1783 * (prior it, it checks for incoming IPC).1784 *1785 */1786 msg->wdata.fid = fibril_get_id();1787 msg->wdata.active = false;1788 async_insert_timeout(&msg->wdata);1789 1790 /* Leave the async_futex locked when entering this function */1791 fibril_switch(FIBRIL_TO_MANAGER);1792 1793 /* Futex is up automatically after fibril_switch */1794 1795 if (!msg->done)1796 return ETIMEOUT;1797 1798 done:1799 if (retval)1800 *retval = msg->retval;1801 1802 amsg_destroy(msg);1803 1804 return 0;1805 }1806 1807 /** Discard the message / reply on arrival.1808 *1809 * The message will be marked to be discarded once the reply arrives in1810 * reply_received(). It is not allowed to call async_wait_for() or1811 * async_wait_timeout() on this message after a call to this function.1812 *1813 * @param amsgid Hash of the message to forget.1814 */1815 void async_forget(aid_t amsgid)1816 {1817 amsg_t *msg = (amsg_t *) amsgid;1818 1819 assert(msg);1820 assert(!msg->forget);1821 assert(!msg->destroyed);1822 1823 futex_down(&async_futex);1824 1825 if (msg->done) {1826 amsg_destroy(msg);1827 } else {1828 msg->dataptr = NULL;1829 msg->forget = true;1830 }1831 1832 futex_up(&async_futex);1833 }1834 1835 /** Wait for specified time.1836 *1837 * The current fibril is suspended but the thread continues to execute.1838 *1839 * @param timeout Duration of the wait in microseconds.1840 *1841 */1842 void async_usleep(suseconds_t timeout)1843 {1844 awaiter_t awaiter;1845 awaiter_initialize(&awaiter);1846 1847 awaiter.fid = fibril_get_id();1848 1849 getuptime(&awaiter.to_event.expires);1850 tv_add_diff(&awaiter.to_event.expires, timeout);1851 1852 futex_down(&async_futex);1853 1854 async_insert_timeout(&awaiter);1855 1856 /* Leave the async_futex locked when entering this function */1857 fibril_switch(FIBRIL_TO_MANAGER);1858 1859 /* Futex is up automatically after fibril_switch() */1860 }1861 1862 /** Delay execution for the specified number of seconds1863 *1864 * @param sec Number of seconds to sleep1865 */1866 void async_sleep(unsigned int sec)1867 {1868 /*1869 * Sleep in 1000 second steps to support1870 * full argument range1871 */1872 1873 while (sec > 0) {1874 unsigned int period = (sec > 1000) ? 1000 : sec;1875 1876 async_usleep(period * 1000000);1877 sec -= period;1878 }1879 }1880 1881 /** Pseudo-synchronous message sending - fast version.1882 *1883 * Send message asynchronously and return only after the reply arrives.1884 *1885 * This function can only transfer 4 register payload arguments. For1886 * transferring more arguments, see the slower async_req_slow().1887 *1888 * @param exch Exchange for sending the message.1889 * @param imethod Interface and method of the call.1890 * @param arg1 Service-defined payload argument.1891 * @param arg2 Service-defined payload argument.1892 * @param arg3 Service-defined payload argument.1893 * @param arg4 Service-defined payload argument.1894 * @param r1 If non-NULL, storage for the 1st reply argument.1895 * @param r2 If non-NULL, storage for the 2nd reply argument.1896 * @param r3 If non-NULL, storage for the 3rd reply argument.1897 * @param r4 If non-NULL, storage for the 4th reply argument.1898 * @param r5 If non-NULL, storage for the 5th reply argument.1899 *1900 * @return Return code of the reply or an error code.1901 *1902 */1903 errno_t async_req_fast(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,1904 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t *r1, sysarg_t *r2,1905 sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)1906 {1907 if (exch == NULL)1908 return ENOENT;1909 1910 ipc_call_t result;1911 aid_t aid = async_send_4(exch, imethod, arg1, arg2, arg3, arg4,1912 &result);1913 1914 errno_t rc;1915 async_wait_for(aid, &rc);1916 1917 if (r1)1918 *r1 = IPC_GET_ARG1(result);1919 1920 if (r2)1921 *r2 = IPC_GET_ARG2(result);1922 1923 if (r3)1924 *r3 = IPC_GET_ARG3(result);1925 1926 if (r4)1927 *r4 = IPC_GET_ARG4(result);1928 1929 if (r5)1930 *r5 = IPC_GET_ARG5(result);1931 1932 return rc;1933 }1934 1935 /** Pseudo-synchronous message sending - slow version.1936 *1937 * Send message asynchronously and return only after the reply arrives.1938 *1939 * @param exch Exchange for sending the message.1940 * @param imethod Interface and method of the call.1941 * @param arg1 Service-defined payload argument.1942 * @param arg2 Service-defined payload argument.1943 * @param arg3 Service-defined payload argument.1944 * @param arg4 Service-defined payload argument.1945 * @param arg5 Service-defined payload argument.1946 * @param r1 If non-NULL, storage for the 1st reply argument.1947 * @param r2 If non-NULL, storage for the 2nd reply argument.1948 * @param r3 If non-NULL, storage for the 3rd reply argument.1949 * @param r4 If non-NULL, storage for the 4th reply argument.1950 * @param r5 If non-NULL, storage for the 5th reply argument.1951 *1952 * @return Return code of the reply or an error code.1953 *1954 */1955 errno_t async_req_slow(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,1956 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *r1,1957 sysarg_t *r2, sysarg_t *r3, sysarg_t *r4, sysarg_t *r5)1958 {1959 if (exch == NULL)1960 return ENOENT;1961 1962 ipc_call_t result;1963 aid_t aid = async_send_5(exch, imethod, arg1, arg2, arg3, arg4, arg5,1964 &result);1965 1966 errno_t rc;1967 async_wait_for(aid, &rc);1968 1969 if (r1)1970 *r1 = IPC_GET_ARG1(result);1971 1972 if (r2)1973 *r2 = IPC_GET_ARG2(result);1974 1975 if (r3)1976 *r3 = IPC_GET_ARG3(result);1977 1978 if (r4)1979 *r4 = IPC_GET_ARG4(result);1980 1981 if (r5)1982 *r5 = IPC_GET_ARG5(result);1983 1984 return rc;1985 }1986 1987 void async_msg_0(async_exch_t *exch, sysarg_t imethod)1988 {1989 if (exch != NULL)1990 ipc_call_async_0(exch->phone, imethod, NULL, NULL);1991 }1992 1993 void async_msg_1(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1)1994 {1995 if (exch != NULL)1996 ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL);1997 }1998 1999 void async_msg_2(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,2000 sysarg_t arg2)2001 {2002 if (exch != NULL)2003 ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL);2004 }2005 2006 void async_msg_3(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,2007 sysarg_t arg2, sysarg_t arg3)2008 {2009 if (exch != NULL)2010 ipc_call_async_3(exch->phone, imethod, arg1, arg2, arg3, NULL,2011 NULL);2012 }2013 2014 void async_msg_4(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,2015 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)2016 {2017 if (exch != NULL)2018 ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4,2019 NULL, NULL);2020 }2021 2022 void async_msg_5(async_exch_t *exch, sysarg_t imethod, sysarg_t arg1,2023 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)2024 {2025 if (exch != NULL)2026 ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4,2027 arg5, NULL, NULL);2028 1186 } 2029 1187 … … 2112 1270 } 2113 1271 2114 static errno_t async_connect_me_to_internal(cap_phone_handle_t phone,2115 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4,2116 cap_phone_handle_t *out_phone)2117 {2118 ipc_call_t result;2119 2120 // XXX: Workaround for GCC's inability to infer association between2121 // rc == EOK and *out_phone being assigned.2122 *out_phone = CAP_NIL;2123 2124 amsg_t *msg = amsg_create();2125 if (!msg)2126 return ENOENT;2127 2128 msg->dataptr = &result;2129 msg->wdata.active = true;2130 2131 ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, arg4,2132 msg, reply_received);2133 2134 errno_t rc;2135 async_wait_for((aid_t) msg, &rc);2136 2137 if (rc != EOK)2138 return rc;2139 2140 *out_phone = (cap_phone_handle_t) IPC_GET_ARG5(result);2141 return EOK;2142 }2143 2144 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.2145 *2146 * Ask through for a new connection to some service.2147 *2148 * @param mgmt Exchange management style.2149 * @param exch Exchange for sending the message.2150 * @param arg1 User defined argument.2151 * @param arg2 User defined argument.2152 * @param arg3 User defined argument.2153 *2154 * @return New session on success or NULL on error.2155 *2156 */2157 async_sess_t *async_connect_me_to(exch_mgmt_t mgmt, async_exch_t *exch,2158 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)2159 {2160 if (exch == NULL) {2161 errno = ENOENT;2162 return NULL;2163 }2164 2165 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));2166 if (sess == NULL) {2167 errno = ENOMEM;2168 return NULL;2169 }2170 2171 cap_phone_handle_t phone;2172 errno_t rc = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,2173 0, &phone);2174 if (rc != EOK) {2175 errno = rc;2176 free(sess);2177 return NULL;2178 }2179 2180 sess->iface = 0;2181 sess->mgmt = mgmt;2182 sess->phone = phone;2183 sess->arg1 = arg1;2184 sess->arg2 = arg2;2185 sess->arg3 = arg3;2186 2187 fibril_mutex_initialize(&sess->remote_state_mtx);2188 sess->remote_state_data = NULL;2189 2190 list_initialize(&sess->exch_list);2191 fibril_mutex_initialize(&sess->mutex);2192 atomic_set(&sess->refcnt, 0);2193 2194 return sess;2195 }2196 2197 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.2198 *2199 * Ask through phone for a new connection to some service and block until2200 * success.2201 *2202 * @param exch Exchange for sending the message.2203 * @param iface Connection interface.2204 * @param arg2 User defined argument.2205 * @param arg3 User defined argument.2206 *2207 * @return New session on success or NULL on error.2208 *2209 */2210 async_sess_t *async_connect_me_to_iface(async_exch_t *exch, iface_t iface,2211 sysarg_t arg2, sysarg_t arg3)2212 {2213 if (exch == NULL) {2214 errno = ENOENT;2215 return NULL;2216 }2217 2218 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));2219 if (sess == NULL) {2220 errno = ENOMEM;2221 return NULL;2222 }2223 2224 cap_phone_handle_t phone;2225 errno_t rc = async_connect_me_to_internal(exch->phone, iface, arg2,2226 arg3, 0, &phone);2227 if (rc != EOK) {2228 errno = rc;2229 free(sess);2230 return NULL;2231 }2232 2233 sess->iface = iface;2234 sess->phone = phone;2235 sess->arg1 = iface;2236 sess->arg2 = arg2;2237 sess->arg3 = arg3;2238 2239 fibril_mutex_initialize(&sess->remote_state_mtx);2240 sess->remote_state_data = NULL;2241 2242 list_initialize(&sess->exch_list);2243 fibril_mutex_initialize(&sess->mutex);2244 atomic_set(&sess->refcnt, 0);2245 2246 return sess;2247 }2248 2249 /** Set arguments for new connections.2250 *2251 * FIXME This is an ugly hack to work around the problem that parallel2252 * exchanges are implemented using parallel connections. When we create2253 * a callback session, the framework does not know arguments for the new2254 * connections.2255 *2256 * The proper solution seems to be to implement parallel exchanges using2257 * tagging.2258 */2259 void async_sess_args_set(async_sess_t *sess, sysarg_t arg1, sysarg_t arg2,2260 sysarg_t arg3)2261 {2262 sess->arg1 = arg1;2263 sess->arg2 = arg2;2264 sess->arg3 = arg3;2265 }2266 2267 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.2268 *2269 * Ask through phone for a new connection to some service and block until2270 * success.2271 *2272 * @param mgmt Exchange management style.2273 * @param exch Exchange for sending the message.2274 * @param arg1 User defined argument.2275 * @param arg2 User defined argument.2276 * @param arg3 User defined argument.2277 *2278 * @return New session on success or NULL on error.2279 *2280 */2281 async_sess_t *async_connect_me_to_blocking(exch_mgmt_t mgmt, async_exch_t *exch,2282 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)2283 {2284 if (exch == NULL) {2285 errno = ENOENT;2286 return NULL;2287 }2288 2289 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));2290 if (sess == NULL) {2291 errno = ENOMEM;2292 return NULL;2293 }2294 2295 cap_phone_handle_t phone;2296 errno_t rc = async_connect_me_to_internal(exch->phone, arg1, arg2, arg3,2297 IPC_FLAG_BLOCKING, &phone);2298 2299 if (rc != EOK) {2300 errno = rc;2301 free(sess);2302 return NULL;2303 }2304 2305 sess->iface = 0;2306 sess->mgmt = mgmt;2307 sess->phone = phone;2308 sess->arg1 = arg1;2309 sess->arg2 = arg2;2310 sess->arg3 = arg3;2311 2312 fibril_mutex_initialize(&sess->remote_state_mtx);2313 sess->remote_state_data = NULL;2314 2315 list_initialize(&sess->exch_list);2316 fibril_mutex_initialize(&sess->mutex);2317 atomic_set(&sess->refcnt, 0);2318 2319 return sess;2320 }2321 2322 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.2323 *2324 * Ask through phone for a new connection to some service and block until2325 * success.2326 *2327 * @param exch Exchange for sending the message.2328 * @param iface Connection interface.2329 * @param arg2 User defined argument.2330 * @param arg3 User defined argument.2331 *2332 * @return New session on success or NULL on error.2333 *2334 */2335 async_sess_t *async_connect_me_to_blocking_iface(async_exch_t *exch, iface_t iface,2336 sysarg_t arg2, sysarg_t arg3)2337 {2338 if (exch == NULL) {2339 errno = ENOENT;2340 return NULL;2341 }2342 2343 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));2344 if (sess == NULL) {2345 errno = ENOMEM;2346 return NULL;2347 }2348 2349 cap_phone_handle_t phone;2350 errno_t rc = async_connect_me_to_internal(exch->phone, iface, arg2,2351 arg3, IPC_FLAG_BLOCKING, &phone);2352 if (rc != EOK) {2353 errno = rc;2354 free(sess);2355 return NULL;2356 }2357 2358 sess->iface = iface;2359 sess->phone = phone;2360 sess->arg1 = iface;2361 sess->arg2 = arg2;2362 sess->arg3 = arg3;2363 2364 fibril_mutex_initialize(&sess->remote_state_mtx);2365 sess->remote_state_data = NULL;2366 2367 list_initialize(&sess->exch_list);2368 fibril_mutex_initialize(&sess->mutex);2369 atomic_set(&sess->refcnt, 0);2370 2371 return sess;2372 }2373 2374 /** Connect to a task specified by id.2375 *2376 */2377 async_sess_t *async_connect_kbox(task_id_t id)2378 {2379 async_sess_t *sess = (async_sess_t *) malloc(sizeof(async_sess_t));2380 if (sess == NULL) {2381 errno = ENOMEM;2382 return NULL;2383 }2384 2385 cap_phone_handle_t phone;2386 errno_t rc = ipc_connect_kbox(id, &phone);2387 if (rc != EOK) {2388 errno = rc;2389 free(sess);2390 return NULL;2391 }2392 2393 sess->iface = 0;2394 sess->mgmt = EXCHANGE_ATOMIC;2395 sess->phone = phone;2396 sess->arg1 = 0;2397 sess->arg2 = 0;2398 sess->arg3 = 0;2399 2400 fibril_mutex_initialize(&sess->remote_state_mtx);2401 sess->remote_state_data = NULL;2402 2403 list_initialize(&sess->exch_list);2404 fibril_mutex_initialize(&sess->mutex);2405 atomic_set(&sess->refcnt, 0);2406 2407 return sess;2408 }2409 2410 static errno_t async_hangup_internal(cap_phone_handle_t phone)2411 {2412 return ipc_hangup(phone);2413 }2414 2415 /** Wrapper for ipc_hangup.2416 *2417 * @param sess Session to hung up.2418 *2419 * @return Zero on success or an error code.2420 *2421 */2422 errno_t async_hangup(async_sess_t *sess)2423 {2424 async_exch_t *exch;2425 2426 assert(sess);2427 2428 if (atomic_get(&sess->refcnt) > 0)2429 return EBUSY;2430 2431 fibril_mutex_lock(&async_sess_mutex);2432 2433 errno_t rc = async_hangup_internal(sess->phone);2434 2435 while (!list_empty(&sess->exch_list)) {2436 exch = (async_exch_t *)2437 list_get_instance(list_first(&sess->exch_list),2438 async_exch_t, sess_link);2439 2440 list_remove(&exch->sess_link);2441 list_remove(&exch->global_link);2442 async_hangup_internal(exch->phone);2443 free(exch);2444 }2445 2446 free(sess);2447 2448 fibril_mutex_unlock(&async_sess_mutex);2449 2450 return rc;2451 }2452 2453 1272 /** Interrupt one thread of this task from waiting for IPC. */ 2454 1273 void async_poke(void) 2455 1274 { 2456 1275 ipc_poke(); 2457 }2458 2459 /** Start new exchange in a session.2460 *2461 * @param session Session.2462 *2463 * @return New exchange or NULL on error.2464 *2465 */2466 async_exch_t *async_exchange_begin(async_sess_t *sess)2467 {2468 if (sess == NULL)2469 return NULL;2470 2471 exch_mgmt_t mgmt = sess->mgmt;2472 if (sess->iface != 0)2473 mgmt = sess->iface & IFACE_EXCHANGE_MASK;2474 2475 async_exch_t *exch = NULL;2476 2477 fibril_mutex_lock(&async_sess_mutex);2478 2479 if (!list_empty(&sess->exch_list)) {2480 /*2481 * There are inactive exchanges in the session.2482 */2483 exch = (async_exch_t *)2484 list_get_instance(list_first(&sess->exch_list),2485 async_exch_t, sess_link);2486 2487 list_remove(&exch->sess_link);2488 list_remove(&exch->global_link);2489 } else {2490 /*2491 * There are no available exchanges in the session.2492 */2493 2494 if ((mgmt == EXCHANGE_ATOMIC) ||2495 (mgmt == EXCHANGE_SERIALIZE)) {2496 exch = (async_exch_t *) malloc(sizeof(async_exch_t));2497 if (exch != NULL) {2498 link_initialize(&exch->sess_link);2499 link_initialize(&exch->global_link);2500 exch->sess = sess;2501 exch->phone = sess->phone;2502 }2503 } else if (mgmt == EXCHANGE_PARALLEL) {2504 cap_phone_handle_t phone;2505 errno_t rc;2506 2507 retry:2508 /*2509 * Make a one-time attempt to connect a new data phone.2510 */2511 rc = async_connect_me_to_internal(sess->phone, sess->arg1,2512 sess->arg2, sess->arg3, 0, &phone);2513 if (rc == EOK) {2514 exch = (async_exch_t *) malloc(sizeof(async_exch_t));2515 if (exch != NULL) {2516 link_initialize(&exch->sess_link);2517 link_initialize(&exch->global_link);2518 exch->sess = sess;2519 exch->phone = phone;2520 } else2521 async_hangup_internal(phone);2522 } else if (!list_empty(&inactive_exch_list)) {2523 /*2524 * We did not manage to connect a new phone. But we2525 * can try to close some of the currently inactive2526 * connections in other sessions and try again.2527 */2528 exch = (async_exch_t *)2529 list_get_instance(list_first(&inactive_exch_list),2530 async_exch_t, global_link);2531 2532 list_remove(&exch->sess_link);2533 list_remove(&exch->global_link);2534 async_hangup_internal(exch->phone);2535 free(exch);2536 goto retry;2537 } else {2538 /*2539 * Wait for a phone to become available.2540 */2541 fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex);2542 goto retry;2543 }2544 }2545 }2546 2547 fibril_mutex_unlock(&async_sess_mutex);2548 2549 if (exch != NULL) {2550 atomic_inc(&sess->refcnt);2551 2552 if (mgmt == EXCHANGE_SERIALIZE)2553 fibril_mutex_lock(&sess->mutex);2554 }2555 2556 return exch;2557 }2558 2559 /** Finish an exchange.2560 *2561 * @param exch Exchange to finish.2562 *2563 */2564 void async_exchange_end(async_exch_t *exch)2565 {2566 if (exch == NULL)2567 return;2568 2569 async_sess_t *sess = exch->sess;2570 assert(sess != NULL);2571 2572 exch_mgmt_t mgmt = sess->mgmt;2573 if (sess->iface != 0)2574 mgmt = sess->iface & IFACE_EXCHANGE_MASK;2575 2576 atomic_dec(&sess->refcnt);2577 2578 if (mgmt == EXCHANGE_SERIALIZE)2579 fibril_mutex_unlock(&sess->mutex);2580 2581 fibril_mutex_lock(&async_sess_mutex);2582 2583 list_append(&exch->sess_link, &sess->exch_list);2584 list_append(&exch->global_link, &inactive_exch_list);2585 fibril_condvar_signal(&avail_phone_cv);2586 2587 fibril_mutex_unlock(&async_sess_mutex);2588 }2589 2590 /** Wrapper for IPC_M_SHARE_IN calls using the async framework.2591 *2592 * @param exch Exchange for sending the message.2593 * @param size Size of the destination address space area.2594 * @param arg User defined argument.2595 * @param flags Storage for the received flags. Can be NULL.2596 * @param dst Address of the storage for the destination address space area2597 * base address. Cannot be NULL.2598 *2599 * @return Zero on success or an error code from errno.h.2600 *2601 */2602 errno_t async_share_in_start(async_exch_t *exch, size_t size, sysarg_t arg,2603 unsigned int *flags, void **dst)2604 {2605 if (exch == NULL)2606 return ENOENT;2607 2608 sysarg_t _flags = 0;2609 sysarg_t _dst = (sysarg_t) -1;2610 errno_t res = async_req_2_4(exch, IPC_M_SHARE_IN, (sysarg_t) size,2611 arg, NULL, &_flags, NULL, &_dst);2612 2613 if (flags)2614 *flags = (unsigned int) _flags;2615 2616 *dst = (void *) _dst;2617 return res;2618 1276 } 2619 1277 … … 2668 1326 } 2669 1327 2670 /** Wrapper for IPC_M_SHARE_OUT calls using the async framework.2671 *2672 * @param exch Exchange for sending the message.2673 * @param src Source address space area base address.2674 * @param flags Flags to be used for sharing. Bits can be only cleared.2675 *2676 * @return Zero on success or an error code from errno.h.2677 *2678 */2679 errno_t async_share_out_start(async_exch_t *exch, void *src, unsigned int flags)2680 {2681 if (exch == NULL)2682 return ENOENT;2683 2684 return async_req_3_0(exch, IPC_M_SHARE_OUT, (sysarg_t) src, 0,2685 (sysarg_t) flags);2686 }2687 2688 1328 /** Wrapper for receiving the IPC_M_SHARE_OUT calls using the async framework. 2689 1329 * … … 2735 1375 { 2736 1376 return ipc_answer_2(chandle, EOK, (sysarg_t) _end, (sysarg_t) dst); 2737 }2738 2739 /** Start IPC_M_DATA_READ using the async framework.2740 *2741 * @param exch Exchange for sending the message.2742 * @param dst Address of the beginning of the destination buffer.2743 * @param size Size of the destination buffer (in bytes).2744 * @param dataptr Storage of call data (arg 2 holds actual data size).2745 *2746 * @return Hash of the sent message or 0 on error.2747 *2748 */2749 aid_t async_data_read(async_exch_t *exch, void *dst, size_t size,2750 ipc_call_t *dataptr)2751 {2752 return async_send_2(exch, IPC_M_DATA_READ, (sysarg_t) dst,2753 (sysarg_t) size, dataptr);2754 }2755 2756 /** Wrapper for IPC_M_DATA_READ calls using the async framework.2757 *2758 * @param exch Exchange for sending the message.2759 * @param dst Address of the beginning of the destination buffer.2760 * @param size Size of the destination buffer.2761 *2762 * @return Zero on success or an error code from errno.h.2763 *2764 */2765 errno_t async_data_read_start(async_exch_t *exch, void *dst, size_t size)2766 {2767 if (exch == NULL)2768 return ENOENT;2769 2770 return async_req_2_0(exch, IPC_M_DATA_READ, (sysarg_t) dst,2771 (sysarg_t) size);2772 1377 } 2773 1378 … … 2878 1483 2879 1484 return (errno_t) rc; 2880 }2881 2882 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework.2883 *2884 * @param exch Exchange for sending the message.2885 * @param src Address of the beginning of the source buffer.2886 * @param size Size of the source buffer.2887 *2888 * @return Zero on success or an error code from errno.h.2889 *2890 */2891 errno_t async_data_write_start(async_exch_t *exch, const void *src, size_t size)2892 {2893 if (exch == NULL)2894 return ENOENT;2895 2896 return async_req_2_0(exch, IPC_M_DATA_WRITE, (sysarg_t) src,2897 (sysarg_t) size);2898 1485 } 2899 1486 … … 3190 1777 } 3191 1778 3192 errno_t async_state_change_start(async_exch_t *exch, sysarg_t arg1, sysarg_t arg2,3193 sysarg_t arg3, async_exch_t *other_exch)3194 {3195 return async_req_5_0(exch, IPC_M_STATE_CHANGE_AUTHORIZE,3196 arg1, arg2, arg3, 0, CAP_HANDLE_RAW(other_exch->phone));3197 }3198 3199 1779 bool async_state_change_receive(cap_call_handle_t *chandle, sysarg_t *arg1, 3200 1780 sysarg_t *arg2, sysarg_t *arg3) … … 3224 1804 } 3225 1805 3226 /** Lock and get session remote state3227 *3228 * Lock and get the local replica of the remote state3229 * in stateful sessions. The call should be paired3230 * with async_remote_state_release*().3231 *3232 * @param[in] sess Stateful session.3233 *3234 * @return Local replica of the remote state.3235 *3236 */3237 void *async_remote_state_acquire(async_sess_t *sess)3238 {3239 fibril_mutex_lock(&sess->remote_state_mtx);3240 return sess->remote_state_data;3241 }3242 3243 /** Update the session remote state3244 *3245 * Update the local replica of the remote state3246 * in stateful sessions. The remote state must3247 * be already locked.3248 *3249 * @param[in] sess Stateful session.3250 * @param[in] state New local replica of the remote state.3251 *3252 */3253 void async_remote_state_update(async_sess_t *sess, void *state)3254 {3255 assert(fibril_mutex_is_locked(&sess->remote_state_mtx));3256 sess->remote_state_data = state;3257 }3258 3259 /** Release the session remote state3260 *3261 * Unlock the local replica of the remote state3262 * in stateful sessions.3263 *3264 * @param[in] sess Stateful session.3265 *3266 */3267 void async_remote_state_release(async_sess_t *sess)3268 {3269 assert(fibril_mutex_is_locked(&sess->remote_state_mtx));3270 3271 fibril_mutex_unlock(&sess->remote_state_mtx);3272 }3273 3274 /** Release the session remote state and end an exchange3275 *3276 * Unlock the local replica of the remote state3277 * in stateful sessions. This is convenience function3278 * which gets the session pointer from the exchange3279 * and also ends the exchange.3280 *3281 * @param[in] exch Stateful session's exchange.3282 *3283 */3284 void async_remote_state_release_exchange(async_exch_t *exch)3285 {3286 if (exch == NULL)3287 return;3288 3289 async_sess_t *sess = exch->sess;3290 assert(fibril_mutex_is_locked(&sess->remote_state_mtx));3291 3292 async_exchange_end(exch);3293 fibril_mutex_unlock(&sess->remote_state_mtx);3294 }3295 3296 void *async_as_area_create(void *base, size_t size, unsigned int flags,3297 async_sess_t *pager, sysarg_t id1, sysarg_t id2, sysarg_t id3)3298 {3299 as_area_pager_info_t pager_info = {3300 .pager = pager->phone,3301 .id1 = id1,3302 .id2 = id2,3303 .id3 = id33304 };3305 return as_area_create(base, size, flags, &pager_info);3306 }3307 3308 1806 /** @} 3309 1807 */ -
uspace/lib/c/generic/fibril_synch.c
rfda19b8 r49a796f1 55 55 * fibril back to fruitful work. 56 56 */ 57 if (atomic_get(&threads_in_ipc_wait) > 0) 58 async_poke(); 57 async_poke(); 59 58 } 60 59 -
uspace/lib/c/generic/libc.c
rfda19b8 r49a796f1 95 95 #endif 96 96 97 __async_init(); 97 __async_server_init(); 98 __async_client_init(); 99 __async_ports_init(); 98 100 99 101 /* The basic run-time environment is setup */ -
uspace/lib/c/generic/private/async.h
rfda19b8 r49a796f1 81 81 } awaiter_t; 82 82 83 /** Session data */ 84 struct async_sess { 85 /** List of inactive exchanges */ 86 list_t exch_list; 87 88 /** Session interface */ 89 iface_t iface; 90 91 /** Exchange management style */ 92 exch_mgmt_t mgmt; 93 94 /** Session identification */ 95 cap_phone_handle_t phone; 96 97 /** First clone connection argument */ 98 sysarg_t arg1; 99 100 /** Second clone connection argument */ 101 sysarg_t arg2; 102 103 /** Third clone connection argument */ 104 sysarg_t arg3; 105 106 /** Exchange mutex */ 107 fibril_mutex_t mutex; 108 109 /** Number of opened exchanges */ 110 atomic_t refcnt; 111 112 /** Mutex for stateful connections */ 113 fibril_mutex_t remote_state_mtx; 114 115 /** Data for stateful connections */ 116 void *remote_state_data; 117 }; 118 119 /** Exchange data */ 120 struct async_exch { 121 /** Link into list of inactive exchanges */ 122 link_t sess_link; 123 124 /** Link into global list of inactive exchanges */ 125 link_t global_link; 126 127 /** Session pointer */ 128 async_sess_t *sess; 129 130 /** Exchange identification */ 131 cap_phone_handle_t phone; 132 }; 133 83 134 extern void awaiter_initialize(awaiter_t *); 84 135 85 extern void __async_init(void); 136 extern void __async_server_init(void); 137 extern void __async_client_init(void); 138 extern void __async_ports_init(void); 86 139 extern void async_insert_timeout(awaiter_t *); 87 extern void reply_received(void *, errno_t, ipc_call_t *); 140 141 extern errno_t async_create_port_internal(iface_t, async_port_handler_t, 142 void *, port_id_t *); 143 extern async_port_handler_t async_get_port_handler(iface_t, port_id_t, void **); 88 144 89 145 #endif -
uspace/lib/c/include/async.h
rfda19b8 r49a796f1 107 107 typedef struct async_sess async_sess_t; 108 108 typedef struct async_exch async_exch_t; 109 110 extern atomic_t threads_in_ipc_wait;111 109 112 110 #define async_manager() \
Note:
See TracChangeset
for help on using the changeset viewer.