summaryrefslogtreecommitdiff
path: root/libcr_ipc/include
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-27 20:45:36 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-27 20:45:36 -0600
commitfa357459f88bb8f0170d1a68df66e7d068d59996 (patch)
tree8585b5755ae224c6609f982d973141f1f6bad97b /libcr_ipc/include
parentd54ddec236bf9bdb8c032cd5fbdb0aa46ffebe86 (diff)
fixes
Diffstat (limited to 'libcr_ipc/include')
-rw-r--r--libcr_ipc/include/libcr_ipc/chan.h2
-rw-r--r--libcr_ipc/include/libcr_ipc/rpc.h94
-rw-r--r--libcr_ipc/include/libcr_ipc/sema.h15
3 files changed, 73 insertions, 38 deletions
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 <assert.h>
-#include "coroutine.h"
+#include <libcr/coroutine.h>
/**
* 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 <assert.h>
-#include "coroutine.h"
+#include <libcr/coroutine.h>
/**
* 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,