summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-17 21:58:14 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-19 20:24:20 -0700
commit58986ed5316acc6d6077541b7b6e754390069d73 (patch)
tree939c68703a9bdd5b165ab8708dd4fe6fafae6196
parent292e62b7fd2f6d8018c5a6d40f6e0cdace4494ae (diff)
libcr: Fixups
-rw-r--r--libcr/coroutine.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/libcr/coroutine.c b/libcr/coroutine.c
index a468df0..252eca2 100644
--- a/libcr/coroutine.c
+++ b/libcr/coroutine.c
@@ -51,8 +51,9 @@
* - It has a small bit of platform-specific code in the "platform
* support" section. Other than this, it should be portable to
* other platforms CPUs. It currently contains implementations for
- * __x86_64__ (assumes POSIX) and __arm__ (assumes bare-metal), and
- * should be fairly easy to add implementations for other platforms.
+ * __unix__ and __ARM_EABI__ "operating systems" on __x86_64__ and
+ * __ARM_ARCH_6M__ CPUs, and should be fairly easy to add
+ * implementations for other platforms.
*
* - It uses setjmp()/longjmp() in "unsafe" ways. POSIX-2017
* longjmp(3p) says
@@ -136,10 +137,10 @@
* Wrappers for setjmp()/longjmp() that do *not* save the
* interrupt mask. */
#if __unix__
- /* On a *NIX OS, we use signals as interrupts. POSIX leaves
- * it implementation-defined whether setjmp()/longjmp() save
- * the signal mask; while glibc does not save it, let's not
- * rely on that. */
+ /* On __unix__, we use POSIX real-time signals as interrupts.
+ * POSIX leaves it implementation-defined whether
+ * setjmp()/longjmp() save the signal mask; while glibc does
+ * not save it, let's not rely on that. */
#define cr_plat_setjmp(env) sigsetjmp(env, 0)
#define cr_plat_longjmp(env, val) siglongjmp(env, val)
#elif __NEWLIB__
@@ -159,10 +160,12 @@
/* For a signal to be *in* the mask means that the signal is
* *blocked*. */
+
static inline void cr_plat_wait_for_interrupt(void) {
sigset_t set;
sigemptyset(&set);
sigsuspend(&set);
+
sigfillset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
}
@@ -177,8 +180,7 @@
sigemptyset(&zero);
sigprocmask(SIG_SETMASK, &zero, NULL);
}
-#elif __arm__
- /* Assume bare-metal if !__unix__. */
+#elif __ARM_ARCH_6M__ && __ARM_EABI__
static ALWAYS_INLINE void cr_plat_wait_for_interrupt(void) {
asm volatile ("wfi":::"memory");
}
@@ -186,20 +188,20 @@
uint32_t primask;
asm volatile ("mrs %0, PRIMASK\n"
"cpsid i"
- : /* %0 */"=r"(primask)
+ : /* %0 */"=l"(primask)
);
return primask == 0;
}
void _cr_plat_enable_interrupts(void) {
- asm volatile ("cpsie i":::"memory");
+ asm volatile ("cpsie i");
}
#else
- #error unsupported platform (not __unix__, not bare-metal __arm__)
+ #error unsupported platform (not __unix__, not __ARM_ARCH_6M__ && __ARM_EABI__)
#endif
/*====================================================================
* Stack management routines. */
-#if __arm__
+#if __ARM_ARCH_6M__
#define CR_PLAT_STACK_GROWS_DOWNWARD 1
#if CONFIG_COROUTINE_MEASURE_STACK
@@ -225,9 +227,9 @@
"mov sp, r0" /* ] */
:
: /* %0 */"m"(saved_sp),
- /* %1 */"r"(stack),
- /* %2 */"r"(fn),
- /* %3 */"r"(args)
+ /* %1 */"l"(stack),
+ /* %2 */"l"(fn),
+ /* %3 */"l"(args)
: "r0"
);
}
@@ -259,7 +261,7 @@
);
}
#else
- #error unsupported platform (not __arm__, not __x86__)
+ #error unsupported CPU (not __ARM_ARCH_6M__, not __x86_64__)
#endif
#if 0
@@ -587,8 +589,7 @@ __attribute__ ((noreturn)) void cr_exit(void) {
cr_plat_longjmp(coroutine_main_env, 1); /* jump to point=b */
}
-void cr_unpause_from_intrhandler(cid_t cid) {
- debugf("cr_unpause(%zu)\n", cid);
+static void _cr_unpause(cid_t cid) {
assert_cid_state(cid, state == CR_PAUSED);
coroutine_table[cid-1].state = CR_RUNNABLE;
@@ -596,11 +597,19 @@ void cr_unpause_from_intrhandler(cid_t cid) {
}
void cr_unpause(cid_t cid) {
+ debugf("cr_unpause(%zu)\n", cid);
+ assert_cid_state(coroutine_running, state == CR_RUNNING);
bool saved = cr_save_and_disable_interrupts();
- cr_unpause_from_intrhandler(cid);
+ _cr_unpause(cid);
cr_restore_interrupts(saved);
}
+void cr_unpause_from_intrhandler(cid_t cid) {
+ debugf("cr_unpause_from_intrhandler(%zu)\n", cid);
+
+ _cr_unpause(cid);
+}
+
cid_t cr_getcid(void) {
assert_cid_state(coroutine_running, state == CR_RUNNING);
return coroutine_running;