diff options
Diffstat (limited to 'libcr_ipc')
-rw-r--r-- | libcr_ipc/include/libcr_ipc/rpc.h | 179 | ||||
-rw-r--r-- | libcr_ipc/tests/test_rpc.c | 12 |
2 files changed, 90 insertions, 101 deletions
diff --git a/libcr_ipc/include/libcr_ipc/rpc.h b/libcr_ipc/include/libcr_ipc/rpc.h index f091685..ff75034 100644 --- a/libcr_ipc/include/libcr_ipc/rpc.h +++ b/libcr_ipc/include/libcr_ipc/rpc.h @@ -10,13 +10,9 @@ #include <stdbool.h> /* for bool */ #include <libmisc/linkedlist.h> /* for lm_sll_root */ -#include <libmisc/macro.h> /* for LM_CAT2_() */ /** - * CR_RPC_DECLARE(NAME, REQ_T, RESP_T) declares the following types - * and methods: - * - * type: + * CR_RPC_DECLARE(NAME, REQ_T, RESP_T) declares the following types: * * / ** * * A NAME##_t is a fair rpc-channel on which the requester submits a @@ -38,105 +34,98 @@ * * the response RESP_T to the correct requester. `REQ_T req` is the * * only public member. * typedef struct { REQ_T req; ... } NAME##_req_t; + */ +#define CR_RPC_DECLARE(NAME, REQ_T, RESP_T) \ + typedef struct { \ + REQ_T req; \ + \ + RESP_T *_resp; /* where to write resp to */ \ + cid_t _requester; \ + } NAME##_req_t; \ + \ + typedef struct { \ + struct _cr_rpc core; \ + NAME##_req_t handle_typ[0]; \ + } NAME##_t + +/* Methods for NAME##_t *******************************************************/ + +/** + * cr_rpc_send_req(ch, req) submits the `req` request over `ch` and + * returns the response. * - * methods: + * @runs_in coroutine + * @cr_pauses always + * @cr_yields always * - * / ** - * * NAME##_send_req(ch, req) submits the `req` request over `ch` and - * * returns the response. - * * - * * @runs_in coroutine - * * @cr_pauses always - * * @cr_yields always - * * / - * RESP_T NAME##_send_req(NAME##_t *ch, REQ_T req); + * RESP_T cr_rpc_send_req(NAME##_t *ch, REQ_T req); + */ +#define cr_rpc_send_req(CH, REQ) ({ \ + cr_assert_in_coroutine(); \ + typeof((CH)->handle_typ[0].req) _req_lvalue = REQ; \ + typeof(*(CH)->handle_typ[0]._resp) _resp_lvalue; \ + _cr_rpc_send_req(&(CH)->core, \ + &_req_lvalue, sizeof(_req_lvalue), \ + &_resp_lvalue); \ + _resp_lvalue; \ +}) + +/** + * cr_rpc_recv_req(ch) reads a request from ch, and returns a + * NAME##_req_t handle wrapping that request. * - * / ** - * * NAME##_recv_req(ch) reads a request from ch, and returns a - * * NAME##_req_t handle wrapping that request. - * * - * * @runs_in coroutine - * * @cr_pauses maybe - * * @cr_yields maybe - * * / - * NAME##_req_t NAME##_recv_req(NAME##_t *ch); + * @runs_in coroutine + * @cr_pauses maybe + * @cr_yields maybe * - * / ** - * * NAME##_can_recv_req(ch) returns whether NAME##_recv_req(ch) - * * would return without pausing. - * * - * * @runs_in coroutine - * * @cr_pauses never - * * @cr_yields never - * * / - * bool NAME##_can_recv_req(NAME##_t *ch); + * NAME##_req_t cr_rcp_recv_req(NAME##_t *ch); + */ +#define cr_rpc_recv_req(CH) ({ \ + cr_assert_in_coroutine(); \ + typeof((CH)->handle_typ[0]) ret; \ + _cr_rpc_recv_req(&(CH)->core, \ + &ret.req, sizeof(ret.req), \ + (void **)&ret._resp, \ + &ret._requester); \ + ret; \ +}) + +/** + * cr_rpc_can_recv_req(ch) returns whether NAME##_recv_req(ch) + * would return without pausing. * - * type: + * @runs_in coroutine + * @cr_pauses never + * @cr_yields never * - * / ** - * * A NAME##_req_t is a handle that wraps a REQ_T, and is a channel - * * that a response may be written to. - * * / - * typedef ... NAME##_req_t; + * bool cr_rpc_can_recv_req(NAME##_t *ch); + */ +#define cr_rpc_can_recv_req(CH) ({ \ + cr_assert_in_coroutine(); \ + (bool)((CH)->core.waiters.front && \ + (CH)->core.waiter_typ == _CR_RPC_REQUESTER); \ +}) + +/* Methods for NAME##_req_t ***************************************************/ + +/** + * cr_rpc_send_resp(req, resp) sends the given response to the given + * request. * - * methods: + * @runs_in coroutine + * @cr_pauses never + * @cr_yields always * - * / ** - * * cr_rpc_send_resp(req, resp) sends the given response to the given - * * request. - * * - * * @runs_in coroutine - * * @cr_pauses never - * * @cr_yields always - * * / - * void NAME##_send_resp(NAME##_req_t req, RESP_T resp); + * void cr_rpc_send_resp(NAME##_req_t req, RESP_T resp); */ -#define CR_RPC_DECLARE(NAME, REQ_T, RESP_T) \ - typedef struct { \ - REQ_T req; \ - \ - RESP_T *_resp; /* where to write resp to */ \ - cid_t _requester; \ - } NAME##_req_t; \ - \ - typedef struct { \ - struct _cr_rpc core; \ - NAME##_req_t handle[0]; \ - } NAME##_t; \ - \ - static inline RESP_T NAME##_send_req(NAME##_t *ch, REQ_T req) { \ - cr_assert_in_coroutine(); \ - RESP_T resp; \ - _cr_rpc_send_req(&ch->core, \ - &req, sizeof(req), \ - &resp); \ - return resp; \ - } \ - \ - static inline NAME##_req_t NAME##_recv_req(NAME##_t *ch) { \ - cr_assert_in_coroutine(); \ - NAME##_req_t ret; \ - _cr_rpc_recv_req(&ch->core, \ - &ret.req, sizeof(ret.req), \ - (void **)&ret._resp, \ - &ret._requester); \ - return ret; \ - } \ - \ - static inline bool NAME##_can_recv_req(NAME##_t *ch) { \ - cr_assert_in_coroutine(); \ - return ch->core.waiters.front && \ - ch->core.waiter_typ == _CR_RPC_REQUESTER; \ - } \ - \ - static inline void NAME##_send_resp(NAME##_req_t req, RESP_T resp) { \ - cr_assert_in_coroutine(); \ - *(req._resp) = resp; \ - cr_unpause(req._requester); \ - cr_yield(); \ - } \ - \ - extern int LM_CAT2_(_CR_RPC_FORCE_SEMICOLON_, __COUNTER__) +#define cr_rpc_send_resp(REQ, RESP) { \ + cr_assert_in_coroutine(); \ + *((REQ)._resp) = RESP; \ + cr_unpause(REQ._requester); \ + cr_yield(); \ +} while(0) + +/* Background details *********************************************************/ enum _cr_rpc_waiter_typ { _CR_RPC_REQUESTER, diff --git a/libcr_ipc/tests/test_rpc.c b/libcr_ipc/tests/test_rpc.c index 1e3c471..910b738 100644 --- a/libcr_ipc/tests/test_rpc.c +++ b/libcr_ipc/tests/test_rpc.c @@ -18,10 +18,10 @@ COROUTINE cr_caller(void *_ch) { intrpc_t *ch = _ch; cr_begin(); - int resp = intrpc_send_req(ch, 1); + int resp = cr_rpc_send_req(ch, 1); test_assert(resp == 2); - resp = intrpc_send_req(ch, 3); + resp = cr_rpc_send_req(ch, 3); test_assert(resp == 4); cr_exit(); @@ -31,9 +31,9 @@ COROUTINE cr_worker1(void *_ch) { intrpc_t *ch = _ch; cr_begin(); - intrpc_req_t req = intrpc_recv_req(ch); + intrpc_req_t req = cr_rpc_recv_req(ch); test_assert(req.req == 1); - intrpc_send_resp(req, 2); + cr_rpc_send_resp(req, 2); cr_exit(); } @@ -42,9 +42,9 @@ COROUTINE cr_worker2(void *_ch) { intrpc_t *ch = _ch; cr_begin(); - intrpc_req_t req = intrpc_recv_req(ch); + intrpc_req_t req = cr_rpc_recv_req(ch); test_assert(req.req == 3); - intrpc_send_resp(req, 4); + cr_rpc_send_resp(req, 4); cr_exit(); } |