diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-02-28 20:15:16 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-03-01 14:51:40 -0700 |
commit | 902a7661cfed71b1f50aa95bac9345883cb435cc (patch) | |
tree | 339e8e4b01b36047ee3b2910a4aa3b46ed528fcb /libcr_ipc | |
parent | 4f1abf2b9472a47da65d117f72dcdffca65b888e (diff) |
Fix linker confusion
Diffstat (limited to 'libcr_ipc')
-rw-r--r-- | libcr_ipc/CMakeLists.txt | 4 | ||||
-rw-r--r-- | libcr_ipc/chan.c | 40 | ||||
-rw-r--r-- | libcr_ipc/include/libcr_ipc/chan.h | 36 | ||||
-rw-r--r-- | libcr_ipc/include/libcr_ipc/select.h | 98 | ||||
-rw-r--r-- | libcr_ipc/select.c | 102 |
5 files changed, 152 insertions, 128 deletions
diff --git a/libcr_ipc/CMakeLists.txt b/libcr_ipc/CMakeLists.txt index 0c3bd57..4590bdd 100644 --- a/libcr_ipc/CMakeLists.txt +++ b/libcr_ipc/CMakeLists.txt @@ -5,6 +5,10 @@ add_library(libcr_ipc INTERFACE) target_include_directories(libcr_ipc SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) +target_sources(libcr_ipc INTERFACE + chan.c + select.c +) target_link_libraries(libcr_ipc INTERFACE libcr ) 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(); + } +} diff --git a/libcr_ipc/include/libcr_ipc/chan.h b/libcr_ipc/include/libcr_ipc/chan.h index da4f08e..5b1e583 100644 --- a/libcr_ipc/include/libcr_ipc/chan.h +++ b/libcr_ipc/include/libcr_ipc/chan.h @@ -1,6 +1,6 @@ /* libcr_ipc/chan.h - Simple channels for libcr * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ @@ -122,37 +122,7 @@ struct _cr_chan { _cr_ipc_dll_root waiters; }; -static void _cr_chan_dequeue(void *_ch, size_t) { - struct _cr_chan *ch = _ch; - _cr_ipc_dll_pop_from_front(&ch->waiters); -} - -static inline 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(); - } -} +void _cr_chan_dequeue(void *_ch, size_t); +void _cr_chan_xfer(enum _cr_chan_waiter_typ self_typ, struct _cr_chan *ch, void *val_ptr, size_t val_size); #endif /* _LIBCR_IPC_CHAN_H_ */ diff --git a/libcr_ipc/include/libcr_ipc/select.h b/libcr_ipc/include/libcr_ipc/select.h index ee49cca..b845082 100644 --- a/libcr_ipc/include/libcr_ipc/select.h +++ b/libcr_ipc/include/libcr_ipc/select.h @@ -1,6 +1,6 @@ /* libcr_ipc/select.h - Select between channels * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ @@ -69,106 +69,14 @@ enum _cr_select_class { _CR_SELECT_CLASS_NONBLOCK, }; -static inline enum _cr_select_class _cr_select_getclass(struct cr_select_arg arg) { - switch (arg.op) { - case _CR_SELECT_OP_RECV: - if (arg.ch->waiters.front && arg.ch->waiter_typ == _CR_CHAN_SENDER) - return _CR_SELECT_CLASS_NONBLOCK; - else - return _CR_SELECT_CLASS_BLOCKING; - case _CR_SELECT_OP_SEND: - if (arg.ch->waiters.front && arg.ch->waiter_typ == _CR_CHAN_RECVER) - return _CR_SELECT_CLASS_NONBLOCK; - else - return _CR_SELECT_CLASS_BLOCKING; - case _CR_SELECT_OP_DEFAULT: - return _CR_SELECT_CLASS_DEFAULT; - default: - assert_notreached("invalid arg.op"); - } -} - struct _cr_select_waiters { size_t cnt; struct cr_select_arg *args; struct _cr_chan_waiter *nodes; }; -static void _cr_select_dequeue(void *_waiters, size_t idx) { - struct _cr_select_waiters *waiters = waiters; - for (size_t i = 0; i < waiters->cnt; i++) - _cr_ipc_dll_remove(&(waiters->args[i].ch->waiters), - &(waiters->nodes[i])); - waiters->cnt = idx; -} - -static size_t cr_select_v(size_t arg_cnt, struct cr_select_arg arg_vec[]) { - size_t cnt_blocking = 0; - size_t cnt_nonblock = 0; - size_t cnt_default = 0; - - assert(arg_cnt); - assert(arg_vec); - cr_assert_in_coroutine(); - - for (size_t i = 0; i < arg_cnt; i++) { - switch (_cr_select_getclass(arg_vec[i])) { - case _CR_SELECT_CLASS_BLOCKING: - cnt_blocking++; - break; - case _CR_SELECT_CLASS_NONBLOCK: - cnt_nonblock++; - break; - case _CR_SELECT_CLASS_DEFAULT: - cnt_default++; - break; - } - } - - if (cnt_nonblock) { - size_t choice = rand_uint63n(cnt_nonblock); - for (size_t i = 0, seen = 0; i < arg_cnt; i++) { - if (_cr_select_getclass(arg_vec[i]) == _CR_SELECT_CLASS_NONBLOCK) { - if (seen == choice) { - _cr_chan_xfer(arg_vec[i].op == _CR_SELECT_OP_RECV - ? _CR_CHAN_RECVER - : _CR_CHAN_SENDER, - arg_vec[i].ch, - arg_vec[i].val_ptr, - arg_vec[i].val_siz); - return i; - } - seen++; - } - } - assert_notreached("should have returned from inside for() loop"); - } - - if (cnt_default) { - for (size_t i = 0; i < arg_cnt; i++) - if (_cr_select_getclass(arg_vec[i]) == _CR_SELECT_CLASS_DEFAULT) - return i; - assert_notreached("should have returned from inside for() loop"); - } - - struct _cr_select_waiters waiters = { - .cnt = arg_cnt, - .args = arg_vec, - .nodes = alloca(sizeof(struct _cr_chan_waiter) * arg_cnt), - }; - for (size_t i = 0; i < arg_cnt; i++) { - waiters.nodes[i] = (struct _cr_chan_waiter){ - .cid = cr_getcid(), - .val_ptr = arg_vec[i].val_ptr, - .dequeue = _cr_select_dequeue, - .dequeue_arg1 = &waiters, - .dequeue_arg2 = i, - }; - _cr_ipc_dll_push_to_rear(&arg_vec[i].ch->waiters, &waiters.nodes[i]); - } - cr_pause_and_yield(); - return waiters.cnt; -} +void _cr_select_dequeue(void *_waiters, size_t idx); +size_t cr_select_v(size_t arg_cnt, struct cr_select_arg arg_vec[]); /* cr_select_l(arg1, arg2, arg3, ...) ******************************************/ diff --git a/libcr_ipc/select.c b/libcr_ipc/select.c new file mode 100644 index 0000000..4bd9067 --- /dev/null +++ b/libcr_ipc/select.c @@ -0,0 +1,102 @@ +/* libcr_ipc/select.c - Select between channels + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <libcr_ipc/select.h> + +static inline enum _cr_select_class _cr_select_getclass(struct cr_select_arg arg) { + switch (arg.op) { + case _CR_SELECT_OP_RECV: + if (arg.ch->waiters.front && arg.ch->waiter_typ == _CR_CHAN_SENDER) + return _CR_SELECT_CLASS_NONBLOCK; + else + return _CR_SELECT_CLASS_BLOCKING; + case _CR_SELECT_OP_SEND: + if (arg.ch->waiters.front && arg.ch->waiter_typ == _CR_CHAN_RECVER) + return _CR_SELECT_CLASS_NONBLOCK; + else + return _CR_SELECT_CLASS_BLOCKING; + case _CR_SELECT_OP_DEFAULT: + return _CR_SELECT_CLASS_DEFAULT; + default: + assert_notreached("invalid arg.op"); + } +} + +void _cr_select_dequeue(void *_waiters, size_t idx) { + struct _cr_select_waiters *waiters = _waiters; + for (size_t i = 0; i < waiters->cnt; i++) + _cr_ipc_dll_remove(&(waiters->args[i].ch->waiters), + &(waiters->nodes[i])); + waiters->cnt = idx; +} + +size_t cr_select_v(size_t arg_cnt, struct cr_select_arg arg_vec[]) { + size_t cnt_blocking = 0; + size_t cnt_nonblock = 0; + size_t cnt_default = 0; + + assert(arg_cnt); + assert(arg_vec); + cr_assert_in_coroutine(); + + for (size_t i = 0; i < arg_cnt; i++) { + switch (_cr_select_getclass(arg_vec[i])) { + case _CR_SELECT_CLASS_BLOCKING: + cnt_blocking++; + break; + case _CR_SELECT_CLASS_NONBLOCK: + cnt_nonblock++; + break; + case _CR_SELECT_CLASS_DEFAULT: + cnt_default++; + break; + } + } + + if (cnt_nonblock) { + size_t choice = rand_uint63n(cnt_nonblock); + for (size_t i = 0, seen = 0; i < arg_cnt; i++) { + if (_cr_select_getclass(arg_vec[i]) == _CR_SELECT_CLASS_NONBLOCK) { + if (seen == choice) { + _cr_chan_xfer(arg_vec[i].op == _CR_SELECT_OP_RECV + ? _CR_CHAN_RECVER + : _CR_CHAN_SENDER, + arg_vec[i].ch, + arg_vec[i].val_ptr, + arg_vec[i].val_siz); + return i; + } + seen++; + } + } + assert_notreached("should have returned from inside for() loop"); + } + + if (cnt_default) { + for (size_t i = 0; i < arg_cnt; i++) + if (_cr_select_getclass(arg_vec[i]) == _CR_SELECT_CLASS_DEFAULT) + return i; + assert_notreached("should have returned from inside for() loop"); + } + + struct _cr_select_waiters waiters = { + .cnt = arg_cnt, + .args = arg_vec, + .nodes = alloca(sizeof(struct _cr_chan_waiter) * arg_cnt), + }; + for (size_t i = 0; i < arg_cnt; i++) { + waiters.nodes[i] = (struct _cr_chan_waiter){ + .cid = cr_getcid(), + .val_ptr = arg_vec[i].val_ptr, + .dequeue = _cr_select_dequeue, + .dequeue_arg1 = &waiters, + .dequeue_arg2 = i, + }; + _cr_ipc_dll_push_to_rear(&arg_vec[i].ch->waiters, &waiters.nodes[i]); + } + cr_pause_and_yield(); + return waiters.cnt; +} |