32extern void __sanitizer_start_switch_fiber(
void **fake_save,
const void *bottom,
size_t size);
33extern void __sanitizer_finish_switch_fiber(
void *fake_save,
const void **bottom_old,
45extern void *__tsan_get_current_fiber(
void);
46extern void *__tsan_create_fiber(
unsigned flags);
47extern void __tsan_destroy_fiber(
void *fiber);
48extern void __tsan_switch_to_fiber(
void *fiber,
unsigned flags);
67 __sanitizer_start_switch_fiber(&from->fake_stack, to->
stack.
limit, size);
74 if (to->tsan_fiber !=
nullptr) {
75 __tsan_switch_to_fiber(to->tsan_fiber, 0);
80 __sanitizer_finish_switch_fiber(from->fake_stack,
nullptr,
nullptr);
84[[gnu::no_sanitize_address]] [[gnu::no_sanitize_thread]]
void
90 __sanitizer_start_switch_fiber(
nullptr, to->
stack.
limit, size);
96 if (to->tsan_fiber !=
nullptr) {
97 __tsan_switch_to_fiber(to->tsan_fiber, 0);
114 const void *bottom =
nullptr;
116 __sanitizer_finish_switch_fiber(
nullptr, &bottom, &size);
118 if (from !=
nullptr) {
131 __tsan_destroy_fiber(fiber->tsan_fiber);
142 memset(f, 0,
sizeof(*f));
148 f->tsan_fiber = __tsan_get_current_fiber();
170 void *arg,
size_t stack_size) {
185 f->tsan_fiber = __tsan_create_fiber(0);
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_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).
static void srn_fiber_launcher(void *fiber_ptr)
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.
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.
AI Generated (🤦) Fiber subsystem overview.
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.
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_DONE
Entry returned. The result is final.
srn_fiber_result_t(* srn_fiber_entry_t)(srn_context_t *ctx, void *arg)
The function a fiber runs.
void * srn_fiber_result_t
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_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_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...
The saved context of a suspended fiber is a single word: its stack pointer at the moment it was switc...
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.
srn_fiber_result_t result
Set when state reaches SRN_FIBER_DONE.
const char * name
For debugging purposes.
srn_fiber_ctx_t fiber_ctx
Saved stack pointer (see srn_fiber_ctx_t)
#define PANIC_IF_NULL(ptr)
#define SHOULD_NOT_HAPPEN