summaryrefslogtreecommitdiff
path: root/libcr_ipc/include
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-07 01:38:42 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-07 19:32:58 -0600
commit062e063f76c5937be4dc8465f6471ff9b5eb7be9 (patch)
tree3eb702a06625ef1f6be0648f7fec311b628808e9 /libcr_ipc/include
parent4d5a8b2f99be5e04954c5067080d1725af8c0ae7 (diff)
libcr_ipc: Add rwmutex
Diffstat (limited to 'libcr_ipc/include')
-rw-r--r--libcr_ipc/include/libcr_ipc/rwmutex.h77
1 files changed, 77 insertions, 0 deletions
diff --git a/libcr_ipc/include/libcr_ipc/rwmutex.h b/libcr_ipc/include/libcr_ipc/rwmutex.h
new file mode 100644
index 0000000..924acce
--- /dev/null
+++ b/libcr_ipc/include/libcr_ipc/rwmutex.h
@@ -0,0 +1,77 @@
+/* libcr_ipc/rwmutex.h - Simple read/write mutexes for libcr
+ *
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _LIBCR_IPC_RWMUTEX_H_
+#define _LIBCR_IPC_RWMUTEX_H_
+
+#include <stdbool.h>
+
+#include <libmisc/private.h>
+
+#include <libcr_ipc/_linkedlist_pub.h>
+
+/**
+ * A cr_rwmutex_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_RWMUTEX_H);
+ unsigned nreaders;
+ bool locked;
+ bool unpausing;
+ _cr_ipc_sll_root waiters;
+ END_PRIVATE(LIBCR_IPC_RWMUTEX_H);
+} cr_rwmutex_t;
+
+/**
+ * Lock the mutex for writing. Blocks if it is already locked.
+ *
+ * @runs_in coroutine
+ * @cr_pauses maybe
+ * @cr_yields maybe
+ */
+void cr_rwmutex_lock(cr_rwmutex_t *mu);
+
+/**
+ * Undo a single cr_rwmutex_lock() call. Unblocks either a single
+ * coroutine that is blocked on cr_rwmutex_lock() or arbitrarily many
+ * coroutines that are blocked on cr_rwmutex_rlock().
+ *
+ * @runs_in coroutine
+ * @cr_pauses never
+ * @cr_yields never
+ */
+void cr_rwmutex_unlock(cr_rwmutex_t *mu);
+
+/**
+ * Lock the mutex for reading. Blocks if it is already locked for
+ * writing.
+ *
+ * @runs_in coroutine
+ * @cr_pauses maybe
+ * @cr_yields maybe
+ */
+void cr_rwmutex_rlock(cr_rwmutex_t *mu);
+
+/**
+ * Undo a single cr_rwmutext_rock() call. If the reader count is
+ * reduced to zero, unblocks a single coroutine that is blocked on
+ * cr_rwmutex_lock().
+ *
+ * @runs_in coroutine
+ * @cr_pauses never
+ * @cr_yields never
+ */
+void cr_rwmutex_runlock(cr_rwmutex_t *mu);
+
+#endif /* _LIBCR_IPC_RWMUTEX_H_ */