summaryrefslogtreecommitdiff
path: root/libcr_ipc/coroutine_sema.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-27 17:25:36 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-27 17:25:36 -0600
commite5e15c04bc58c34906e6d7cfcbad68d1a5617563 (patch)
tree580f5fb0fafc7e974c969fc8aae229205c836195 /libcr_ipc/coroutine_sema.c
parent71e1a86a033c380f85dd300d788af63bfef25bab (diff)
wip
Diffstat (limited to 'libcr_ipc/coroutine_sema.c')
-rw-r--r--libcr_ipc/coroutine_sema.c95
1 files changed, 0 insertions, 95 deletions
diff --git a/libcr_ipc/coroutine_sema.c b/libcr_ipc/coroutine_sema.c
deleted file mode 100644
index a8b5ec4..0000000
--- a/libcr_ipc/coroutine_sema.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/* coroutine_sema.h - Simple semaphores for coroutine.{h,c}
- *
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-Licence-Identifier: AGPL-3.0-or-later
- */
-
-#include <assert.h>
-
-#include "coroutine_sema.h"
-
-struct cid_list {
- cid_t val;
- struct cid_list *next;
-};
-
-/* head->next->next->tail */
-
-struct _cr_sema {
- int cnt;
-
- struct cid_list *head, **tail;
- /* locked indicates that a call from within a coroutine is is
- * messing with ->{head,tail}, so a signal handler can't read
- * it. */
- bool locked;
-};
-
-/** Drain the sema->{head,tail} list. Returns true if cr_getcid() was drained. */
-static inline bool drain(volatile 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)
- sema->tail = &sema->head;
- }
- }
- 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 && 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(volatile cr_sema_t *sema) {
- sema->cnt++;
- if (!sema->locked)
- drain();
-}
-
-void cr_sema_wait(volatile cr_sema_t *sema) {
- struct 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())
- /* 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();
-}