29#define FIBER_TESTS(X) \
30 X("fiber::types", test_fiber_types), X("fiber::switch", test_fiber_switch), \
31 X("fiber::stack", test_fiber_stack), \
32 X("fiber::thread_stack_bounds", test_fiber_thread_stack_bounds), \
33 X("fiber::auto_name", test_fiber_auto_name), \
34 X("fiber::make_schedule", test_fiber_make_schedule), \
35 X("fiber::spawn_copy", test_fiber_spawn_copy), X("fiber::sched::run", test_fiber_sched_run), \
36 X("fiber::sched::yield", test_fiber_sched_yield), \
37 X("fiber::sched::yield_round_robin", test_fiber_sched_yield_round_robin), \
38 X("fiber::sched::suspend", test_fiber_sched_suspend), \
39 X("fiber::sched::park_abort", test_fiber_sched_park_abort), \
40 X("fiber::sched::registry", test_fiber_sched_registry), \
41 X("fiber::sched::double_wake", test_fiber_sched_double_wake), \
42 X("fiber::sched::wait_for", test_fiber_sched_wait_for), \
43 X("fiber::sched::wait_for_done", test_fiber_sched_wait_for_done), \
44 X("fiber::sched::wait_for_many", test_fiber_sched_wait_for_many), \
45 X("fiber::sched::mt_run", test_fiber_sched_mt_run), \
46 X("fiber::sched::mt_yield", test_fiber_sched_mt_yield), \
47 X("fiber::sched::stop", test_fiber_sched_stop)
190 ((
char *)s.
limit)[0] = (char)0x5A;
191 ((
char *)s.
start)[-1] = (char)0x5A;
265 for (
int i = 0; i < N; i++) {
273 for (
int i = 0; i < N; i++) {
293 int id = (int)(intptr_t)arg;
294 for (
int i = 0; i < 2; i++) {
316 for (
int i = 0; i < 4; i++) {
338 int id = (int)(intptr_t)arg;
339 for (
int i = 0; i < 3; i++) {
363 for (
int i = 1; i < 6; i++) {
680 for (
int i = 0; i < N; i++) {
700 int rounds = (int)(intptr_t)arg;
701 for (
int i = 0; i < rounds; i++) {
715 enum { N = 64,
ROUNDS = 8 };
716 for (
int i = 0; i < N; i++) {
741 for (
int i = 0; i < 3; i++) {
766 enum { PENDING = 3 };
767 for (
int i = 0; i < PENDING; i++) {
#define RELEASE_CONTEXT(x)
#define ASSERT_NOT_NULL(x)
#define SHUTDOWN_ENGINE(mm, engine)
#define MAKE_ENGINE(mm, engine)
#define MAKE_CONTEXT(engine, x)
size_t srn_mm_get_os_page_size(void)
Retutrns the OS page size.
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...
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,...
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_fiber_switch(srn_fiber_t *from, srn_fiber_t *to)
Compiled without AddressSanitizer instrumentation, in stack-use-after-return mode ASan would place fr...
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.
AI Generated (🤦) Fiber subsystem overview.
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...
#define SRN_FIBER_SPAWN_COPY(ctx, entry, value)
srn_fiber_spawn_copy for an lvalue, the address and size are taken for the caller.
void srn_fiber_stack_free(srn_fiber_stack_t stack)
@ 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.
#define SRN_FIBER_DEFAULT_STACK_SIZE
Default size of every fiber stack.
void * srn_fiber_result_t
What a fiber's entry produces, type-erased.
static srn_fiber_t * fiber_dwake_waiter
static void test_fiber_sched_registry()
static void test_fiber_sched_wait_for_many()
static bool fiber_dwake_signalled
static void test_fiber_switch()
static int fiber_wf_result
static atomic_int fiber_mt_yield_counter
static srn_fiber_result_t fiber_pending_entry(srn_context_t *ctx, void *arg)
static void test_fiber_sched_double_wake()
static srn_fiber_result_t fiber_run_entry(srn_context_t *ctx, void *arg)
static bool fiber_mbox_park(srn_fiber_t *self, void *arg)
static srn_fiber_result_t fiber_wf_seen
static void test_fiber_make_schedule()
static atomic_int fiber_mt_counter
static srn_fiber_result_t fiber_dwake_consumer_entry(srn_context_t *ctx, void *arg)
static srn_fiber_result_t fiber_yield_entry(srn_context_t *ctx, void *arg)
static void test_fiber_sched_mt_yield()
static void test_fiber_stack()
static srn_fiber_result_t spawn_copy_entry(srn_context_t *ctx, void *arg)
static srn_fiber_result_t fiber_mt_entry(srn_context_t *ctx, void *arg)
static srn_fiber_result_t fiber_stopper_entry(srn_context_t *ctx, void *arg)
static srn_fiber_result_t fiber_wf_target_entry(srn_context_t *ctx, void *arg)
static int spawn_copy_seen
static void test_fiber_thread_stack_bounds()
static void test_fiber_types()
static int fiber_yield_log[4]
static srn_fiber_t fiber_pp_thread
static void test_fiber_spawn_copy()
static srn_fiber_result_t fiber_rr_entry(srn_context_t *ctx, void *arg)
static void test_fiber_sched_mt_run()
static int fiber_run_counter
static void test_fiber_sched_yield_round_robin()
static srn_fiber_result_t fiber_dwake_producer_entry(srn_context_t *ctx, void *arg)
static int fiber_dwake_runs
static srn_fiber_result_t fiber_wf_counting_waiter(srn_context_t *ctx, void *arg)
static void test_fiber_sched_suspend()
static bool fiber_stuck_park(srn_fiber_t *self, void *arg)
static void test_fiber_sched_park_abort()
static srn_fiber_result_t fiber_stuck_entry(srn_context_t *ctx, void *arg)
static atomic_int fiber_stop_rounds
static int fiber_rr_log[6]
static srn_fiber_result_t auto_name_entry(srn_context_t *ctx, void *arg)
static srn_fiber_result_t fiber_producer_entry(srn_context_t *ctx, void *arg)
static void test_fiber_auto_name()
static srn_fiber_result_t fiber_mt_yield_entry(srn_context_t *ctx, void *arg)
static void test_fiber_sched_yield()
static void test_fiber_sched_wait_for()
static bool fiber_dwake_park(srn_fiber_t *self, void *arg)
static void test_fiber_sched_run()
static int fiber_pp_rounds
static void fiber_pp_entry(void *arg)
static srn_fiber_result_t fiber_wf_waiter_entry(srn_context_t *ctx, void *arg)
static srn_fiber_t * fiber_wf_target
static void test_fiber_sched_stop()
static int fiber_ok_value
static srn_fiber_t fiber_pp_worker
static int fiber_pp_ticks
static int fiber_mbox_got
static fiber_mbox_t fiber_mbox
static srn_fiber_result_t fiber_consumer_entry(srn_context_t *ctx, void *arg)
static void test_fiber_sched_wait_for_done()
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.
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.
void srn_sched_stop(srn_scheduler_t *sched)
Ask a running scheduler to stop.
void srn_fiber_schedule(srn_fiber_t *fiber)
Schedule a NEW fiber, making it eligible to run.
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_suspend(srn_fiber_park_fn commit, void *arg)
A suspended fiber is on no scheduler queue, and the scheduler does not track what it waits on – whoev...
void srn_fiber_yield(void)
Yield cooperatively, re-enqueue the running fiber and run the next ready one.
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.