summaryrefslogtreecommitdiff
path: root/libcr_ipc
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
parentd54ddec236bf9bdb8c032cd5fbdb0aa46ffebe86 (diff)
fixes
Diffstat (limited to 'libcr_ipc')
-rw-r--r--libcr_ipc/CMakeLists.txt3
-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
-rw-r--r--libcr_ipc/sema.c34
5 files changed, 85 insertions, 63 deletions
diff --git a/libcr_ipc/CMakeLists.txt b/libcr_ipc/CMakeLists.txt
index b794908..3388fcd 100644
--- a/libcr_ipc/CMakeLists.txt
+++ b/libcr_ipc/CMakeLists.txt
@@ -8,3 +8,6 @@ target_include_directories(libcr_ipc SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/
target_sources(libcr_ipc INTERFACE
sema.c
)
+target_link_libraries(libcr_ipc INTERFACE
+ libcr
+)
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,
diff --git a/libcr_ipc/sema.c b/libcr_ipc/sema.c
index a8b5ec4..5f489aa 100644
--- a/libcr_ipc/sema.c
+++ b/libcr_ipc/sema.c
@@ -6,27 +6,11 @@
#include <assert.h>
-#include "coroutine_sema.h"
-
-struct cid_list {
- cid_t val;
- struct cid_list *next;
-};
-
-/* head->next->next->tail */
-
-struct _cr_sema {
- int cnt;
-
- struct 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;
-};
+#include <libcr/coroutine.h>
+#include <libcr_ipc/sema.h>
/** Drain the sema->{head,tail} list. Returns true if cr_getcid() was drained. */
-static inline bool drain(volatile cr_sema_t *sema) {
+static inline bool drain(cr_sema_t *sema) {
assert(!sema->locked);
cid_t self = cr_getcid();
@@ -59,21 +43,21 @@ static inline bool drain(volatile cr_sema_t *sema) {
/* If there are still coroutines in sema->head, check
* that sema->cnt wasn't incremented between `if
* (!sema->cnt)` and `sema->locked = false`. */
- } while (state == DRAINED_SOME && cnt);
+ } while (state == DRAINED_SOME && sema->cnt);
/* If state == DRAINED_SELF, then we better have been the last
* item in the list! */
assert(state != DRAINED_SELF || !sema->head);
return state == DRAINED_SELF;
}
-void cr_sema_signal(volatile cr_sema_t *sema) {
+void cr_sema_signal(cr_sema_t *sema) {
sema->cnt++;
if (!sema->locked)
- drain();
+ drain(sema);
}
-void cr_sema_wait(volatile cr_sema_t *sema) {
- struct cid_list self = {
+void cr_sema_wait(cr_sema_t *sema) {
+ struct _cr_sema_cid_list self = {
.val = cr_getcid(),
.next = NULL,
};
@@ -86,7 +70,7 @@ void cr_sema_wait(volatile cr_sema_t *sema) {
sema->tail = &(self.next);
sema->locked = false;
- if (drain())
+ if (drain(sema))
/* DRAINED_SELF: (1) No need to pause+yield, (2) we
* better have been the last item in the list! */
assert(!self.next);