Subversion Repositories HelenOS

Rev

Rev 4338 | Rev 4348 | 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.  
  47. static inline void async_manager(void)
  48. {
  49.     fibril_switch(FIBRIL_TO_MANAGER);
  50. }
  51.  
  52. ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs);
  53. static inline ipc_callid_t async_get_call(ipc_call_t *data)
  54. {
  55.     return async_get_call_timeout(data, 0);
  56. }
  57.  
  58. /*
  59.  * User-friendly wrappers for async_send_fast() and async_send_slow(). The
  60.  * macros are in the form async_send_m(), where m denotes the number of payload
  61.  * arguments.  Each macros chooses between the fast and the slow version based
  62.  * on m.
  63.  */
  64.  
  65. #define async_send_0(phoneid, method, dataptr) \
  66.     async_send_fast((phoneid), (method), 0, 0, 0, 0, (dataptr))
  67. #define async_send_1(phoneid, method, arg1, dataptr) \
  68.     async_send_fast((phoneid), (method), (arg1), 0, 0, 0, (dataptr))
  69. #define async_send_2(phoneid, method, arg1, arg2, dataptr) \
  70.     async_send_fast((phoneid), (method), (arg1), (arg2), 0, 0, (dataptr))
  71. #define async_send_3(phoneid, method, arg1, arg2, arg3, dataptr) \
  72.     async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (dataptr))
  73. #define async_send_4(phoneid, method, arg1, arg2, arg3, arg4, dataptr) \
  74.     async_send_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  75.         (dataptr))
  76. #define async_send_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, dataptr) \
  77.     async_send_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  78.         (arg5), (dataptr))
  79.  
  80. extern aid_t async_send_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
  81.     ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipc_call_t *dataptr);
  82. extern aid_t async_send_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
  83.     ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5,
  84.     ipc_call_t *dataptr);
  85. extern void async_wait_for(aid_t amsgid, ipcarg_t *result);
  86. extern int async_wait_timeout(aid_t amsgid, ipcarg_t *retval,
  87.     suseconds_t timeout);
  88.  
  89. fid_t async_new_connection(ipcarg_t in_phone_hash, ipc_callid_t callid,
  90.     ipc_call_t *call, void (*cthread)(ipc_callid_t, ipc_call_t *));
  91. void async_usleep(suseconds_t timeout);
  92. void async_create_manager(void);
  93. void async_destroy_manager(void);
  94. int _async_init(void);
  95.  
  96. extern void async_set_client_connection(async_client_conn_t conn);
  97. extern void async_set_interrupt_received(async_client_conn_t conn);
  98.  
  99. /* Wrappers for simple communication */
  100. #define async_msg_0(phone, method) \
  101.     ipc_call_async_0((phone), (method), NULL, NULL, !in_interrupt_handler())
  102. #define async_msg_1(phone, method, arg1) \
  103.     ipc_call_async_1((phone), (method), (arg1), NULL, NULL, \
  104.         !in_interrupt_handler())
  105. #define async_msg_2(phone, method, arg1, arg2) \
  106.     ipc_call_async_2((phone), (method), (arg1), (arg2), NULL, NULL, \
  107.         !in_interrupt_handler())
  108. #define async_msg_3(phone, method, arg1, arg2, arg3) \
  109.     ipc_call_async_3((phone), (method), (arg1), (arg2), (arg3), NULL, NULL, \
  110.         !in_interrupt_handler())
  111. #define async_msg_4(phone, method, arg1, arg2, arg3, arg4) \
  112.     ipc_call_async_4((phone), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
  113.         NULL, !in_interrupt_handler())
  114. #define async_msg_5(phone, method, arg1, arg2, arg3, arg4, arg5) \
  115.     ipc_call_async_5((phone), (method), (arg1), (arg2), (arg3), (arg4), \
  116.         (arg5), NULL, NULL, !in_interrupt_handler())
  117.  
  118. /*
  119.  * User-friendly wrappers for async_req_fast() and async_req_slow(). The macros
  120.  * are in the form async_req_m_n(), where m is the number of payload arguments
  121.  * and n is the number of return arguments. The macros decide between the fast
  122.  * and slow verion based on m.
  123.  */
  124. #define async_req_0_0(phoneid, method) \
  125.     async_req_fast((phoneid), (method), 0, 0, 0, 0, NULL, NULL, NULL, NULL, \
  126.     NULL)
  127. #define async_req_0_1(phoneid, method, r1) \
  128.     async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), NULL, NULL, NULL, \
  129.     NULL)
  130. #define async_req_0_2(phoneid, method, r1, r2) \
  131.     async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), NULL, NULL, \
  132.     NULL)
  133. #define async_req_0_3(phoneid, method, r1, r2, r3) \
  134.     async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), NULL, \
  135.     NULL)
  136. #define async_req_0_4(phoneid, method, r1, r2, r3, r4) \
  137.     async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
  138.     NULL)
  139. #define async_req_0_5(phoneid, method, r1, r2, r3, r4, r5) \
  140.     async_req_fast((phoneid), (method), 0, 0, 0, 0, (r1), (r2), (r3), (r4), \
  141.     (r5))
  142. #define async_req_1_0(phoneid, method, arg1) \
  143.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, NULL, NULL, NULL, \
  144.     NULL, NULL)
  145. #define async_req_1_1(phoneid, method, arg1, rc1) \
  146.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), NULL, NULL, \
  147.     NULL, NULL)
  148. #define async_req_1_2(phoneid, method, arg1, rc1, rc2) \
  149.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), NULL, \
  150.     NULL, NULL)
  151. #define async_req_1_3(phoneid, method, arg1, rc1, rc2, rc3) \
  152.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
  153.     NULL, NULL)
  154. #define async_req_1_4(phoneid, method, arg1, rc1, rc2, rc3, rc4) \
  155.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
  156.     (rc4), NULL)
  157. #define async_req_1_5(phoneid, method, arg1, rc1, rc2, rc3, rc4, rc5) \
  158.     async_req_fast((phoneid), (method), (arg1), 0, 0, 0, (rc1), (rc2), (rc3), \
  159.     (rc4), (rc5))
  160. #define async_req_2_0(phoneid, method, arg1, arg2) \
  161.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, NULL, NULL, \
  162.     NULL, NULL, NULL)
  163. #define async_req_2_1(phoneid, method, arg1, arg2, rc1) \
  164.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), NULL, \
  165.     NULL, NULL, NULL)
  166. #define async_req_2_2(phoneid, method, arg1, arg2, rc1, rc2) \
  167.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
  168.     NULL, NULL, NULL)
  169. #define async_req_2_3(phoneid, method, arg1, arg2, rc1, rc2, rc3) \
  170.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
  171.     (rc3), NULL, NULL)
  172. #define async_req_2_4(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4) \
  173.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
  174.     (rc3), (rc4), NULL)
  175. #define async_req_2_5(phoneid, method, arg1, arg2, rc1, rc2, rc3, rc4, rc5) \
  176.     async_req_fast((phoneid), (method), (arg1), (arg2), 0, 0, (rc1), (rc2), \
  177.     (rc3), (rc4), (rc5))
  178. #define async_req_3_0(phoneid, method, arg1, arg2, arg3) \
  179.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, NULL, NULL, \
  180.     NULL, NULL, NULL)
  181. #define async_req_3_1(phoneid, method, arg1, arg2, arg3, rc1) \
  182.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
  183.     NULL, NULL, NULL, NULL)
  184. #define async_req_3_2(phoneid, method, arg1, arg2, arg3, rc1, rc2) \
  185.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
  186.     (rc2), NULL, NULL, NULL)
  187. #define async_req_3_3(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3) \
  188.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
  189.     (rc2), (rc3), NULL, NULL)
  190. #define async_req_3_4(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4) \
  191.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
  192.     (rc2), (rc3), (rc4), NULL)
  193. #define async_req_3_5(phoneid, method, arg1, arg2, arg3, rc1, rc2, rc3, rc4, \
  194.     rc5) \
  195.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, (rc1), \
  196.         (rc2), (rc3), (rc4), (rc5))
  197. #define async_req_4_0(phoneid, method, arg1, arg2, arg3, arg4) \
  198.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), NULL, \
  199.     NULL, NULL, NULL, NULL)
  200. #define async_req_4_1(phoneid, method, arg1, arg2, arg3, arg4, rc1) \
  201.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
  202.     NULL, NULL, NULL, NULL)
  203. #define async_req_4_2(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2) \
  204.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
  205.     (rc2), NULL, NULL, NULL)
  206. #define async_req_4_3(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3) \
  207.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), (rc1), \
  208.     (rc2), (rc3), NULL, NULL)
  209. #define async_req_4_4(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
  210.     rc4) \
  211.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  212.         (rc1), (rc2), (rc3), (rc4), NULL)
  213. #define async_req_4_5(phoneid, method, arg1, arg2, arg3, arg4, rc1, rc2, rc3, \
  214.     rc4, rc5) \
  215.     async_req_fast((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  216.         (rc1), (rc2), (rc3), (rc4), (rc5))
  217. #define async_req_5_0(phoneid, method, arg1, arg2, arg3, arg4, arg5) \
  218.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  219.         (arg5), NULL, NULL, NULL, NULL, NULL)
  220. #define async_req_5_1(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1) \
  221.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  222.     (arg5), (rc1), NULL, NULL, NULL, NULL)
  223. #define async_req_5_2(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2) \
  224.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  225.     (arg5), (rc1), (rc2), NULL, NULL, NULL)
  226. #define async_req_5_3(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
  227.     rc3) \
  228.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  229.         (arg5), (rc1), (rc2), (rc3), NULL, NULL)
  230. #define async_req_5_4(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
  231.     rc3, rc4) \
  232.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  233.         (arg5), (rc1), (rc2), (rc3), (rc4), NULL)
  234. #define async_req_5_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, rc1, rc2, \
  235.     rc3, rc4, rc5) \
  236.     async_req_slow((phoneid), (method), (arg1), (arg2), (arg3), (arg4), \
  237.         (arg5), (rc1), (rc2), (rc3), (rc4), (rc5))
  238.  
  239. extern ipcarg_t async_req_fast(int phoneid, ipcarg_t method, ipcarg_t arg1,
  240.     ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t *r1, ipcarg_t *r2,
  241.     ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5);
  242. extern ipcarg_t async_req_slow(int phoneid, ipcarg_t method, ipcarg_t arg1,
  243.     ipcarg_t arg2, ipcarg_t arg3, ipcarg_t arg4, ipcarg_t arg5, ipcarg_t *r1,
  244.     ipcarg_t *r2, ipcarg_t *r3, ipcarg_t *r4, ipcarg_t *r5);
  245.  
  246. static inline void async_serialize_start(void)
  247. {
  248.     fibril_inc_sercount();
  249. }
  250.  
  251. static inline void async_serialize_end(void)
  252. {
  253.     fibril_dec_sercount();
  254. }
  255.  
  256. extern bool in_interrupt_handler(void);
  257.  
  258. extern atomic_t async_futex;
  259.  
  260. #endif
  261.  
  262. /** @}
  263.  */
  264.