Subversion Repositories HelenOS

Rev

Rev 4420 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2006 Ondrej Palkovsky
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup libc
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #ifndef LIBC_ASYNC_H_
  36. #define LIBC_ASYNC_H_
  37.  
  38. #include <ipc/ipc.h>
  39. #include <fibril.h>
  40. #include <sys/time.h>
  41. #include <atomic.h>
  42. #include <bool.h>
  43.  
  44. typedef ipc_callid_t aid_t;
  45. typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call);
  46. typedef void (*async_pending_t)(void);
  47.  
  48. extern atomic_t async_futex;
  49.  
  50. static inline void async_manager(void)
  51. {
  52.     fibril_switch(FIBRIL_TO_MANAGER);
  53. }
  54.  
  55. extern ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
  56.  
  57. static inline ipc_callid_t async_get_call(ipc_call_t *data)
  58. {
  59.     return async_get_call_timeout(data, 0);
  60. }
  61.  
  62. /*
  63.  * User-friendly wrappers for async_send_fast() and async_send_slow(). The
  64.  * macros are in the form async_send_m(), where m denotes the number of payload
  65.  * arguments.  Each macros chooses between the fast and the slow version based
  66.  * on m.
  67.  */
  68.  
  69. #define async_send_0(phoneid, method, dataptr) \
  70.     async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
  71. #define async_send_1(phoneid, method, arg1, dataptr) \
  72.     async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
  73. #define async_send_2(phoneid, method, arg1, arg2, dataptr) \
  74.     async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
  75. #define async_send_3(phoneid, method, arg1, arg2, arg3, dataptr) \
  76.     async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
  77. #define async_send_4(phoneid, method, arg1, arg2, arg3, arg4, dataptr) \
  78.     async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  79.         (dataptr))
  80. #define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
  81.     async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  82.         (arg5), (dataptr))
  83.  
  84. extern aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
  85.     ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr);
  86. extern aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
  87.     ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5,
  88.     ipc_call_t *dataptr);
  89. extern void async_wait_for(aid_t amsgid, ipcarg_t *result);
  90. extern int async_wait_timeout(aid_t amsgid, ipcarg_t *retval,
  91.     suseconds_t timeout);
  92.  
  93. extern fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
  94.     ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *));
  95. extern void async_usleep(suseconds_t timeout);
  96. extern void async_create_manager(void);
  97. extern void async_destroy_manager(void);
  98. extern int _async_init(void);
  99.  
  100. extern void async_set_client_connection(async_client_conn_t conn);
  101. extern void async_set_interrupt_received(async_client_conn_t conn);
  102. extern void async_set_pending(async_pending_t pend);
  103.  
  104. /* Wrappers for simple communication */
  105. #define async_msg_0(phone, method) \
  106.     ipc_call_async_0((phone), (method), NULL, NULL, true)
  107. #define async_msg_1(phone, method, arg1) \
  108.     ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \
  109.         true)
  110. #define async_msg_2(phone, method, arg1, arg2) \
  111.     ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \
  112.         true)
  113. #define async_msg_3(phone, method, arg1, arg2, arg3) \
  114.     ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \
  115.         true)
  116. #define async_msg_4(phone, method, arg1, arg2, arg3, arg4) \
  117.     ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
  118.         NULL, true)
  119. #define async_msg_5(phone, method, arg1, arg2, arg3, arg4, arg5) \
  120.     ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \
  121.         (arg5), NULL, NULL, true)
  122.  
  123. /*
  124.  * User-friendly wrappers for async_req_fast() and async_req_slow(). The macros
  125.  * are in the form async_req_m_n(), where m is the number of payload arguments
  126.  * and n is the number of return arguments. The macros decide between the fast
  127.  * and slow verion based on m.
  128.  */
  129. #define async_req_0_0(phoneid, method) \
  130.     async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
  131.         NULL)
  132. #define async_req_0_1(phoneid, method, r1) \
  133.     async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
  134.         NULL)
  135. #define async_req_0_2(phoneid, method, r1, r2) \
  136.     async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
  137.         NULL)
  138. #define async_req_0_3(phoneid, method, r1, r2, r3) \
  139.     async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
  140.         NULL)
  141. #define async_req_0_4(phoneid, method, r1, r2, r3, r4) \
  142.     async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
  143.         NULL)
  144. #define async_req_0_5(phoneid, method, r1, r2, r3, r4, r5) \
  145.     async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
  146.         (r5))
  147. #define async_req_1_0(phoneid, method, arg1) \
  148.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
  149.         NULL, NULL)
  150. #define async_req_1_1(phoneid, method, arg1, rc1) \
  151.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
  152.         NULL, NULL)
  153. #define async_req_1_2(phoneid, method, arg1, rc1, rc2) \
  154.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
  155.         NULL, NULL)
  156. #define async_req_1_3(phoneid, method, arg1, rc1, rc2, rc3) \
  157.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
  158.         NULL, NULL)
  159. #define async_req_1_4(phoneid, method, arg1, rc1, rc2, rc3, rc4) \
  160.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
  161.         (rc4), NULL)
  162. #define async_req_1_5(phoneid, method, arg1, rc1, rc2, rc3, rc4, rc5) \
  163.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
  164.         (rc4), (rc5))
  165. #define async_req_2_0(phoneid, method, arg1, arg2) \
  166.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
  167.         NULL, NULL, NULL)
  168. #define async_req_2_1(phoneid, method, arg1, arg2, rc1) \
  169.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
  170.         NULL, NULL, NULL)
  171. #define async_req_2_2(phoneid, method, arg1, arg2, rc1, rc2) \
  172.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
  173.         NULL, NULL, NULL)
  174. #define async_req_2_3(phoneid, method, arg1, arg2, rc1, rc2, rc3) \
  175.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
  176.         (rc3), NULL, NULL)
  177. #define async_req_2_4(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4) \
  178.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
  179.         (rc3), (rc4), NULL)
  180. #define async_req_2_5(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
  181.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
  182.         (rc3), (rc4), (rc5))
  183. #define async_req_3_0(phoneid, method, arg1, arg2, arg3) \
  184.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
  185.         NULL, NULL, NULL)
  186. #define async_req_3_1(phoneid, method, arg1, arg2, arg3, rc1) \
  187.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
  188.         NULL, NULL, NULL, NULL)
  189. #define async_req_3_2(phoneid, method, arg1, arg2, arg3, rc1, rc2) \
  190.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
  191.         (rc2), NULL, NULL, NULL)
  192. #define async_req_3_3(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3) \
  193.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
  194.         (rc2), (rc3), NULL, NULL)
  195. #define async_req_3_4(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
  196.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
  197.         (rc2), (rc3), (rc4), NULL)
  198. #define async_req_3_5(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
  199.     rc5) \
  200.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
  201.         (rc2), (rc3), (rc4), (rc5))
  202. #define async_req_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
  203.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
  204.         NULL, NULL, NULL, NULL)
  205. #define async_req_4_1(phoneid, method, arg1, arg2, arg3, arg4, rc1) \
  206.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
  207.         NULL, NULL, NULL, NULL)
  208. #define async_req_4_2(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2) \
  209.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
  210.         (rc2), NULL, NULL, NULL)
  211. #define async_req_4_3(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
  212.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
  213.         (rc2), (rc3), NULL, NULL)
  214. #define async_req_4_4(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
  215.     rc4) \
  216.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  217.         (rc1), (rc2), (rc3), (rc4), NULL)
  218. #define async_req_4_5(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
  219.     rc4, rc5) \
  220.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  221.         (rc1), (rc2), (rc3), (rc4), (rc5))
  222. #define async_req_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
  223.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  224.         (arg5), NULL, NULL, NULL, NULL, NULL)
  225. #define async_req_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1) \
  226.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  227.         (arg5), (rc1), NULL, NULL, NULL, NULL)
  228. #define async_req_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
  229.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  230.         (arg5), (rc1), (rc2), NULL, NULL, NULL)
  231. #define async_req_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
  232.     rc3) \
  233.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  234.         (arg5), (rc1), (rc2), (rc3), NULL, NULL)
  235. #define async_req_5_4(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
  236.     rc3, rc4) \
  237.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  238.         (arg5), (rc1), (rc2), (rc3), (rc4), NULL)
  239. #define async_req_5_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
  240.     rc3, rc4, rc5) \
  241.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  242.         (arg5), (rc1), (rc2), (rc3), (rc4), (rc5))
  243.  
  244. extern ipcarg_t async_req_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
  245.     ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t *r1, ipcarg_t *r2,
  246.     ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5);
  247. extern ipcarg_t async_req_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
  248.     ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, ipcarg_t *r1,
  249.     ipcarg_t *r2, ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5);
  250.  
  251. static inline void async_serialize_start(void)
  252. {
  253.     fibril_inc_sercount();
  254. }
  255.  
  256. static inline void async_serialize_end(void)
  257. {
  258.     fibril_dec_sercount();
  259. }
  260.  
  261. #endif
  262.  
  263. /** @}
  264.  */
  265.