diff options
-rw-r--r-- | lib9p/srv.c | 12 | ||||
-rw-r--r-- | libcr_ipc/include/libcr_ipc/chan.h | 181 | ||||
-rw-r--r-- | libcr_ipc/tests/test_chan.c | 10 | ||||
-rw-r--r-- | libcr_ipc/tests/test_select.c | 4 | ||||
-rw-r--r-- | libhw_cr/w5500.c | 6 |
5 files changed, 104 insertions, 109 deletions
diff --git a/lib9p/srv.c b/lib9p/srv.c index 7e2bab0..d3748b7 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -45,14 +45,14 @@ static_assert(CONFIG_9P_SRV_MAX_HOSTMSG_SIZE <= SSIZE_MAX); bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx) { assert(ctx); - return _lib9p_srv_flushch_can_send(&ctx->flushch); + return cr_chan_can_send(&ctx->flushch); } void lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx) { assert(ctx); - assert(_lib9p_srv_flushch_can_send(&ctx->flushch)); + assert(cr_chan_can_send(&ctx->flushch)); lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_ECANCELED, "request canceled by flush"); - _lib9p_srv_flushch_send(&ctx->flushch, true); + cr_chan_send(&ctx->flushch, true); } /* structs ********************************************************************/ @@ -580,8 +580,8 @@ void lib9p_srv_worker_loop(struct lib9p_srv *srv) { handle_message(&req); /* Release resources. ****************************************/ - while (_lib9p_srv_flushch_can_send(&req.flushch)) - _lib9p_srv_flushch_send(&req.flushch, false); + while (cr_chan_can_send(&req.flushch)) + cr_chan_send(&req.flushch, false); map_del(&req.parent_sess->reqs, req.tag); if (req.parent_sess->closing && !map_len(&req.parent_sess->reqs)) cr_unpause(req.parent_sess->parent_conn->reader); @@ -868,7 +868,7 @@ static void handle_Tflush(struct srv_req *ctx, struct srv_req **oldreqp = map_load(&ctx->parent_sess->reqs, req->oldtag); if (oldreqp) - _lib9p_srv_flushch_recv(&((*oldreqp)->flushch)); + cr_chan_recv(&((*oldreqp)->flushch)); } static void handle_Twalk(struct srv_req *ctx, diff --git a/libcr_ipc/include/libcr_ipc/chan.h b/libcr_ipc/include/libcr_ipc/chan.h index 80acdb8..5282725 100644 --- a/libcr_ipc/include/libcr_ipc/chan.h +++ b/libcr_ipc/include/libcr_ipc/chan.h @@ -11,15 +11,11 @@ #include <stddef.h> /* for size_t */ #include <libmisc/linkedlist.h> /* for lm_dll_root */ -#include <libmisc/macro.h> /* for LM_CAT2_() */ /* 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,78 +28,78 @@ * * 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_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_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_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, @@ -134,31 +130,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/tests/test_chan.c b/libcr_ipc/tests/test_chan.c index 9b6f018..e5d9dc8 100644 --- a/libcr_ipc/tests/test_chan.c +++ b/libcr_ipc/tests/test_chan.c @@ -15,12 +15,12 @@ COROUTINE cr_producer(void *_ch) { intchan_t *ch = _ch; cr_begin(); - intchan_send(ch, 1); + cr_chan_send(ch, 1); - while (!intchan_can_send(ch)) + while (!cr_chan_can_send(ch)) cr_yield(); - intchan_send(ch, 2); + cr_chan_send(ch, 2); cr_end(); @@ -31,10 +31,10 @@ COROUTINE cr_consumer(void *_ch) { intchan_t *ch = _ch; cr_begin(); - x = intchan_recv(ch); + x = cr_chan_recv(ch); test_assert(x == 1); - x = intchan_recv(ch); + x = cr_chan_recv(ch); test_assert(x == 2); cr_end(); diff --git a/libcr_ipc/tests/test_select.c b/libcr_ipc/tests/test_select.c index 1db645b..f0a71a3 100644 --- a/libcr_ipc/tests/test_select.c +++ b/libcr_ipc/tests/test_select.c @@ -65,7 +65,7 @@ COROUTINE cr_producer(void *_n) { int n = *(int *)_n; cr_begin(); - intchan_send(&ch[n], n); + cr_chan_send(&ch[n], n); cr_end(); } @@ -73,7 +73,7 @@ COROUTINE cr_producer(void *_n) { COROUTINE cr_final(void *) { cr_begin(); - int ret = intchan_recv(&fch); + int ret = cr_chan_recv(&fch); printf("ret=%d\n", ret); test_assert(ret == 567); diff --git a/libhw_cr/w5500.c b/libhw_cr/w5500.c index fa427d9..c04e344 100644 --- a/libhw_cr/w5500.c +++ b/libhw_cr/w5500.c @@ -217,7 +217,7 @@ static COROUTINE w5500_irq_cr(void *_chip) { } if (send_bits) { debugf("w5500_irq_cr(): signal sock[%"PRIu8"]->write_ch", socknum); - _w5500_sockintr_ch_send(&socket->write_ch, send_bits); + cr_chan_send(&socket->write_ch, send_bits); } break; } @@ -666,7 +666,7 @@ static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec w5500_socket_cmd(socket, CMD_SEND); cr_mutex_unlock(&chip->mu); - switch (_w5500_sockintr_ch_recv(&socket->write_ch)) { + switch (cr_chan_recv(&socket->write_ch)) { case SOCKINTR_SEND_OK: debugf(" => sent %zu", freesize); done += freesize; @@ -853,7 +853,7 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t w5500_socket_cmd(socket, CMD_SEND); cr_mutex_unlock(&chip->mu); - switch (_w5500_sockintr_ch_recv(&socket->write_ch)) { + switch (cr_chan_recv(&socket->write_ch)) { case SOCKINTR_SEND_OK: debugf(" => sent"); return count; |