// threads.h — C11 threading API. Single-core IIgs / bare-metal: every // thread function fails with `thrd_error`. Mutexes / cond-vars compile // but produce no synchronization — callers running on a single core // don't need any. This header is here so portable C11 code that // `#include ` and uses `thrd_t` etc. compiles. #ifndef _THREADS_H #define _THREADS_H #include enum { thrd_success = 0, thrd_busy = 1, thrd_error = 2, thrd_nomem = 3, thrd_timedout = 4 }; enum { mtx_plain = 0, mtx_recursive = 1, mtx_timed = 2 }; #define ONCE_FLAG_INIT 0 #define TSS_DTOR_ITERATIONS 1 typedef int thrd_t; typedef int (*thrd_start_t)(void *); typedef struct { int _x; } mtx_t; typedef struct { int _x; } cnd_t; typedef int once_flag; typedef unsigned short tss_t; typedef void (*tss_dtor_t)(void *); // All thread create/join calls fail — no scheduler. static inline int thrd_create(thrd_t *t, thrd_start_t f, void *a) { (void)t; (void)f; (void)a; return thrd_error; } static inline thrd_t thrd_current(void) { return 0; } static inline int thrd_equal(thrd_t a, thrd_t b) { return a == b; } static inline void thrd_exit(int v) { (void)v; for (;;) {} } static inline int thrd_join(thrd_t t, int *res) { (void)t; (void)res; return thrd_error; } static inline int thrd_detach(thrd_t t) { (void)t; return thrd_error; } static inline int thrd_sleep(const struct timespec *d, struct timespec *r) { (void)d; (void)r; return -1; } static inline void thrd_yield(void) { } // Mutex / cond — no-ops on a uniprocessor. static inline int mtx_init(mtx_t *m, int t) { (void)m; (void)t; return thrd_success; } static inline int mtx_lock(mtx_t *m) { (void)m; return thrd_success; } static inline int mtx_trylock(mtx_t *m) { (void)m; return thrd_success; } static inline int mtx_timedlock(mtx_t *m, const struct timespec *t) { (void)m; (void)t; return thrd_success; } static inline int mtx_unlock(mtx_t *m) { (void)m; return thrd_success; } static inline void mtx_destroy(mtx_t *m) { (void)m; } static inline int cnd_init(cnd_t *c) { (void)c; return thrd_success; } static inline int cnd_signal(cnd_t *c) { (void)c; return thrd_success; } static inline int cnd_broadcast(cnd_t *c) { (void)c; return thrd_success; } static inline int cnd_wait(cnd_t *c, mtx_t *m) { (void)c; (void)m; return thrd_error; } static inline int cnd_timedwait(cnd_t *c, mtx_t *m, const struct timespec *t) { (void)c; (void)m; (void)t; return thrd_timedout; } static inline void cnd_destroy(cnd_t *c) { (void)c; } // call_once — straightforward on a single-core target. static inline void call_once(once_flag *f, void (*fn)(void)) { if (!*f) { *f = 1; fn(); } } // Thread-specific storage: no other threads, so it's just a pointer. // At most 8 keys. extern void *__tss_slots[8]; extern int __tss_next; static inline int tss_create(tss_t *k, tss_dtor_t d) { (void)d; if (__tss_next >= 8) return thrd_error; *k = (tss_t)__tss_next++; return thrd_success; } static inline void *tss_get(tss_t k) { return __tss_slots[k]; } static inline int tss_set(tss_t k, void *v) { __tss_slots[k] = v; return thrd_success; } static inline void tss_delete(tss_t k) { (void)k; } #endif