From 4d5a8b2f99be5e04954c5067080d1725af8c0ae7 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Mon, 7 Apr 2025 00:09:00 -0600 Subject: libcr_ipc: Pull as much as possible from public .h to .c files --- libcr_ipc/sema.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 libcr_ipc/sema.c (limited to 'libcr_ipc/sema.c') diff --git a/libcr_ipc/sema.c b/libcr_ipc/sema.c new file mode 100644 index 0000000..85add6c --- /dev/null +++ b/libcr_ipc/sema.c @@ -0,0 +1,66 @@ +/* libcr_ipc/sema.c - Simple semaphores for libcr + * + * Copyright (C) 2024-2025 Luke T. Shumaker + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include /* for cid_t, cr_* */ + +#define IMPLEMENTATION_FOR_LIBCR_IPC_SEMA_H YES +#include + +#include "_linkedlist.h" + +struct cr_sema_waiter { + cr_ipc_sll_node; + cid_t cid; +}; + +void cr_sema_signal(cr_sema_t *sema) { + assert(sema); + cr_assert_in_coroutine(); + + bool saved = cr_save_and_disable_interrupts(); + sema->cnt++; + if (sema->waiters.front && !sema->unpausing) { + cr_unpause( + cr_ipc_sll_node_cast(struct cr_sema_waiter, sema->waiters.front)->cid); + sema->unpausing = true; + } + cr_restore_interrupts(saved); +} + +void cr_sema_signal_from_intrhandler(cr_sema_t *sema) { + assert(sema); + cr_assert_in_intrhandler(); + + sema->cnt++; + if (sema->waiters.front && !sema->unpausing) { + cr_unpause_from_intrhandler( + cr_ipc_sll_node_cast(struct cr_sema_waiter, sema->waiters.front)->cid); + sema->unpausing = true; + } +} + +void cr_sema_wait(cr_sema_t *sema) { + assert(sema); + cr_assert_in_coroutine(); + + bool saved = cr_save_and_disable_interrupts(); + + struct cr_sema_waiter self = { + .cid = cr_getcid(), + }; + cr_ipc_sll_push_to_rear(&sema->waiters, &self); + if (sema->waiters.front != &self.cr_ipc_sll_node || !sema->cnt) + cr_pause_and_yield(); + assert(sema->waiters.front == &self.cr_ipc_sll_node && sema->cnt); + cr_ipc_sll_pop_from_front(&sema->waiters); + sema->cnt--; + if (sema->cnt && sema->waiters.front) + cr_unpause( + cr_ipc_sll_node_cast(struct cr_sema_waiter, sema->waiters.front)->cid); + else + sema->unpausing = false; + cr_restore_interrupts(saved); +} -- cgit v1.2.3-2-g168b