diff options
Diffstat (limited to 'libcr_ipc/mutex.c')
-rw-r--r-- | libcr_ipc/mutex.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/libcr_ipc/mutex.c b/libcr_ipc/mutex.c new file mode 100644 index 0000000..1b4e626 --- /dev/null +++ b/libcr_ipc/mutex.c @@ -0,0 +1,44 @@ +/* libcr_ipc/mutex.c - Simple mutexes for libcr + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <libcr/coroutine.h> /* for cid_t, cr_* */ +#include <libmisc/assert.h> + +#define IMPLEMENTATION_FOR_LIBCR_IPC_MUTEX_H YES +#include <libcr_ipc/mutex.h> + +struct cr_mutex_waiter { + cid_t cid; +}; +SLIST_DECLARE_NODE(_cr_mutex_waiter_list, struct cr_mutex_waiter); + +void cr_mutex_lock(cr_mutex_t *mu) { + assert(mu); + cr_assert_in_coroutine(); + + if (!mu->locked) /* non-blocking fast-path */ + mu->locked = true; + else { /* blocking slow-path */ + struct _cr_mutex_waiter_list_node self = { .val = { + .cid = cr_getcid(), + }}; + slist_push_to_rear(&mu->waiters, &self); + cr_pause_and_yield(); + } + assert(mu->locked); +} + +void cr_mutex_unlock(cr_mutex_t *mu) { + assert(mu); + cr_assert_in_coroutine(); + + assert(mu->locked); + if (mu->waiters.front) { + cr_unpause(mu->waiters.front->val.cid); + slist_pop_from_front(&mu->waiters); + } else + mu->locked = false; +} |