Serene Runtime 1.0.0
C runtime for the Serene programming language
Loading...
Searching...
No Matches
fiber_tests.h File Reference
#include <stdatomic.h>
#include <stdint.h>
#include "base.h"
#include "serene/rt/fiber.h"
Include dependency graph for fiber_tests.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  fiber_mbox_t
 

Macros

#define FIBER_TESTS(X)
 

Functions

static void test_fiber_types ()
 
static void test_fiber_stack ()
 
static void fiber_pp_entry (void *arg)
 
static void test_fiber_switch ()
 
static srn_fiber_result_t fiber_run_entry (srn_context_t *ctx, void *arg)
 
static void test_fiber_sched_run ()
 
static srn_fiber_result_t fiber_yield_entry (srn_context_t *ctx, void *arg)
 
static void test_fiber_sched_yield ()
 
static bool fiber_mbox_park (srn_fiber_t *self, void *arg)
 
static srn_fiber_result_t fiber_consumer_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_sched_suspend ()
 
static void test_fiber_sched_park_abort ()
 
static bool fiber_stuck_park (srn_fiber_t *self, void *arg)
 
static srn_fiber_result_t fiber_stuck_entry (srn_context_t *ctx, void *arg)
 
static void test_fiber_sched_registry ()
 
static bool fiber_dwake_park (srn_fiber_t *self, void *arg)
 
static srn_fiber_result_t fiber_dwake_consumer_entry (srn_context_t *ctx, void *arg)
 
static srn_fiber_result_t fiber_dwake_producer_entry (srn_context_t *ctx, void *arg)
 
static void test_fiber_sched_double_wake ()
 
static srn_fiber_result_t fiber_wf_target_entry (srn_context_t *ctx, void *arg)
 
static srn_fiber_result_t fiber_wf_waiter_entry (srn_context_t *ctx, void *arg)
 
static void test_fiber_sched_wait_for ()
 
static void test_fiber_sched_wait_for_done ()
 
static srn_fiber_result_t fiber_wf_counting_waiter (srn_context_t *ctx, void *arg)
 
static void test_fiber_sched_wait_for_many ()
 
static srn_fiber_result_t fiber_mt_entry (srn_context_t *ctx, void *arg)
 
static void test_fiber_sched_mt_run ()
 
static srn_fiber_result_t fiber_mt_yield_entry (srn_context_t *ctx, void *arg)
 
static void test_fiber_sched_mt_yield ()
 
static srn_fiber_result_t fiber_stopper_entry (srn_context_t *ctx, void *arg)
 
static srn_fiber_result_t fiber_pending_entry (srn_context_t *ctx, void *arg)
 
static void test_fiber_sched_stop ()
 

Variables

static srn_fiber_t fiber_pp_thread
 
static srn_fiber_t fiber_pp_worker
 
static int fiber_pp_ticks
 
static int fiber_pp_rounds
 
static int fiber_ok_value
 
static int fiber_run_counter
 
static int fiber_yield_log [4]
 
static int fiber_yield_n
 
static fiber_mbox_t fiber_mbox
 
static int fiber_mbox_got
 
static srn_fiber_tfiber_dwake_waiter
 
static bool fiber_dwake_signalled
 
static int fiber_dwake_runs
 
static int fiber_wf_result
 
static srn_fiber_tfiber_wf_target
 
static srn_fiber_result_t fiber_wf_seen
 
static int fiber_wf_woke
 
static atomic_int fiber_mt_counter
 
static atomic_int fiber_mt_yield_counter
 
static atomic_int fiber_stop_rounds
 

Macro Definition Documentation

◆ FIBER_TESTS

#define FIBER_TESTS ( X)
Value:
X("fiber::types", test_fiber_types), X("fiber::switch", test_fiber_switch), \
X("fiber::stack", test_fiber_stack), \
X("fiber::sched::run", test_fiber_sched_run), \
X("fiber::sched::yield", test_fiber_sched_yield), \
X("fiber::sched::suspend", test_fiber_sched_suspend), \
X("fiber::sched::park_abort", test_fiber_sched_park_abort), \
X("fiber::sched::registry", test_fiber_sched_registry), \
X("fiber::sched::double_wake", test_fiber_sched_double_wake), \
X("fiber::sched::wait_for", test_fiber_sched_wait_for), \
X("fiber::sched::wait_for_done", test_fiber_sched_wait_for_done), \
X("fiber::sched::wait_for_many", test_fiber_sched_wait_for_many), \
X("fiber::sched::mt_run", test_fiber_sched_mt_run), \
X("fiber::sched::mt_yield", test_fiber_sched_mt_yield), \
X("fiber::sched::stop", test_fiber_sched_stop)
static void test_fiber_sched_registry()
static void test_fiber_sched_wait_for_many()
static void test_fiber_switch()
static void test_fiber_sched_double_wake()
static void test_fiber_sched_mt_yield()
static void test_fiber_stack()
Definition fiber_tests.h:58
static void test_fiber_types()
Definition fiber_tests.h:43
static void test_fiber_sched_mt_run()
static void test_fiber_sched_suspend()
static void test_fiber_sched_park_abort()
static void test_fiber_sched_yield()
static void test_fiber_sched_wait_for()
static void test_fiber_sched_run()
static void test_fiber_sched_stop()
static void test_fiber_sched_wait_for_done()

Definition at line 27 of file fiber_tests.h.

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)

Function Documentation

◆ fiber_consumer_entry()

static srn_fiber_result_t fiber_consumer_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 238 of file fiber_tests.h.

238 {
239 UNUSED(ctx);
240 UNUSED(arg);
243 return &fiber_ok_value;
244}
static bool fiber_mbox_park(srn_fiber_t *self, void *arg)
static int fiber_ok_value
static int fiber_mbox_got
static fiber_mbox_t fiber_mbox
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...
Definition scheduler.c:898
#define UNUSED(x)
Definition utils.h:43
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fiber_dwake_consumer_entry()

static srn_fiber_result_t fiber_dwake_consumer_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 362 of file fiber_tests.h.

363 {
364 UNUSED(ctx);
365 UNUSED(arg);
368 return &fiber_ok_value;
369}
static int fiber_dwake_runs
static bool fiber_dwake_park(srn_fiber_t *self, void *arg)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fiber_dwake_park()

static bool fiber_dwake_park ( srn_fiber_t * self,
void * arg )
static

Definition at line 353 of file fiber_tests.h.

353 {
354 UNUSED(arg);
356 return false;
357 }
358 fiber_dwake_waiter = self;
359 return true;
360}
static srn_fiber_t * fiber_dwake_waiter
static bool fiber_dwake_signalled
Here is the caller graph for this function:

◆ fiber_dwake_producer_entry()

static srn_fiber_result_t fiber_dwake_producer_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 371 of file fiber_tests.h.

372 {
373 UNUSED(ctx);
374 UNUSED(arg);
376 if (fiber_dwake_waiter != nullptr) {
378 fiber_dwake_waiter = nullptr;
379 srn_fiber_ready(w); // first waker: SUSPENDED -> READY, enqueued
380 srn_fiber_ready(w); // second waker: already READY -> no-op
381 }
382 return &fiber_ok_value;
383}
void srn_fiber_ready(srn_fiber_t *fiber)
Mark a suspended fiber runnable again.
Definition scheduler.c:918
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fiber_mbox_park()

static bool fiber_mbox_park ( srn_fiber_t * self,
void * arg )
static

Definition at line 229 of file fiber_tests.h.

229 {
230 fiber_mbox_t *mb = arg;
231 if (mb->has_value) {
232 return false;
233 }
234 mb->waiter = self;
235 return true;
236}
srn_fiber_t * waiter
Here is the caller graph for this function:

◆ fiber_mt_entry()

static srn_fiber_result_t fiber_mt_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 512 of file fiber_tests.h.

512 {
513 UNUSED(ctx);
514 UNUSED(arg);
515 atomic_fetch_add(&fiber_mt_counter, 1);
516 return &fiber_ok_value;
517}
static atomic_int fiber_mt_counter
Here is the caller graph for this function:

◆ fiber_mt_yield_entry()

static srn_fiber_result_t fiber_mt_yield_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 545 of file fiber_tests.h.

545 {
546 UNUSED(ctx);
547 int rounds = (int)(intptr_t)arg;
548 for (int i = 0; i < rounds; i++) {
549 atomic_fetch_add(&fiber_mt_yield_counter, 1);
551 }
552 return &fiber_ok_value;
553}
static atomic_int fiber_mt_yield_counter
void srn_fiber_yield(void)
Yield cooperatively: re-enqueue the running fiber and run the next ready one.
Definition scheduler.c:876
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fiber_pending_entry()

static srn_fiber_result_t fiber_pending_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 595 of file fiber_tests.h.

595 {
596 UNUSED(ctx);
597 UNUSED(arg);
598 // Never reached: the stopper ends the run first. It adds a large amount, so
599 // any accidental execution is visible in the count.
600 atomic_fetch_add(&fiber_stop_rounds, 1000);
601 return &fiber_ok_value;
602}
static atomic_int fiber_stop_rounds
Here is the caller graph for this function:

◆ fiber_pp_entry()

static void fiber_pp_entry ( void * arg)
static

Definition at line 90 of file fiber_tests.h.

90 {
91 UNUSED(arg);
93 for (int i = 0; i < fiber_pp_rounds; i++) {
96 }
98}
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...
Definition fiber.c:85
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...
Definition fiber.c:62
void srn_fiber_on_entry(srn_fiber_t *from)
Call as the first action inside a fresh fiber's entry.
Definition fiber.c:107
static srn_fiber_t fiber_pp_thread
Definition fiber_tests.h:85
static int fiber_pp_rounds
Definition fiber_tests.h:88
static srn_fiber_t fiber_pp_worker
Definition fiber_tests.h:86
static int fiber_pp_ticks
Definition fiber_tests.h:87
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fiber_producer_entry()

static srn_fiber_result_t fiber_producer_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 246 of file fiber_tests.h.

246 {
247 UNUSED(ctx);
248 UNUSED(arg);
249 fiber_mbox.value = 42;
250 fiber_mbox.has_value = true;
251 if (fiber_mbox.waiter != nullptr) {
252 srn_fiber_t *w = fiber_mbox.waiter;
253 fiber_mbox.waiter = nullptr;
255 }
256 return &fiber_ok_value;
257}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fiber_run_entry()

static srn_fiber_result_t fiber_run_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 134 of file fiber_tests.h.

134 {
135 UNUSED(ctx);
136 UNUSED(arg);
138 return &fiber_ok_value;
139}
static int fiber_run_counter
Here is the caller graph for this function:

◆ fiber_stopper_entry()

static srn_fiber_result_t fiber_stopper_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 584 of file fiber_tests.h.

584 {
585 UNUSED(ctx);
586 srn_scheduler_t *sched = arg;
587 for (int i = 0; i < 3; i++) {
588 atomic_fetch_add(&fiber_stop_rounds, 1);
590 }
591 srn_sched_stop(sched);
592 return &fiber_ok_value;
593}
void srn_sched_stop(srn_scheduler_t *sched)
Ask a running scheduler to stop.
Definition scheduler.c:849
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fiber_stuck_entry()

static srn_fiber_result_t fiber_stuck_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 317 of file fiber_tests.h.

317 {
318 UNUSED(ctx);
319 UNUSED(arg);
320 srn_fiber_suspend(fiber_stuck_park, nullptr); // never readied
321 return &fiber_ok_value;
322}
static bool fiber_stuck_park(srn_fiber_t *self, void *arg)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fiber_stuck_park()

static bool fiber_stuck_park ( srn_fiber_t * self,
void * arg )
static

Definition at line 311 of file fiber_tests.h.

311 {
312 UNUSED(self);
313 UNUSED(arg);
314 return true; // stay parked, with no waker
315}
Here is the caller graph for this function:

◆ fiber_wf_counting_waiter()

static srn_fiber_result_t fiber_wf_counting_waiter ( srn_context_t * ctx,
void * arg )
static

Definition at line 473 of file fiber_tests.h.

474 {
475 UNUSED(ctx);
476 UNUSED(arg);
479 }
480 return &fiber_ok_value;
481}
static int fiber_wf_woke
static int fiber_wf_result
static srn_fiber_t * fiber_wf_target
srn_fiber_result_t srn_fiber_wait_for(srn_fiber_t *target)
Block the calling fiber until target finishes, then return its result.
Definition scheduler.c:963
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fiber_wf_target_entry()

static srn_fiber_result_t fiber_wf_target_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 414 of file fiber_tests.h.

414 {
415 UNUSED(ctx);
416 UNUSED(arg);
417 return &fiber_wf_result;
418}
Here is the caller graph for this function:

◆ fiber_wf_waiter_entry()

static srn_fiber_result_t fiber_wf_waiter_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 420 of file fiber_tests.h.

420 {
421 UNUSED(ctx);
422 UNUSED(arg);
424 return &fiber_ok_value;
425}
static srn_fiber_result_t fiber_wf_seen
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fiber_yield_entry()

static srn_fiber_result_t fiber_yield_entry ( srn_context_t * ctx,
void * arg )
static

Definition at line 176 of file fiber_tests.h.

176 {
177 UNUSED(ctx);
178 int id = (int)(intptr_t)arg;
179 for (int i = 0; i < 2; i++) {
182 }
183 return &fiber_ok_value;
184}
static int fiber_yield_n
static int fiber_yield_log[4]
Here is the call graph for this function:
Here is the caller graph for this function:

◆ test_fiber_sched_double_wake()

static void test_fiber_sched_double_wake ( )
static

Definition at line 385 of file fiber_tests.h.

385 {
386 MAKE_ENGINE(mm, engine);
387 MAKE_CONTEXT(engine, ctx);
388 srn_scheduler_t *sched = engine->scheduler;
389 ASSERT_NOT_NULL(sched);
390
391 fiber_dwake_waiter = nullptr;
392 fiber_dwake_signalled = false;
394
395 // Consumer first, so it runs and suspends before the producer wakes it.
396 (void)srn_fiber_make(ctx, sched, fiber_dwake_consumer_entry, nullptr, 0);
397 (void)srn_fiber_make(ctx, sched, fiber_dwake_producer_entry, nullptr, 0);
398
399 srn_sched_run(sched, 1);
400
402
403 RELEASE_CONTEXT(ctx);
404 SHUTDOWN_ENGINE(mm, engine);
405}
#define TEST_CHECK(cond)
Definition acutest.h:96
#define RELEASE_CONTEXT(x)
Definition base.h:46
#define ASSERT_NOT_NULL(x)
Definition base.h:30
#define SHUTDOWN_ENGINE(mm, engine)
Definition base.h:38
#define MAKE_ENGINE(mm, engine)
Definition base.h:32
#define MAKE_CONTEXT(engine, x)
Definition base.h:42
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).
Definition fiber.c:169
static srn_fiber_result_t fiber_dwake_consumer_entry(srn_context_t *ctx, void *arg)
static srn_fiber_result_t fiber_dwake_producer_entry(srn_context_t *ctx, void *arg)
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...
Definition scheduler.c:784
Here is the call graph for this function:

◆ test_fiber_sched_mt_run()

static void test_fiber_sched_mt_run ( )
static

Definition at line 519 of file fiber_tests.h.

519 {
520 MAKE_ENGINE(mm, engine);
521 MAKE_CONTEXT(engine, ctx);
522 srn_scheduler_t *sched = engine->scheduler;
523 ASSERT_NOT_NULL(sched);
524
525 atomic_store(&fiber_mt_counter, 0);
526 enum { N = 256 };
527 for (int i = 0; i < N; i++) {
528 (void)srn_fiber_make(ctx, sched, fiber_mt_entry, nullptr, 0);
529 }
530
531 srn_sched_run(sched, 4);
532
533 TEST_CHECK(atomic_load(&fiber_mt_counter) == N);
534
535 RELEASE_CONTEXT(ctx);
536 SHUTDOWN_ENGINE(mm, engine);
537}
static srn_fiber_result_t fiber_mt_entry(srn_context_t *ctx, void *arg)
Here is the call graph for this function:

◆ test_fiber_sched_mt_yield()

static void test_fiber_sched_mt_yield ( )
static

Definition at line 555 of file fiber_tests.h.

555 {
556 MAKE_ENGINE(mm, engine);
557 MAKE_CONTEXT(engine, ctx);
558 srn_scheduler_t *sched = engine->scheduler;
559 ASSERT_NOT_NULL(sched);
560
561 atomic_store(&fiber_mt_yield_counter, 0);
562 enum { N = 64, ROUNDS = 8 };
563 for (int i = 0; i < N; i++) {
564 (void)srn_fiber_make(ctx, sched, fiber_mt_yield_entry,
565 (void *)(intptr_t)ROUNDS, 0);
566 }
567
568 srn_sched_run(sched, 4);
569
570 TEST_CHECK(atomic_load(&fiber_mt_yield_counter) == N * ROUNDS);
571
572 RELEASE_CONTEXT(ctx);
573 SHUTDOWN_ENGINE(mm, engine);
574}
static srn_fiber_result_t fiber_mt_yield_entry(srn_context_t *ctx, void *arg)
Here is the call graph for this function:

◆ test_fiber_sched_park_abort()

static void test_fiber_sched_park_abort ( )
static

Definition at line 284 of file fiber_tests.h.

284 {
285 MAKE_ENGINE(mm, engine);
286 MAKE_CONTEXT(engine, ctx);
287 srn_scheduler_t *sched = engine->scheduler;
288 ASSERT_NOT_NULL(sched);
289
291 fiber_mbox.value = 7;
292 fiber_mbox.has_value = true; // value present before the consumer runs
293 fiber_mbox_got = 0;
294
295 (void)srn_fiber_make(ctx, sched, fiber_consumer_entry, nullptr, 0);
296
297 srn_sched_run(sched, 1);
298
300 TEST_CHECK(fiber_mbox.waiter == nullptr); // never registered as a waiter
301
302 RELEASE_CONTEXT(ctx);
303 SHUTDOWN_ENGINE(mm, engine);
304}
static srn_fiber_result_t fiber_consumer_entry(srn_context_t *ctx, void *arg)
Here is the call graph for this function:

◆ test_fiber_sched_registry()

static void test_fiber_sched_registry ( )
static

Definition at line 324 of file fiber_tests.h.

324 {
325 MAKE_ENGINE(mm, engine);
326 MAKE_CONTEXT(engine, ctx);
327 srn_scheduler_t *sched = engine->scheduler;
328 ASSERT_NOT_NULL(sched);
329
330 srn_fiber_t *stuck =
331 srn_fiber_make(ctx, sched, fiber_stuck_entry, nullptr, 0);
332 ASSERT_NOT_NULL(stuck);
333
334 // Drains the ready queue. The stuck fiber suspends and is abandoned.
335 srn_sched_run(sched, 1);
337
338 // The registry lets shutdown find and free the abandoned fiber's stack.
339 srn_sched_shutdown(sched);
340
341 RELEASE_CONTEXT(ctx);
342 SHUTDOWN_ENGINE(mm, engine);
343}
@ SRN_FIBER_SUSPENDED
Parked off the run queue, awaits srn_fiber_ready.
Definition fiber.h:188
static srn_fiber_result_t fiber_stuck_entry(srn_context_t *ctx, void *arg)
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.
Definition scheduler.c:314
_Atomic srn_fiber_state_t state
The lifecycle state.
Definition fiber.h:217
Here is the call graph for this function:

◆ test_fiber_sched_run()

static void test_fiber_sched_run ( )
static

Definition at line 141 of file fiber_tests.h.

141 {
142 MAKE_ENGINE(mm, engine);
143 MAKE_CONTEXT(engine, ctx);
144 srn_scheduler_t *sched = engine->scheduler;
145 ASSERT_NOT_NULL(sched);
146
148 enum { N = 4 };
149 srn_fiber_t *fibers[N];
150 for (int i = 0; i < N; i++) {
151 fibers[i] = srn_fiber_make(ctx, sched, fiber_run_entry, nullptr, 0);
152 ASSERT_NOT_NULL(fibers[i]);
153 }
154
155 srn_sched_run(sched, 1);
156
158 for (int i = 0; i < N; i++) {
159 // The struct lives in the context block after reaping. Only the stack is
160 // released, so state and result are still readable here.
161 TEST_CHECK(fibers[i]->state == SRN_FIBER_DONE);
162 TEST_CHECK(fibers[i]->result == &fiber_ok_value);
163 }
164
165 RELEASE_CONTEXT(ctx);
166 SHUTDOWN_ENGINE(mm, engine);
167}
@ SRN_FIBER_DONE
Entry returned. The result is final.
Definition fiber.h:190
static srn_fiber_result_t fiber_run_entry(srn_context_t *ctx, void *arg)
Here is the call graph for this function:

◆ test_fiber_sched_stop()

static void test_fiber_sched_stop ( )
static

Definition at line 604 of file fiber_tests.h.

604 {
605 MAKE_ENGINE(mm, engine);
606 MAKE_CONTEXT(engine, ctx);
607 srn_scheduler_t *sched = engine->scheduler;
608 ASSERT_NOT_NULL(sched);
609
610 atomic_store(&fiber_stop_rounds, 0);
611 // Stopper first so it reaches the single worker before the pending fibers.
612 (void)srn_fiber_make(ctx, sched, fiber_stopper_entry, sched, 0);
613 enum { PENDING = 3 };
614 for (int i = 0; i < PENDING; i++) {
615 (void)srn_fiber_make(ctx, sched, fiber_pending_entry, nullptr, 0);
616 }
617
618 // Returns when the stopper calls srn_sched_stop, with the pending fibers
619 // still queued.
620 srn_sched_run(sched, 1);
621
622 // Only the stopper ran (three rounds); no pending fiber ran.
623 TEST_CHECK(atomic_load(&fiber_stop_rounds) == 3);
624
625 // Reap the pending fibers while their structs (in the context block) are
626 // still alive, before releasing the context. SHUTDOWN_ENGINE calls shutdown
627 // again, which is a no-op on an already torn-down scheduler.
628 srn_sched_shutdown(sched);
629
630 RELEASE_CONTEXT(ctx);
631 SHUTDOWN_ENGINE(mm, engine);
632}
static srn_fiber_result_t fiber_pending_entry(srn_context_t *ctx, void *arg)
static srn_fiber_result_t fiber_stopper_entry(srn_context_t *ctx, void *arg)
Here is the call graph for this function:

◆ test_fiber_sched_suspend()

static void test_fiber_sched_suspend ( )
static

Definition at line 259 of file fiber_tests.h.

259 {
260 MAKE_ENGINE(mm, engine);
261 MAKE_CONTEXT(engine, ctx);
262 srn_scheduler_t *sched = engine->scheduler;
263 ASSERT_NOT_NULL(sched);
264
266 fiber_mbox_got = 0;
267
268 // Order matters: the consumer must be enqueued first so it runs and suspends
269 // before the producer fills the slot.
270 (void)srn_fiber_make(ctx, sched, fiber_consumer_entry, nullptr, 0);
271 (void)srn_fiber_make(ctx, sched, fiber_producer_entry, nullptr, 0);
272
273 srn_sched_run(sched, 1);
274
276
277 RELEASE_CONTEXT(ctx);
278 SHUTDOWN_ENGINE(mm, engine);
279}
static srn_fiber_result_t fiber_producer_entry(srn_context_t *ctx, void *arg)
Here is the call graph for this function:

◆ test_fiber_sched_wait_for()

static void test_fiber_sched_wait_for ( )
static

Definition at line 427 of file fiber_tests.h.

427 {
428 MAKE_ENGINE(mm, engine);
429 MAKE_CONTEXT(engine, ctx);
430 srn_scheduler_t *sched = engine->scheduler;
431 ASSERT_NOT_NULL(sched);
432
433 fiber_wf_seen = nullptr;
434 // Waiter made first, so it runs and parks before the target finishes.
435 (void)srn_fiber_make(ctx, sched, fiber_wf_waiter_entry, nullptr, 0);
437 srn_fiber_make(ctx, sched, fiber_wf_target_entry, nullptr, 0);
438
439 srn_sched_run(sched, 1);
440
442
443 RELEASE_CONTEXT(ctx);
444 SHUTDOWN_ENGINE(mm, engine);
445}
static srn_fiber_result_t fiber_wf_target_entry(srn_context_t *ctx, void *arg)
static srn_fiber_result_t fiber_wf_waiter_entry(srn_context_t *ctx, void *arg)
Here is the call graph for this function:

◆ test_fiber_sched_wait_for_done()

static void test_fiber_sched_wait_for_done ( )
static

Definition at line 449 of file fiber_tests.h.

449 {
450 MAKE_ENGINE(mm, engine);
451 MAKE_CONTEXT(engine, ctx);
452 srn_scheduler_t *sched = engine->scheduler;
453 ASSERT_NOT_NULL(sched);
454
455 fiber_wf_seen = nullptr;
456 // Target made first, so it runs and finishes before the waiter runs.
458 srn_fiber_make(ctx, sched, fiber_wf_target_entry, nullptr, 0);
459 (void)srn_fiber_make(ctx, sched, fiber_wf_waiter_entry, nullptr, 0);
460
461 srn_sched_run(sched, 1);
462
464
465 RELEASE_CONTEXT(ctx);
466 SHUTDOWN_ENGINE(mm, engine);
467}
Here is the call graph for this function:

◆ test_fiber_sched_wait_for_many()

static void test_fiber_sched_wait_for_many ( )
static

Definition at line 483 of file fiber_tests.h.

483 {
484 MAKE_ENGINE(mm, engine);
485 MAKE_CONTEXT(engine, ctx);
486 srn_scheduler_t *sched = engine->scheduler;
487 ASSERT_NOT_NULL(sched);
488
489 fiber_wf_woke = 0;
490 // Three waiters made first so they all park, then the target finishes.
491 (void)srn_fiber_make(ctx, sched, fiber_wf_counting_waiter, nullptr, 0);
492 (void)srn_fiber_make(ctx, sched, fiber_wf_counting_waiter, nullptr, 0);
493 (void)srn_fiber_make(ctx, sched, fiber_wf_counting_waiter, nullptr, 0);
495 srn_fiber_make(ctx, sched, fiber_wf_target_entry, nullptr, 0);
496
497 srn_sched_run(sched, 1);
498
500
501 RELEASE_CONTEXT(ctx);
502 SHUTDOWN_ENGINE(mm, engine);
503}
static srn_fiber_result_t fiber_wf_counting_waiter(srn_context_t *ctx, void *arg)
Here is the call graph for this function:

◆ test_fiber_sched_yield()

static void test_fiber_sched_yield ( )
static

Definition at line 186 of file fiber_tests.h.

186 {
187 MAKE_ENGINE(mm, engine);
188 MAKE_CONTEXT(engine, ctx);
189 srn_scheduler_t *sched = engine->scheduler;
190 ASSERT_NOT_NULL(sched);
191
192 fiber_yield_n = 0;
193 (void)srn_fiber_make(ctx, sched, fiber_yield_entry, (void *)(intptr_t)1, 0);
194 (void)srn_fiber_make(ctx, sched, fiber_yield_entry, (void *)(intptr_t)2, 0);
195
196 srn_sched_run(sched, 1);
197
199 int ones = 0;
200 int twos = 0;
201 for (int i = 0; i < 4; i++) {
202 if (fiber_yield_log[i] == 1) {
203 ones++;
204 } else if (fiber_yield_log[i] == 2) {
205 twos++;
206 }
207 }
208 TEST_CHECK(ones == 2);
209 TEST_CHECK(twos == 2);
210
211 RELEASE_CONTEXT(ctx);
212 SHUTDOWN_ENGINE(mm, engine);
213}
static srn_fiber_result_t fiber_yield_entry(srn_context_t *ctx, void *arg)
Here is the call graph for this function:

◆ test_fiber_stack()

static void test_fiber_stack ( )
static

Definition at line 58 of file fiber_tests.h.

58 {
59 size_t page = srn_mm_get_os_page_size();
60
62
63 TEST_CHECK(s.guard != nullptr);
64 TEST_CHECK(s.limit != nullptr);
65 TEST_CHECK(s.start != nullptr);
66 // The guard sits exactly one page below the usable region.
67 TEST_CHECK((char *)s.limit == (char *)s.guard + page);
68 // The usable region is non-empty, page-aligned, and at least the default.
69 TEST_CHECK((char *)s.start > (char *)s.limit);
70 TEST_CHECK(((uintptr_t)s.limit & (page - 1)) == 0);
72
73 // The whole usable region is writable end to end. The guard is left alone.
74 ((char *)s.limit)[0] = (char)0x5A;
75 ((char *)s.start)[-1] = (char)0x5A;
76
78}
size_t srn_mm_get_os_page_size(void)
Retutrns the OS page size.
Definition default.c:270
static size_t srn_fiber_stack_size(srn_fiber_stack_t s)
Definition fiber.h:437
#define SRN_FIBER_DEFAULT_STACK_SIZE
Default size of every fiber stack.
Definition fiber.h:138
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...
Definition stack_posix.c:34
void srn_fiber_stack_free(srn_fiber_stack_t stack)
Definition stack_posix.c:67
One stack per fiber, mapped with a guard page at the low end so an overflow faults deterministically ...
Definition fiber.h:168
void * guard
The protected page to detect stack overflows.
Definition fiber.h:174
void * limit
Low end of usable region.
Definition fiber.h:172
void * start
High end, stack pointer initialises to this address.
Definition fiber.h:170
Here is the call graph for this function:

◆ test_fiber_switch()

static void test_fiber_switch ( )
static

Definition at line 100 of file fiber_tests.h.

100 {
102
104
106 fiber_pp_worker.stack = worker_stack;
108 srn_fiber_ctx_make(&fiber_pp_worker.fiber_ctx, worker_stack, fiber_pp_entry,
109 nullptr);
110
111 fiber_pp_ticks = 0;
112 fiber_pp_rounds = 5;
113
114 // `rounds` yields, plus one more switch to let the worker run to completion.
115 for (int i = 0; i <= fiber_pp_rounds; i++) {
117 }
118
121
122 srn_fiber_stack_free(worker_stack);
123}
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...
Definition ctx_x86_64.c:29
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...
Definition fiber.c:137
@ SRN_FIBER_NEW
Created, stack mapped, never resumed.
Definition fiber.h:182
@ SRN_FIBER_RUNNING
Currently executing.
Definition fiber.h:186
static void fiber_pp_entry(void *arg)
Definition fiber_tests.h:90
Here is the call graph for this function:

◆ test_fiber_types()

static void test_fiber_types ( )
static

Definition at line 43 of file fiber_tests.h.

43 {
44 // Smoke test: the public types exist and the build/test wiring works.
45 // The saved context is a single stack-pointer word.
46 TEST_CHECK(sizeof(srn_fiber_ctx_t) == sizeof(void *));
47 // The lifecycle states run from creation to completion in order.
53}
@ SRN_FIBER_READY
On the run queue, eligible to run.
Definition fiber.h:184
The saved context of a suspended fiber is a single word: its stack pointer at the moment it was switc...
Definition fiber.h:147

Variable Documentation

◆ fiber_dwake_runs

int fiber_dwake_runs
static

Definition at line 351 of file fiber_tests.h.

◆ fiber_dwake_signalled

bool fiber_dwake_signalled
static

Definition at line 350 of file fiber_tests.h.

◆ fiber_dwake_waiter

srn_fiber_t* fiber_dwake_waiter
static

Definition at line 349 of file fiber_tests.h.

◆ fiber_mbox

fiber_mbox_t fiber_mbox
static

Definition at line 224 of file fiber_tests.h.

◆ fiber_mbox_got

int fiber_mbox_got
static

Definition at line 225 of file fiber_tests.h.

◆ fiber_mt_counter

atomic_int fiber_mt_counter
static

Definition at line 510 of file fiber_tests.h.

◆ fiber_mt_yield_counter

atomic_int fiber_mt_yield_counter
static

Definition at line 543 of file fiber_tests.h.

◆ fiber_ok_value

int fiber_ok_value
static

Definition at line 127 of file fiber_tests.h.

◆ fiber_pp_rounds

int fiber_pp_rounds
static

Definition at line 88 of file fiber_tests.h.

◆ fiber_pp_thread

srn_fiber_t fiber_pp_thread
static

Definition at line 85 of file fiber_tests.h.

◆ fiber_pp_ticks

int fiber_pp_ticks
static

Definition at line 87 of file fiber_tests.h.

◆ fiber_pp_worker

srn_fiber_t fiber_pp_worker
static

Definition at line 86 of file fiber_tests.h.

◆ fiber_run_counter

int fiber_run_counter
static

Definition at line 132 of file fiber_tests.h.

◆ fiber_stop_rounds

atomic_int fiber_stop_rounds
static

Definition at line 582 of file fiber_tests.h.

◆ fiber_wf_result

int fiber_wf_result
static

Definition at line 410 of file fiber_tests.h.

◆ fiber_wf_seen

srn_fiber_result_t fiber_wf_seen
static

Definition at line 412 of file fiber_tests.h.

◆ fiber_wf_target

srn_fiber_t* fiber_wf_target
static

Definition at line 411 of file fiber_tests.h.

◆ fiber_wf_woke

int fiber_wf_woke
static

Definition at line 471 of file fiber_tests.h.

◆ fiber_yield_log

int fiber_yield_log[4]
static

Definition at line 173 of file fiber_tests.h.

◆ fiber_yield_n

int fiber_yield_n
static

Definition at line 174 of file fiber_tests.h.