/* libcr_ipc/chan.c - Simple channels for libcr * * Copyright (C) 2024-2025 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later */ #include 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(); } }