Skip to content

Shared test concurrency core

include/test/conc.h View source View on GitHub

Concurrency stuff that tests really like to use, primarily for thread fleets and other things. Nightmare tests and regular tests can use these. Some features:

  1. Cooperative stops, so deadlines can tell workers to    quit instead of abandoning them

  2. Quiesce/park so coordinators can bring workers to a stop

  3. Per-CPU progress counters for stall detection

struct test_rng (1 field) source
§ uint64_t state
struct test_progress_counter (1 field) source
struct test_stall_evidence (2 fields) source
§ time_ms_t silent_ms
§ uint64_t progress
struct test_conc_worker (6 fields) source
§ size_t index
§ const char *role
§ struct test_rng rng
§ void *arg
§ atomic(struct thread *) th
§ atomic_bool parked
struct test_conc (8 fields) source
§ atomic_bool active
§ atomic(enum test_stop) stop
§ atomic_bool quiesce_requested
§ atomic_size_t parked_count
§ struct test_conc_worker *workers cc_counted_by(worker_count)
§ size_t worker_count
§ atomic(struct thread *) aux

An extra thread that should be alerted on stop but isn’t a worker, NULL if unused

§ struct event start

For telling all the workers ‘go!‘

struct test_liveness_state (11 fields) source
§ struct watchdog_callback callback
§ uint64_t last_progress
§ time_ms_t last_change_ms
§ time_ms_t threshold_ms
§ bool was_quiesced
§ struct test_stall_evidence pending
§ enum test_on_stall policy
§ cpu_id_t coordinator_cpu
§ bool registered
§ struct test_conc *conc
enum test_stop : uint8_t (5 variants) source
§ TEST_RUN = 0
§ TEST_STOP_BUDGET

soft deadline, wind down when out of time

§ TEST_STOP_FINDING

worker reported a failure

§ TEST_STOP_FAIL

harness-side failure, e.g. spawn failed

§ TEST_STOP_STALL

hard deadline

enum test_on_stall : uint8_t (2 variants) source
§ TEST_ON_STALL_REPORT = 0
§ TEST_ON_STALL_CRASH
enum test_liveness_phase : uint8_t (4 variants) source
§ TEST_LIVE_OFF = 0
§ TEST_LIVE_ARMED
§ TEST_LIVE_PENDING
§ TEST_LIVE_REPORTED
uint64_t test_rng_seed_for(uint64_t base_seed, size_t index)
source
void test_conc_init(
    struct test_conc *c,
    struct test_conc_worker *workers,
    size_t worker_count
)
source
void test_conc_publish_stop(
    struct test_conc *c,
    enum test_stop reason
)
source
void test_conc_park(struct test_conc *c, struct test_conc_worker *w)
source
void test_conc_unpark_self(
    struct test_conc *c,
    struct test_conc_worker *w
)
source
uint64_t test_conc_progress_sum(void)
source

This is a percpu heuristic, migrations are fine

bool test_liveness_start(
    struct test_liveness_state *state,
    struct test_conc *conc,
    time_ms_t threshold_ms,
    enum test_on_stall policy
)
source
void test_liveness_stop(struct test_liveness_state *state)
source
bool test_liveness_take(
    struct test_liveness_state *state,
    struct test_stall_evidence *out
)
source

Return stall evidence when pending, false if nothing to report

void test_conc_progress_tick(void)
source
uint64_t test_rng_next(struct test_rng *rng)
source
bool test_conc_must_stop(const struct test_conc *c)
source
enum test_stop test_conc_stop_reason(const struct test_conc *c)
source
bool test_conc_must_park(const struct test_conc *c)
source
#define TEST_PROGRESS()
source
Expansion
#define TEST_PROGRESS() test_conc_progress_tick()