From a1a20d71f6d9f6b26893b0f2d641da47cd59e74e Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Mon, 7 Apr 2025 14:28:17 -0600 Subject: libcr_ipc: Add waitgroup --- libcr_ipc/include/libcr_ipc/waitgroup.h | 65 +++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 libcr_ipc/include/libcr_ipc/waitgroup.h (limited to 'libcr_ipc/include') diff --git a/libcr_ipc/include/libcr_ipc/waitgroup.h b/libcr_ipc/include/libcr_ipc/waitgroup.h new file mode 100644 index 0000000..32369cf --- /dev/null +++ b/libcr_ipc/include/libcr_ipc/waitgroup.h @@ -0,0 +1,65 @@ +/* libcr_ipc/waitgroup.h - Go-like WaitGroups for libcr + * + * Copyright (C) 2025 Luke T. Shumaker + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIBCR_IPC_WAITGROUP_H_ +#define _LIBCR_IPC_WAITGROUP_H_ + +#include + +#include + +#include + +/** + * A cr_waitgroup_t is a fair read/write mutex. + * + * A waiting writer blocks any new readers; this ensures that the + * writer is able to eventually get the lock. + * + * None of the methods have `_from_intrhandler` variants because (1) + * an interrupt handler can't block, so it shouldn't ever lock a mutex + * because that can block; and (2) if it can't lock a mutex in the + * first place, then it has no business unlocking one. + */ +typedef struct { + BEGIN_PRIVATE(LIBCR_IPC_WAITGROUP_H); + int count; + bool unpausing; + _cr_ipc_sll_root waiters; + END_PRIVATE(LIBCR_IPC_WAITGROUP_H); +} cr_waitgroup_t; + +/** + * Add delta (which may be negative) to the counter. If the counter + * becomes zero, all cr_waitgroup_wait() are unblocked. The counter + * must not become negative. + * + * @runs_in coroutine + * @cr_pauses never + * @cr_yields never + */ +void cr_waitgroup_add(cr_waitgroup_t *wg, int delta); + +/** + * Like cr_waitgroup_add(), but for use from an interrupt handler. + * + * @runs_in intrhandler + */ +void cr_waitgroup_add_from_intrhandler(cr_waitgroup_t *wg, int delta); + +#define cr_waitgroup_done(WG) cr_waitgroup_add(WG, -1) +#define cr_waitgroup_done_from_intrhandler(WG) cr_waitgroup_add_from_intrhandler(WG, -1) + +/** + * Wait until the counter becomes zero. If the counter is already zero, returns immediately. + * + * @runs_in coroutine + * @cr_pauses maybe + * @cr_yields maybe + */ +void cr_waitgroup_wait(cr_waitgroup_t *wg); + +#endif /* _LIBCR_IPC_WAITGROUP_H_ */ -- cgit v1.2.3-2-g168b