summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-29 12:14:45 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-29 12:24:10 -0600
commitcd0b080d638005bff762f1f8cae9a6c76648265b (patch)
treef9b76002924a16afae66df3815d521f0e7b25efb
parent6940b244de7c5048c55fc57ada93501c1be5ab20 (diff)
tidy, s/sighandler/intrhandler/
-rw-r--r--libcr/coroutine.c20
-rw-r--r--libcr/include/libcr/coroutine.h4
-rw-r--r--libcr_ipc/include/libcr_ipc/sema.h49
-rw-r--r--libnetio/netio_posix.c4
4 files changed, 50 insertions, 27 deletions
diff --git a/libcr/coroutine.c b/libcr/coroutine.c
index 25e3e4f..74c74d8 100644
--- a/libcr/coroutine.c
+++ b/libcr/coroutine.c
@@ -131,7 +131,7 @@ enum coroutine_state {
struct coroutine {
volatile enum coroutine_state state;
- volatile bool sig_unpause;
+ volatile bool intr_unpause;
jmp_buf env;
size_t stack_size;
void *stack;
@@ -444,11 +444,11 @@ void cr_yield(void) {
void cr_pause_and_yield(void) {
assert_cid_state(coroutine_running, == CR_RUNNING);
- if (coroutine_table[coroutine_running-1].sig_unpause)
+ if (coroutine_table[coroutine_running-1].intr_unpause)
_cr_transition(CR_RUNNABLE);
else
_cr_transition(CR_PAUSED);
- coroutine_table[coroutine_running-1].sig_unpause = false;
+ coroutine_table[coroutine_running-1].intr_unpause = false;
}
void cr_exit(void) {
@@ -463,23 +463,23 @@ void cr_unpause(cid_t cid) {
assert_cid_state(cid, == CR_PAUSED);
debugf("cr_unpause(%zu)\n", cid);
- coroutine_table[cid-1].sig_unpause = false;
- coroutine_table[cid-1].state = CR_RUNNABLE;
+ coroutine_table[cid-1].intr_unpause = false;
+ coroutine_table[cid-1].state = CR_RUNNABLE;
}
-void cr_unpause_from_sighandler(cid_t cid) {
+void cr_unpause_from_intrhandler(cid_t cid) {
assert_cid(cid);
- debugf("cr_unpause_from_sighandler(%zu)\n", cid);
+ debugf("cr_unpause_from_intrhandler(%zu)\n", cid);
switch (coroutine_table[cid-1].state) {
case CR_RUNNING:
debugf("... raced, deferring unpause\n");
- coroutine_table[cid-1].sig_unpause = true;
+ coroutine_table[cid-1].intr_unpause = true;
break;
case CR_PAUSED:
debugf("... actual unpause\n");
- coroutine_table[cid-1].sig_unpause = false;
- coroutine_table[cid-1].state = CR_RUNNABLE;
+ coroutine_table[cid-1].intr_unpause = false;
+ coroutine_table[cid-1].state = CR_RUNNABLE;
break;
default:
assertf(false, "cid=%zu state=%s\n",
diff --git a/libcr/include/libcr/coroutine.h b/libcr/include/libcr/coroutine.h
index faaf6c3..f580b09 100644
--- a/libcr/include/libcr/coroutine.h
+++ b/libcr/include/libcr/coroutine.h
@@ -113,8 +113,8 @@ void cr_yield(void);
void cr_pause_and_yield(void);
/** cr_unpause() marks a coroutine as runnable that has previously marked itself as non-runnable with cr_pause_and_yield(). */
void cr_unpause(cid_t);
-/** cr_unpause_from_sighandler() is like cr_unpause(), but safe to call from a signal handler that might race with the coroutine actually pausing itself. */
-void cr_unpause_from_sighandler(cid_t);
+/** cr_unpause_from_intrhandler() is like cr_unpause(), but safe to call from a interrupt handler that might race with the coroutine actually pausing itself. */
+void cr_unpause_from_intrhandler(cid_t);
/** cr_end() is a counterpart to cr_begin(), but is really just cr_exit(). */
#define cr_end cr_exit
diff --git a/libcr_ipc/include/libcr_ipc/sema.h b/libcr_ipc/include/libcr_ipc/sema.h
index 257c8d5..9fe3223 100644
--- a/libcr_ipc/include/libcr_ipc/sema.h
+++ b/libcr_ipc/include/libcr_ipc/sema.h
@@ -10,6 +10,10 @@
#include <stdbool.h>
#include <libcr_ipc/_common.h>
+/* Most of the complexity in this file is so that
+ * cr_sema_signal_from_intrhandler() can actually be safe when called
+ * in an interrupt handler. */
+
/**
* A cr_sema_t is a fair unbounded[1] counting semaphore.
*
@@ -20,18 +24,20 @@ typedef struct {
struct _cr_ipc_cid_fifo waiters;
/* locked indicates that a call from within a coroutine is is
- * messing with ->waiters, so a signal handler can't read it.
- * Use `asm volatile ("":::"memory")` after setting =true and
- * before setting =false to make sure the compiler doesn't
- * re-order writes! */
+ * messing with ->waiters, so an interrupt handler can't read
+ * it. Use `asm volatile ("":::"memory")` after setting =true
+ * and before setting =false to make sure the compiler doesn't
+ * re-order writes to ->waiters to be outside of the critical
+ * section! */
volatile bool locked;
} cr_sema_t;
/**
* Drain a maximum of sema->cnt coroutines from the sema->waiters
- * list. Returns true if cr_getcid() was drained.
+ * list. Returns true if cr_getcid() was drained and we're not in an
+ * interrupt handler.
*/
-static inline bool _cr_sema_drain(cr_sema_t *sema) {
+static inline bool _cr_sema_drain(cr_sema_t *sema, bool in_intrhandler) {
assert(!sema->locked);
cid_t self = cr_getcid();
@@ -52,10 +58,14 @@ static inline bool _cr_sema_drain(cr_sema_t *sema) {
} else {
sema->cnt--;
cid_t cid = _cr_ipc_cid_fifo_pop(&sema->waiters);
- if (cid == self)
- state = DRAINED_SELF;
- else
- cr_unpause_from_sighandler(cid);
+ if (in_intrhandler)
+ cr_unpause_from_intrhandler(cid);
+ else {
+ if (cid == self)
+ state = DRAINED_SELF;
+ else
+ cr_unpause(cid);
+ }
}
}
asm volatile ("":::"memory");
@@ -75,12 +85,25 @@ static inline bool _cr_sema_drain(cr_sema_t *sema) {
*
* @blocks never
* @yields never
- * @run_in anywhere (coroutine, sighandler)
+ * @run_in coroutine
*/
static inline void cr_sema_signal(cr_sema_t *sema) {
sema->cnt++;
if (!sema->locked)
- _cr_sema_drain(sema);
+ assert(!_cr_sema_drain(sema, false));
+}
+
+/**
+ * Like cr_sema_signal(), but safe to call from an interrupt handler.
+ *
+ * @blocks never
+ * @yields never
+ * @run_in intrhandler
+ */
+static inline void cr_sema_signal_from_intrhandler(cr_sema_t *sema) {
+ sema->cnt++;
+ if (!sema->locked)
+ assert(!_cr_sema_drain(sema, true));
}
/**
@@ -99,7 +122,7 @@ static inline void cr_sema_wait(cr_sema_t *sema) {
asm volatile ("":::"memory");
sema->locked = false;
- if (_cr_sema_drain(sema))
+ if (_cr_sema_drain(sema, false))
/* DRAINED_SELF: (1) No need to pause+yield, (2) we
* better have been the last item in the list! */
assert(!self.next);
diff --git a/libnetio/netio_posix.c b/libnetio/netio_posix.c
index 34f415d..54df412 100644
--- a/libnetio/netio_posix.c
+++ b/libnetio/netio_posix.c
@@ -40,7 +40,7 @@ struct netio_socket {
static struct netio_socket socket_table[CONFIG_NETIO_NUM_PORTS] = {0};
static void handle_sig_io(int sig __attribute__ ((unused)), siginfo_t *info, void *ucontext __attribute__ ((unused))) {
- cr_unpause_from_sighandler((cid_t)info->si_value.sival_int);
+ cr_unpause_from_intrhandler((cid_t)info->si_value.sival_int);
}
#if CONFIG_NETIO_ISLINUX
@@ -51,7 +51,7 @@ static void handle_sig_accept(int sig __attribute__ ((unused)), siginfo_t *info,
sock = &socket_table[i];
if (!sock)
return;
- cr_sema_signal(&sock->accept_waiters);
+ cr_sema_signal_from_intrhandler(&sock->accept_waiters);
}
#endif