27#define FIBER_TESTS(X) \
28 X("fiber::types", test_fiber_types), X("fiber::switch", test_fiber_switch), \
29 X("fiber::stack", test_fiber_stack), \
30 X("fiber::sched::run", test_fiber_sched_run), \
31 X("fiber::sched::yield", test_fiber_sched_yield), \
32 X("fiber::sched::suspend", test_fiber_sched_suspend), \
33 X("fiber::sched::park_abort", test_fiber_sched_park_abort), \
34 X("fiber::sched::registry", test_fiber_sched_registry), \
35 X("fiber::sched::double_wake", test_fiber_sched_double_wake), \
36 X("fiber::sched::wait_for", test_fiber_sched_wait_for), \
37 X("fiber::sched::wait_for_done", test_fiber_sched_wait_for_done), \
38 X("fiber::sched::wait_for_many", test_fiber_sched_wait_for_many), \
39 X("fiber::sched::mt_run", test_fiber_sched_mt_run), \
40 X("fiber::sched::mt_yield", test_fiber_sched_mt_yield), \
41 X("fiber::sched::stop", test_fiber_sched_stop)
74 ((
char *)s.
limit)[0] = (char)0x5A;
75 ((
char *)s.
start)[-1] = (char)0x5A;
150 for (
int i = 0; i < N; i++) {
158 for (
int i = 0; i < N; i++) {
178 int id = (int)(intptr_t)arg;
179 for (
int i = 0; i < 2; i++) {
201 for (
int i = 0; i < 4; i++) {
527 for (
int i = 0; i < N; i++) {
547 int rounds = (int)(intptr_t)arg;
548 for (
int i = 0; i < rounds; i++) {
562 enum { N = 64, ROUNDS = 8 };
563 for (
int i = 0; i < N; i++) {
565 (
void *)(intptr_t)ROUNDS, 0);
587 for (
int i = 0; i < 3; i++) {
613 enum { PENDING = 3 };
614 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)
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...
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_make(srn_context_t *ctx, srn_scheduler_t *sched, srn_fiber_entry_t entry, void *arg, size_t stack_size)
Create a fiber that will run entry(ctx, arg).
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...
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.
static size_t srn_fiber_stack_size(srn_fiber_stack_t s)
@ 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
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 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 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 void test_fiber_types()
static int fiber_yield_log[4]
static srn_fiber_t fiber_pp_thread
static void test_fiber_sched_mt_run()
static int fiber_run_counter
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 srn_fiber_result_t fiber_producer_entry(srn_context_t *ctx, void *arg)
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.
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_sched_run(srn_scheduler_t *sched, int 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.
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...
void srn_fiber_stack_free(srn_fiber_stack_t stack)
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.
_Atomic srn_fiber_state_t state
The lifecycle state.