diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-04-07 14:28:17 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-04-07 20:28:56 -0600 |
commit | a1a20d71f6d9f6b26893b0f2d641da47cd59e74e (patch) | |
tree | d6a692b3858f2c222dd8eeed371bf7ed4ec27db7 /libcr_ipc/include | |
parent | 4d5a8b2f99be5e04954c5067080d1725af8c0ae7 (diff) |
libcr_ipc: Add waitgrouplukeshu/waitgroup
Diffstat (limited to 'libcr_ipc/include')
-rw-r--r-- | libcr_ipc/include/libcr_ipc/waitgroup.h | 65 |
1 files changed, 65 insertions, 0 deletions
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 <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIBCR_IPC_WAITGROUP_H_ +#define _LIBCR_IPC_WAITGROUP_H_ + +#include <stdbool.h> + +#include <libmisc/private.h> + +#include <libcr_ipc/_linkedlist_pub.h> + +/** + * 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_ */ |