summaryrefslogtreecommitdiff
path: root/libcr/coroutine.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcr/coroutine.c')
-rw-r--r--libcr/coroutine.c87
1 files changed, 47 insertions, 40 deletions
diff --git a/libcr/coroutine.c b/libcr/coroutine.c
index 37a5b1f..568de4e 100644
--- a/libcr/coroutine.c
+++ b/libcr/coroutine.c
@@ -130,20 +130,48 @@
#if 0
{ /* bracket to get Emacs indentation to work how I want */
#endif
-#if __arm__ /*======================================================*/
- /* Assume bare metal ARMv6-M. */
- #define CR_PLAT_STACK_GROWS_DOWNWARD 1
-
- /* Wrappers for setjmp()/longjmp() that do *not* save the
- * interrupt mask.
- *
- * newlib does not have sigsetjmp()/sigsetlongjmp(), but
+/*====================================================================
+ * 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. */
+ #define cr_plat_setjmp(env) sigsetjmp(env, 0)
+ #define cr_plat_longjmp(env, val) siglongjmp(env, val)
+#elif __NEWLIB__
+ /* newlib does not have sigsetjmp()/sigsetlongjmp(), but
* setjmp()/longjmp() do not save the interrupt mask, * so we
* can use them directly. */
#define cr_plat_setjmp(env) setjmp(env)
#define cr_plat_longjmp(env, val) longjmp(env, val)
+#else
+ #error unsupported platform (not __unix__, not __NEWLIB__)
+#endif
+
+/*====================================================================
+ * Interrupt management routines. */
+#if __unix__
+ #include <signal.h> /* for sig*, SIG_* */
+ #include <unistd.h> /* for pause() */
+ static inline void cr_plat_wait_for_interrupt(void) {
+ pause();
+ }
+ void _cr_plat_disable_interrupts(void) {
+ sigset_t all;
+ sigfillset(&all);
+ sigprocmask(SIG_BLOCK, &all, NULL);
+ }
+ void _cr_plat_enable_interrupts(void) {
+ sigset_t all;
+ sigfillset(&all);
+ sigprocmask(SIG_UNBLOCK, &all, NULL);
+ }
+#elif __arm__
+ /* Assume bare-metal if !__unix__. */
static ALWAYS_INLINE void cr_plat_wait_for_interrupt(void) {
asm volatile ("wfi":::"memory");
}
@@ -153,6 +181,14 @@
void _cr_plat_enable_interrupts(void) {
asm volatile ("cpsie i":::"memory");
}
+#else
+ #error unsupported platform (not __unix__, not bare-metal __arm__)
+#endif
+
+/*====================================================================
+ * Stack management routines. */
+#if __arm__
+ #define CR_PLAT_STACK_GROWS_DOWNWARD 1
#if CONFIG_COROUTINE_MEASURE_STACK
static ALWAYS_INLINE uintptr_t cr_plat_get_sp(void) {
@@ -183,37 +219,9 @@
: "r0"
);
}
-
-#elif __x86_64__ /*=================================================*/
- /* Assume POSIX. */
- #include <signal.h> /* for sig*, SIG_* */
- #include <unistd.h> /* for pause() */
-
+#elif __x86_64__
#define CR_PLAT_STACK_GROWS_DOWNWARD 1
- /* Wrappers for setjmp()/longjmp() that do *not* save the
- * interrupt mask.
- *
- * POSIX leaves it implementation-defined whether they 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)
-
- static inline void cr_plat_wait_for_interrupt(void) {
- pause();
- }
- void _cr_plat_disable_interrupts(void) {
- sigset_t all;
- sigfillset(&all);
- sigprocmask(SIG_BLOCK, &all, NULL);
- }
- void _cr_plat_enable_interrupts(void) {
- sigset_t all;
- sigfillset(&all);
- sigprocmask(SIG_UNBLOCK, &all, NULL);
- }
-
#if CONFIG_COROUTINE_MEASURE_STACK
static ALWAYS_INLINE uintptr_t cr_plat_get_sp(void) {
uintptr_t sp;
@@ -238,11 +246,10 @@
: "rdi"
);
}
-
#else
- #error unsupported platform
-
+ #error unsupported platform (not __arm__, not __x86__)
#endif
+
#if 0
}
#endif