diff options
Diffstat (limited to 'libcr_ipc/include')
-rw-r--r-- | libcr_ipc/include/libcr_ipc/chan.h | 189 | ||||
-rw-r--r-- | libcr_ipc/include/libcr_ipc/mutex.h | 8 | ||||
-rw-r--r-- | libcr_ipc/include/libcr_ipc/rpc.h | 185 | ||||
-rw-r--r-- | libcr_ipc/include/libcr_ipc/rwmutex.h | 12 | ||||
-rw-r--r-- | libcr_ipc/include/libcr_ipc/sema.h | 10 |
5 files changed, 199 insertions, 205 deletions
diff --git a/libcr_ipc/include/libcr_ipc/chan.h b/libcr_ipc/include/libcr_ipc/chan.h index 80acdb8..5a87643 100644 --- a/libcr_ipc/include/libcr_ipc/chan.h +++ b/libcr_ipc/include/libcr_ipc/chan.h @@ -10,16 +10,12 @@ #include <stdbool.h> /* for bool */ #include <stddef.h> /* for size_t */ -#include <libmisc/linkedlist.h> /* for lm_dll_root */ -#include <libmisc/macro.h> /* for LM_CAT2_() */ +#include <libmisc/linkedlist.h> /* for DLIST_DECLARE() */ /* base channels **************************************************************/ /** - * CR_CHAN_DECLARE(NAME, VAL_T) declares the following type and - * methods: - * - * type: + * CR_CHAN_DECLARE(NAME, VAL_T) declares the following type: * * / ** * * A NAME##_t is a fair unbuffered channel that transports @@ -32,87 +28,89 @@ * * something from an interrupt handler. * * / * typedef ... NAME##_t; + */ +#define CR_CHAN_DECLARE(NAME, VAL_T) \ + typedef struct { \ + struct _cr_chan core; \ + VAL_T val_typ[0]; \ + } NAME##_t + +/** + * cr_chan_send(ch, val) sends `val` over `ch`. * - * methods: + * @runs_in coroutine + * @cr_pauses maybe + * @cr_yields always * - * / ** - * * NAME##_send(ch, val) sends `val` over `ch`. - * * - * * @runs_in coroutine - * * @cr_pauses maybe - * * @cr_yields always - * * / - * void NAME##_send(NAME##_t *ch, VAL_T val); + * void cr_chan_send(NAME##_t *ch, VAL_T val); + */ +#define cr_chan_send(CH, VAL) do { \ + cr_assert_in_coroutine(); \ + typeof((CH)->val_typ[0]) _val_lvalue = VAL; \ + _cr_chan_xfer(_CR_CHAN_SENDER, &(CH)->core, \ + &_val_lvalue, sizeof(_val_lvalue)); \ +} while(0) + +/** + * cr_chan_recv(ch) reads and returns a value from ch. * - * / ** - * * NAME##_recv(ch) reads and returns a value from ch. - * * - * * @runs_in coroutine - * * @cr_pauses maybe - * * @cr_yields always - * * / - * VAL_T NAME##_recv(NAME##_t *ch); + * @runs_in coroutine + * @cr_pauses maybe + * @cr_yields always * - * / ** - * * NAME##_can_send(ch) returns whether NAME##_send(ch, val) - * * would run without pausing. - * * - * * @runs_in coroutine - * * @cr_pauses never - * * @cr_yields never - * * / - * bool NAME##_can_send(NAME##_t *ch); + * VAL_T cr_chan_recv(NAME##_T ch); + */ +#define cr_chan_recv(CH) ({ \ + cr_assert_in_coroutine(); \ + typeof((CH)->val_typ[0]) _val_lvalue; \ + _cr_chan_xfer(_CR_CHAN_RECVER, &(CH)->core, \ + &_val_lvalue, sizeof(_val_lvalue)); \ + _val_lvalue; \ +}) + +/** + * cr_chan_can_send(ch) returns whether cr_chan_send(ch, val) would + * run without pausing. * - * / ** - * * NAME##_can_recv(ch) returns whether NAME##_recv(ch) would - * * return without pausing. - * * - * * @runs_in coroutine - * * @cr_pauses never - * * @cr_yields never - * * / - * NAME##_can_recv(NAME##_t *ch); + * @runs_in coroutine + * @cr_pauses never + * @cr_yields never + * + * bool cr_chan_can_send(NAME##_t *ch); */ -#define CR_CHAN_DECLARE(NAME, VAL_T) \ - typedef struct { \ - struct _cr_chan core; \ - VAL_T vals[0]; \ - } NAME##_t; \ - \ - static inline void NAME##_send(NAME##_t *ch, VAL_T val) { \ - cr_assert_in_coroutine(); \ - _cr_chan_xfer(_CR_CHAN_SENDER, &ch->core, &val, sizeof(val)); \ - } \ - \ - static inline VAL_T NAME##_recv(NAME##_t *ch) { \ - cr_assert_in_coroutine(); \ - VAL_T val; \ - _cr_chan_xfer(_CR_CHAN_RECVER, &ch->core, &val, sizeof(val)); \ - return val; \ - } \ - \ - static inline bool NAME##_can_send(NAME##_t *ch) { \ - cr_assert_in_coroutine(); \ - return ch->core.waiters.front && \ - ch->core.waiter_typ == _CR_CHAN_RECVER; \ - } \ - \ - static inline bool NAME##_can_recv(NAME##_t *ch) { \ - cr_assert_in_coroutine(); \ - return ch->core.waiters.front && \ - ch->core.waiter_typ == _CR_CHAN_SENDER; \ - } \ - \ - extern int LM_CAT2_(_CR_CHAN_FORCE_SEMICOLON_, __COUNTER__) +#define cr_chan_can_send(CH) ({ \ + cr_assert_in_coroutine(); \ + (bool)((CH)->core.waiters.front && \ + (CH)->core.waiter_typ == _CR_CHAN_RECVER); \ +}) + +/** + * cr_chan_can_recv(ch) returns whether cr_chan_recv(ch) would return + * without pausing. + * + * @runs_in coroutine + * @cr_pauses never + * @cr_yields never + * + * bool cr_chan_can_recv(NAME##_t *ch); + */ +#define cr_chan_can_recv(CH) ({ \ + cr_assert_in_coroutine(); \ + (bool)((CH)->core.waiters.front && \ + (CH)->core.waiter_typ == _CR_CHAN_SENDER); \ +}) + enum _cr_chan_waiter_typ { _CR_CHAN_SENDER, _CR_CHAN_RECVER, }; +DLIST_DECLARE(_cr_chan_waiter_list); + struct _cr_chan { - enum _cr_chan_waiter_typ waiter_typ; - lm_dll_root waiters; + enum _cr_chan_waiter_typ waiter_typ; + struct _cr_chan_waiter_list waiters; }; void _cr_chan_xfer(enum _cr_chan_waiter_typ self_typ, struct _cr_chan *ch, void *val_ptr, size_t val_size); @@ -134,31 +132,30 @@ struct cr_select_arg { size_t val_siz; }; -#define CR_SELECT_RECV(CH, VALP) \ - /* The _valp temporary variable is to get the compiler to check that \ - * the types are compatible. */ \ - ((struct cr_select_arg){ \ - .op = _CR_SELECT_OP_RECV, \ - .ch = &((CH)->core), \ - .val_ptr = ({ typeof((CH)->vals[0]) *_valp = VALP; _valp; }), \ - .val_siz = sizeof((CH)->vals[0]), \ - }) +#define CR_SELECT_RECV(CH, VALP) ((struct cr_select_arg){ \ + .op = _CR_SELECT_OP_RECV, \ + .ch = &((CH)->core), \ + /* The _valp temporary variable is to get the compiler to check that \ + * the types are compatible. */ \ + .val_ptr = ({ typeof((CH)->val_typ[0]) *_valp = VALP; _valp; }), \ + .val_siz = sizeof((CH)->val_typ[0]), \ +}) + /* BUG: It's bogus that CR_SELECT_SEND takes VALP instead of VAL, but * since we need an address, taking VAL would introduce uncomfortable * questions about where VAL sits on the stack. */ -#define CR_SELECT_SEND(CH, VALP) \ - /* The _valp temporary variable is to get the compiler to check that \ - * the types are compatible. */ \ - ((struct cr_select_arg){ \ - .op = _CR_SELECT_OP_SEND, \ - .ch = &((CH)->core), \ - .val_ptr = ({ typeof((CH)->vals[0]) *_valp = VALP; _valp; }), \ - .val_siz = sizeof((CH)->vals[0]), \ - }) -#define CR_SELECT_DEFAULT \ - ((struct cr_select_arg){ \ - .op = _CR_SELECT_OP_DEFAULT, \ - }) +#define CR_SELECT_SEND(CH, VALP) ((struct cr_select_arg){ \ + .op = _CR_SELECT_OP_SEND, \ + .ch = &((CH)->core), \ + /* The _valp temporary variable is to get the compiler to check that \ + * the types are compatible. */ \ + .val_ptr = ({ typeof((CH)->val_typ[0]) *_valp = VALP; _valp; }), \ + .val_siz = sizeof((CH)->val_typ[0]), \ +}) + +#define CR_SELECT_DEFAULT ((struct cr_select_arg){ \ + .op = _CR_SELECT_OP_DEFAULT, \ +}) /* cr_select_v(arg_cnt, arg_vec) **********************************************/ diff --git a/libcr_ipc/include/libcr_ipc/mutex.h b/libcr_ipc/include/libcr_ipc/mutex.h index 0f3c9c2..e5f43c8 100644 --- a/libcr_ipc/include/libcr_ipc/mutex.h +++ b/libcr_ipc/include/libcr_ipc/mutex.h @@ -9,9 +9,11 @@ #include <stdbool.h> /* for bool */ -#include <libmisc/linkedlist.h> +#include <libmisc/linkedlist.h> /* for SLIST_DECLARE() */ #include <libmisc/private.h> +SLIST_DECLARE(_cr_mutex_waiter_list); + /** * A cr_mutex_t is a fair mutex. * @@ -22,8 +24,8 @@ */ typedef struct { BEGIN_PRIVATE(LIBCR_IPC_MUTEX_H); - bool locked; - lm_sll_root waiters; + bool locked; + struct _cr_mutex_waiter_list waiters; END_PRIVATE(LIBCR_IPC_MUTEX_H); } cr_mutex_t; diff --git a/libcr_ipc/include/libcr_ipc/rpc.h b/libcr_ipc/include/libcr_ipc/rpc.h index f091685..ecf48cf 100644 --- a/libcr_ipc/include/libcr_ipc/rpc.h +++ b/libcr_ipc/include/libcr_ipc/rpc.h @@ -9,14 +9,10 @@ #include <stdbool.h> /* for bool */ -#include <libmisc/linkedlist.h> /* for lm_sll_root */ -#include <libmisc/macro.h> /* for LM_CAT2_() */ +#include <libmisc/linkedlist.h> /* for SLIST_DECLARE() */ /** - * 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,114 +34,109 @@ * * 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, _CR_RPC_RESPONDER, }; +SLIST_DECLARE(_cr_rpc_waiter_list); + struct _cr_rpc { enum _cr_rpc_waiter_typ waiter_typ; - lm_sll_root waiters; + struct _cr_rpc_waiter_list waiters; }; void _cr_rpc_send_req(struct _cr_rpc *ch, void *req_ptr, size_t req_size, void *resp_ptr); diff --git a/libcr_ipc/include/libcr_ipc/rwmutex.h b/libcr_ipc/include/libcr_ipc/rwmutex.h index d48abe9..8ccae63 100644 --- a/libcr_ipc/include/libcr_ipc/rwmutex.h +++ b/libcr_ipc/include/libcr_ipc/rwmutex.h @@ -9,9 +9,11 @@ #include <stdbool.h> -#include <libmisc/linkedlist.h> +#include <libmisc/linkedlist.h> /* for SLIST_DECLARE() */ #include <libmisc/private.h> +SLIST_DECLARE(_cr_rwmutex_waiter_list); + /** * A cr_rwmutex_t is a fair read/write mutex. * @@ -25,10 +27,10 @@ */ typedef struct { BEGIN_PRIVATE(LIBCR_IPC_RWMUTEX_H); - unsigned nreaders; - bool locked; - bool unpausing; - lm_sll_root waiters; + unsigned nreaders; + bool locked; + bool unpausing; + struct _cr_rwmutex_waiter_list waiters; END_PRIVATE(LIBCR_IPC_RWMUTEX_H); } cr_rwmutex_t; diff --git a/libcr_ipc/include/libcr_ipc/sema.h b/libcr_ipc/include/libcr_ipc/sema.h index cc387f4..8b5ac5b 100644 --- a/libcr_ipc/include/libcr_ipc/sema.h +++ b/libcr_ipc/include/libcr_ipc/sema.h @@ -9,9 +9,11 @@ #include <stdbool.h> -#include <libmisc/linkedlist.h> +#include <libmisc/linkedlist.h> /* for SLIST_DECLARE() */ #include <libmisc/private.h> +SLIST_DECLARE(_cr_sema_waiter_list); + /** * A cr_sema_t is a fair unbounded[1] counting semaphore. * @@ -19,9 +21,9 @@ */ typedef struct { BEGIN_PRIVATE(LIBCR_IPC_SEMA_H); - unsigned int cnt; - bool unpausing; - lm_sll_root waiters; + unsigned int cnt; + bool unpausing; + struct _cr_sema_waiter_list waiters; END_PRIVATE(LIBCR_IPC_SEMA_H); } cr_sema_t; |