65816-llvm-mos/runtime/include/threads.h
Scott Duensing e65fedc8e1 Checkpoint
2026-05-13 15:48:34 -05:00

91 lines
3.6 KiB
C

// 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 <threads.h>` and uses `thrd_t` etc. compiles.
#ifndef _THREADS_H
#define _THREADS_H
#include <time.h>
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