114# error "no fiber context switch for this architecture (need ctx_<arch>.c and switch_<arch>.S)"
122#if defined(__SANITIZE_ADDRESS__)
124#elif defined(__has_feature)
125# if __has_feature(address_sanitizer)
133#if defined(__SANITIZE_THREAD__)
135#elif defined(__has_feature)
136# if __has_feature(thread_sanitizer)
159#define srn_fiber_get_scheduler_m(fiber) fiber->ctx->engine->scheduler
180#define SRN_FIBER_DEFAULT_STACK_SIZE (128U * 1024U)
187#define SRN_FIBER_NAME_MAX 32U
336[[nodiscard]] [[gnu::nonnull(1)]]
402[[gnu::nonnull(1, 2)]]
408[[gnu::nonnull(1, 2)]]
425[[nodiscard]] [[gnu::nonnull(1, 2, 4)]]
445[[gnu::nonnull(1, 2)]]
453[[gnu::nonnull(1, 2, 3)]]
461#define SRN_FIBER_SPAWN_COPY(ctx, entry, value) \
462 srn_fiber_spawn_copy(ctx, entry, &(value), sizeof(value))
513[[gnu::returns_nonnull]]
524[[gnu::nonnull(1, 2)]]
544[[gnu::nonnull(1, 3)]]
554[[gnu::nonnull(1, 2)]]
565[[noreturn]] [[gnu::nonnull(1)]]
612 return (
size_t)((
char *)s.
start - (
char *)s.
limit);
void srn_sched_register(srn_scheduler_t *sched, srn_fiber_t *fiber)
Record a fiber in the scheduler's registry of live fibers, where it stays until it is reaped.
srn_fiber_t * srn_fiber_worker_loop(void)
The worker's loop of the worker running on the calling os thread.
void srn_fiber_switch_final(srn_fiber_t *to)
Like srn_fiber_switch, but for a fiber that has finished and must not be resumed, control transfers t...
void srn_fiber_swap(srn_fiber_ctx_t *from, srn_fiber_ctx_t *to)
Save the current execution context into from, restore to, and resume on to's stack.
void srn_sched_wake_worker(srn_scheduler_t *sched, size_t channel)
Rouse parked workers so the owner of channel consumes its completions.
void srn_fiber_ready(srn_fiber_t *fiber)
Mark a suspended fiber runnable again, waking it when the event it awaited occurs.
srn_fiber_result_t srn_fiber_wait_for(srn_fiber_t *target)
Block the calling fiber until target finishes, then return its result.
srn_fiber_t * srn_fiber_spawn_copy(srn_context_t *ctx, srn_fiber_entry_t entry, const void *arg, size_t size)
srn_fiber_spawn with size bytes of *arg copied into ctx first, so the fiber owns its argument and the...
srn_fiber_t * srn_fiber_spawn(srn_context_t *ctx, srn_fiber_entry_t entry, void *arg)
Make and schedule a fiber with every default, the engine's scheduler, the configured stack size,...
srn_fiber_stack_t srn_fiber_stack_alloc(size_t size)
Allocate a stack of at least size usable bytes plus a guard page, or SRN_FIBER_DEFAULT_STACK_SIZE whe...
static size_t srn_fiber_stack_size(srn_fiber_stack_t s)
void srn_fiber_ctx_make(srn_fiber_ctx_t *fiber_ctx, srn_fiber_stack_t stack, void(*fn)(void *), void *arg)
Initialise a fresh fiber context so the first srn_fiber_swap into it begins executing fn(arg) on stac...
void srn_sched_drain(srn_scheduler_t *sched)
Ask a running scheduler to wind down gracefully.
#define SRN_FIBER_NAME_MAX
Size of the embedded debug name buffer on every fiber, terminator included.
void srn_fiber_init_thread(srn_fiber_t *f)
Represent the calling OS thread as the running fiber ("#0"), so the scheduler or a test can switch aw...
void srn_sched_shutdown(srn_scheduler_t *sched)
The one stop tear down of the fiber subsystem, should be called once srn_sched_run has returned.
bool srn_sched_accepting_submissions(srn_scheduler_t *sched)
Whether the scheduler still accepts new IO submissions.
void srn_fiber_stack_free(srn_fiber_stack_t stack)
void srn_sched_stop(srn_scheduler_t *sched)
Ask a running scheduler to stop.
void srn_sched_enqueue(srn_scheduler_t *sched, srn_fiber_t *fiber)
Place a fiber on a scheduler's ready queue, making it eligible to run.
@ SRN_FIBER_NEW
Created, stack mapped, never resumed.
@ SRN_FIBER_RUNNING
Currently executing.
@ SRN_FIBER_READY
On the run queue, eligible to run.
@ SRN_FIBER_DONE
Entry returned. The result is final.
@ SRN_FIBER_SUSPENDED
Parked off the run queue, awaits srn_fiber_ready.
srn_fiber_result_t(* srn_fiber_entry_t)(srn_context_t *ctx, void *arg)
The function a fiber runs.
srn_scheduler_t * srn_sched_init(srn_engine_t *engine)
srn_fiber_t * srn_fiber_current(void)
The fiber currently running on this os thread, or null when the calling thread is not a worker or the...
void srn_fiber_switch(srn_fiber_t *from, srn_fiber_t *to)
Switch from from to to, both live fibers, telling AddressSanitizer about the stack change.
srn_fiber_t * srn_fiber_make(srn_context_t *ctx, srn_scheduler_t *sched, const char *name, srn_fiber_entry_t entry, void *arg, size_t stack_size)
Create a fiber that will run entry(ctx, arg), registered with sched but NOT scheduled.
void srn_fiber_on_entry(srn_fiber_t *from)
Call as the first action inside a fresh fiber's entry.
bool(* srn_fiber_park_fn)(srn_fiber_t *self, void *arg)
Suspend commit callback.
void srn_fiber_schedule(srn_fiber_t *fiber)
Schedule a NEW fiber, making it eligible to run.
void * srn_fiber_result_t
What a fiber's entry produces, type-erased.
enum srn_fiber_state_e srn_fiber_state_t
void srn_sched_run(srn_scheduler_t *sched, size_t nworkers)
Run the scheduler with nworkers os threads draining it, returning once the pool goes quiescent (every...
void srn_fiber_on_reap(srn_fiber_t *fiber)
Call when a finished fiber is reaped, after it has switched away for the last time.
void srn_fiber_suspend(srn_fiber_park_fn commit, void *arg)
Park the running fiber until a party calls srn_fiber_ready.
void srn_fiber_yield(void)
Yield cooperatively, re-enqueue the running fiber and run the next ready one.
srn_worker_id_t srn_sched_current_worker_id(void)
Return the id of the worker that the calling os thread is running, or SIZE_MAX when the calling threa...
Engine is a structure to own the long living and main pieces of the compiler.
The saved context of a suspended fiber is a single word, its stack pointer at the moment it was switc...
One stack per fiber, mapped with a guard page at the low end so an overflow faults deterministically ...
void * guard
The protected page to detect stack overflows.
void * limit
Low end of usable region.
void * start
High end, stack pointer initialises to this address.
char name[SRN_FIBER_NAME_MAX]
Debug name, the caller's choice copied at creation, or the autogenerated f#<id> from the engine wide ...
_Atomic srn_fiber_state_t state
The lifecycle state.
srn_fiber_t * link
Intrusive link threading this fiber onto one of the scheduler's singly-linked lists (the ready run qu...
srn_fiber_t * waiters
Head of the list of fibers blocked in srn_fiber_wait_for on this fiber.
srn_fiber_result_t result
Set when state reaches SRN_FIBER_DONE.
srn_fiber_park_fn park_commit
While this fiber is suspending, the commit the worker routine runs once the fiber is off the stack,...
srn_fiber_t * reg_prev
Registry links.
srn_fiber_ctx_t fiber_ctx
Saved stack pointer (see srn_fiber_ctx_t).