diff options
Diffstat (limited to 'libcr_ipc/sema.c')
-rw-r--r-- | libcr_ipc/sema.c | 81 |
1 files changed, 0 insertions, 81 deletions
diff --git a/libcr_ipc/sema.c b/libcr_ipc/sema.c deleted file mode 100644 index a3efb57..0000000 --- a/libcr_ipc/sema.c +++ /dev/null @@ -1,81 +0,0 @@ -/* libcr_ipc/sema.c - Simple semaphores for libcr (implementation file) - * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-Licence-Identifier: AGPL-3.0-or-later - */ - -#include <assert.h> - -#include <libcr_ipc/sema.h> - -/** Drain the sema->{head,tail} list. Returns true if cr_getcid() was drained. */ -static inline bool drain(cr_sema_t *sema) { - assert(!sema->locked); - cid_t self = cr_getcid(); - - enum drain_result { - DRAINING, - DRAINED_SELF, /* stopped because drained `self` */ - DRAINED_ALL, /* stopped because sema->head == NULL */ - DRAINED_SOME, /* stopped because sema->cnt == 0 */ - } state = DRAINING; - do { - sema->locked = true; - while (state == DRAINING) { - if (!sema->head) { - state = DRAINED_ALL; - } else if (!sema->cnt) { - state = DRAINED_SOME; - } else { - sema->cnt--; - cid_t cid = sema->head->val; - if (cid == self) - state = DRAINED_SELF; - else - cr_unpause(sema->head->val); - sema->head = sema->head->next; - if (!sema->head) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" - sema->tail = &sema->head; -#pragma GCC diagnostic pop - } - } - sema->locked = false; - /* If there are still coroutines in sema->head, check - * that sema->cnt wasn't incremented between `if - * (!sema->cnt)` and `sema->locked = false`. */ - } while (state == DRAINED_SOME && sema->cnt); - /* If state == DRAINED_SELF, then we better have been the last - * item in the list! */ - assert(state != DRAINED_SELF || !sema->head); - return state == DRAINED_SELF; -} - -void cr_sema_signal(cr_sema_t *sema) { - sema->cnt++; - if (!sema->locked) - drain(sema); -} - -void cr_sema_wait(cr_sema_t *sema) { - struct _cr_ipc_cid_list self = { - .val = cr_getcid(), - .next = NULL, - }; - - sema->locked = true; - if (!sema->tail) - sema->head = &self; - else - *(sema->tail) = &self; - sema->tail = &(self.next); - sema->locked = false; - - if (drain(sema)) - /* DRAINED_SELF: (1) No need to pause+yield, (2) we - * better have been the last item in the list! */ - assert(!self.next); - else - cr_pause_and_yield(); -} |