From fa357459f88bb8f0170d1a68df66e7d068d59996 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Fri, 27 Sep 2024 20:45:36 -0600 Subject: fixes --- libcr_ipc/include/libcr_ipc/chan.h | 2 +- libcr_ipc/include/libcr_ipc/rpc.h | 94 +++++++++++++++++++++++--------------- libcr_ipc/include/libcr_ipc/sema.h | 15 +++++- 3 files changed, 73 insertions(+), 38 deletions(-) (limited to 'libcr_ipc/include') diff --git a/libcr_ipc/include/libcr_ipc/chan.h b/libcr_ipc/include/libcr_ipc/chan.h index a3621a6..66ea1c4 100644 --- a/libcr_ipc/include/libcr_ipc/chan.h +++ b/libcr_ipc/include/libcr_ipc/chan.h @@ -14,7 +14,7 @@ #include -#include "coroutine.h" +#include /** * cr_chan_t(val_t) returns the type definition for a channel on diff --git a/libcr_ipc/include/libcr_ipc/rpc.h b/libcr_ipc/include/libcr_ipc/rpc.h index 11d40d7..3c42f34 100644 --- a/libcr_ipc/include/libcr_ipc/rpc.h +++ b/libcr_ipc/include/libcr_ipc/rpc.h @@ -13,11 +13,11 @@ #include -#include "coroutine.h" +#include /** * cr_rpc_t(req_t, resp_t) returns the type definition for a - * rcp-channel on which the requester submits a value of type `req_t` + * rpc-channel on which the requester submits a value of type `req_t` * and the responder responds with a value of type `resp_t`. * * There may be multiple concurrent requesters, but only one @@ -31,6 +31,10 @@ resp_t *resp_p; \ } +#define _cr_rpc_static_assert_sametype(a, b, msg) \ + static_assert(_Generic(a, typeof(b): 1, default: 0), msg) +#define _cr_rpc_str(a) #a + /* These "functions" are preprocessor macros instead of real C * functions so that the compiler can do type-checking instead of * having these functions take `void*`. */ @@ -42,29 +46,38 @@ * Blocking: Always; until the responder has called both * cr_rpc_recv_req() and cr_rpc_send_resp(). */ -#define cr_rpc_req(ch, _resp_p, _req) do { \ - cid_t next = 0; \ - if ((ch)->requester) { \ - *((ch)->tail_requester = cr_getcid(); \ - (ch)->tail_requester = &next; \ - cr_pause_and_yield(); \ - } else { \ - (ch)->requester = cr_getcid(); \ - (ch)->tail_requester = &next; \ - } \ - assert((ch)->requester == cr_getcid()); \ - (ch)->req_p = &(_req); \ - (ch)->resp_p = (_resp_p; \ - if ((ch)->responder != 0) \ - cr_unpause((ch)->responder); \ - cr_pause_and_yield(); \ - if (next) { \ - (ch)->requester = next; \ - cr_unpause(next); \ - } else { \ - (ch)->requester = 0; \ - (ch)->tail_requester = NULL; \ - } +#define cr_rpc_req(ch, _resp_p, _req) do { \ + typeof(_req) _req_lvalue = _req; \ + _cr_rpc_static_assert_sametype(_resp_p, (ch)->resp_p, \ + "wrong resp_p type for rpc chan: " \ + _cr_rpc_str(_resp_p)); \ + _cr_rpc_static_assert_sametype(&_req_lvalue, (ch)->req_p, \ + "wrong req type for rpc chan: " \ + _cr_rpc_str(_req)); \ + assert(ch); \ + assert(_resp_p); \ + cid_t next = 0; \ + if ((ch)->requester) { \ + *((ch)->tail_requester) = cr_getcid(); \ + (ch)->tail_requester = &next; \ + cr_pause_and_yield(); \ + } else { \ + (ch)->requester = cr_getcid(); \ + (ch)->tail_requester = &next; \ + } \ + assert((ch)->requester == cr_getcid()); \ + (ch)->req_p = &_req_lvalue; \ + (ch)->resp_p = (_resp_p); \ + if ((ch)->responder != 0) \ + cr_unpause((ch)->responder); \ + cr_pause_and_yield(); \ + if (next) { \ + (ch)->requester = next; \ + cr_unpause(next); \ + } else { \ + (ch)->requester = 0; \ + (ch)->tail_requester = NULL; \ + } \ } while (0) /** @@ -84,12 +97,17 @@ * * Blocking: Maybe. */ -#define cr_rpc_recv_req(ch, _req_p) do { \ - (ch)->responder = cr_getcid(); \ - if ((ch)->requester == 0) \ - cr_pause_and_yield(); \ - *(_req_p) = *((ch)->req_p); \ - (ch)->req_p = NULL; \ +#define cr_rpc_recv_req(ch, _req_p) do { \ + _cr_rpc_static_assert_sametype(_req_p, (ch)->req_p, \ + "wrong req_p type for rpc chan: " \ + _cr_rpc_str(_req_p)); \ + assert(ch); \ + assert(_req_p); \ + (ch)->responder = cr_getcid(); \ + if ((ch)->requester == 0) \ + cr_pause_and_yield(); \ + *(_req_p) = *((ch)->req_p); \ + (ch)->req_p = NULL; \ } while (0) /** @@ -98,11 +116,15 @@ * * Blocking: Never. */ -#define cr_rpc_send_resp(ch, _resp) do { \ - (ch)->responder = 0; \ - *((ch)->resp_p) = (_resp); \ - (ch)->resp_p = NULL; \ - cr_unpause((ch)->requester); \ +#define cr_rpc_send_resp(ch, _resp) do { \ + _cr_rpc_static_assert_sametype(_resp, *(ch)->resp_p, \ + "wrong resp type for rpc chan: " \ + _cr_rpc_str(_reps)); \ + assert(ch); \ + (ch)->responder = 0; \ + *((ch)->resp_p) = (_resp); \ + (ch)->resp_p = NULL; \ + cr_unpause((ch)->requester); \ } while (0) #endif /* _COROUTINE_RPC_H_ */ diff --git a/libcr_ipc/include/libcr_ipc/sema.h b/libcr_ipc/include/libcr_ipc/sema.h index 57d5855..a2a176d 100644 --- a/libcr_ipc/include/libcr_ipc/sema.h +++ b/libcr_ipc/include/libcr_ipc/sema.h @@ -7,12 +7,25 @@ #ifndef _COROUTINE_SEMA_H_ #define _COROUTINE_SEMA_H_ +struct _cr_sema_cid_list { + cid_t val; + struct _cr_sema_cid_list *next; +}; + /** * A cr_sema_t is a fair unbounded[1] counting semaphore. * * [1]: Well, INT_MAX */ -typedef struct sema_t cr_sema_t; +typedef volatile struct { + int cnt; + + struct _cr_sema_cid_list *head, **tail; + /* locked indicates that a call from within a coroutine is is + * messing with ->{head,tail}, so a signal handler can't read + * it. */ + bool locked; +} cr_sema_t; /** * Increment the semaphore, -- cgit v1.2.3-2-g168b