summaryrefslogtreecommitdiff
path: root/libcr_ipc/chan.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-03-01 17:28:29 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-03-01 17:28:29 -0700
commit188ac62a0c0f5519f5d45519fa7d224cb25305c6 (patch)
tree5543f56fc89c548cf411f76e317894005a6b198c /libcr_ipc/chan.c
parentf929205572e1d56fa3719b426b45aafded58e86a (diff)
parent18ad76a7a2baa9c78e01e85886f693e572fcb2a9 (diff)
Merge branch 'lukeshu/misc'
Diffstat (limited to 'libcr_ipc/chan.c')
-rw-r--r--libcr_ipc/chan.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/libcr_ipc/chan.c b/libcr_ipc/chan.c
new file mode 100644
index 0000000..7dd1132
--- /dev/null
+++ b/libcr_ipc/chan.c
@@ -0,0 +1,40 @@
+/* libcr_ipc/chan.c - Simple channels for libcr
+ *
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libcr_ipc/chan.h>
+
+void _cr_chan_dequeue(void *_ch, size_t) {
+ struct _cr_chan *ch = _ch;
+ _cr_ipc_dll_pop_from_front(&ch->waiters);
+}
+
+void _cr_chan_xfer(enum _cr_chan_waiter_typ self_typ, struct _cr_chan *ch, void *val_ptr, size_t val_size) {
+ assert(ch);
+ assert(val_ptr);
+
+ if (ch->waiters.front && ch->waiter_typ != self_typ) { /* non-blocking fast-path */
+ /* Copy. */
+ struct _cr_chan_waiter *front = _cr_ipc_dll_node_cast(struct _cr_chan_waiter, ch->waiters.front);
+ if (self_typ == _CR_CHAN_SENDER)
+ memcpy(front->val_ptr, val_ptr, val_size);
+ else
+ memcpy(val_ptr, front->val_ptr, val_size);
+ cr_unpause(front->cid);
+ front->dequeue(front->dequeue_arg1,
+ front->dequeue_arg2);
+ cr_yield();
+ } else { /* blocking slow-path */
+ struct _cr_chan_waiter self = {
+ .cid = cr_getcid(),
+ .val_ptr = val_ptr,
+ .dequeue = _cr_chan_dequeue,
+ .dequeue_arg1 = ch,
+ };
+ _cr_ipc_dll_push_to_rear(&ch->waiters, &self);
+ ch->waiter_typ = self_typ;
+ cr_pause_and_yield();
+ }
+}