Skip to main content

SCHED_CORE

Constant SCHED_CORE 

Source
pub const SCHED_CORE: &str = "/* The LOGOS scheduler \u{2014} `logicaffeine_runtime::Scheduler::process_step`, ported step for step.\n *\n * ONE policy core for every C-family tier: the coroutine runtimes (host C, RISC-V) and the stackless\n * frames (CUDA, the host bytecode walker). An operation is a state transition over the task table: it\n * mutates the queues and leaves the task it was handed either READY at the back of the ready queue,\n * holding the value it resumes with, or blocked off the queue. A tier supplies only the yield \u{2014} switching\n * back to its scheduler loop\'s context, or saving a frame\'s pc and returning \u{2014} and reads `resume`\n * when the task runs again. Every concurrency operation is a scheduling point, as it is in the runtime.\n *\n * Before this text a tier defines:\n *   LOGOS_FN         the qualifier of a core function (`static`, or `__device__ static`)\n *   LOGOS_VAR        the qualifier of a core variable\n *   logos_alloc(n)   / logos_release(p)\n *   LOGOS_TASK_TIER  the tier\'s own fields of a task: its context, or its frame\n * and may define LOGOS_SCHED_POLICY and LOGOS_CHAN_DEFAULT_CAP (defaults below: the runtime\'s own).\n */\n\n#ifndef LOGOS_SCHED_POLICY\n#define LOGOS_SCHED_FIFO 0\n#define LOGOS_SCHED_LIFO 1\n#define LOGOS_SCHED_ROUNDROBIN 2\n#define LOGOS_SCHED_RANDOM 3\n#define LOGOS_SCHED_PRIORITY 4\n#define LOGOS_SCHED_POLICY LOGOS_SCHED_FIFO\n#endif\n/* A pipe with no written capacity holds `SchedulerConfig::default_channel_capacity` values. */\n#ifndef LOGOS_CHAN_DEFAULT_CAP\n#define LOGOS_CHAN_DEFAULT_CAP 32LL\n#endif\n#ifndef LOGOS_SEL_MAX\n#define LOGOS_SEL_MAX 16\n#endif\n\n#define LOGOS_READY 0\n#define LOGOS_BLOCKED_RECV 1\n#define LOGOS_BLOCKED_SEND 2\n#define LOGOS_BLOCKED_TIMER 3\n#define LOGOS_BLOCKED_SELECT 4\n#define LOGOS_BLOCKED_AWAIT 5\n#define LOGOS_DONE 6\n\n#define LOGOS_ARM_RECV 0\n#define LOGOS_ARM_AFTER 1\n\ntypedef struct logos_task logos_task;\ntypedef struct logos_chan logos_chan;\n\n/* Tasks in arrival order, oldest first. */\ntypedef struct {\n    logos_task **at;\n    int head, len, cap;\n} logos_queue;\n\nstruct logos_task {\n    int state;\n    long long resume;         /* the value the operation that woke it delivers */\n    int resume_nothing;       /* it delivered `nothing`: a closed pipe, an empty try, an awaited task */\n    int selected_arm;         /* the arm a select resolved to */\n    long long send_value;     /* the value a blocked send holds */\n    logos_chan *waits_on;     /* the pipe a blocked receive or send waits on */\n    logos_task *awaits;       /* the task a blocked await waits for */\n    int sel_n;                /* a waiting select\'s arms, in declaration order */\n    int sel_kind[LOGOS_SEL_MAX];\n    logos_chan *sel_chan[LOGOS_SEL_MAX];\n    logos_queue awaiters;     /* the tasks awaiting this one, in the order they began to */\n    long long priority;\n    LOGOS_TASK_TIER\n};\n\nstruct logos_chan {\n    long long *buf;\n    int head, len, cap_alloc;\n    long long capacity;\n    int closed;\n    logos_queue receivers;    /* blocked receives; a waiting select once per arm naming this pipe */\n    logos_queue senders;      /* blocked sends, each holding its value in `send_value` */\n};\n\ntypedef struct {\n    long long fire_at;\n    logos_task *task;\n    int arm;                  /* the select arm it resolves, or -1 for a `Sleep` */\n} logos_timer;\n\nLOGOS_VAR logos_queue logos_ready_q;\n/* Finished tasks retain their storage until the scheduler has left their execution context. */\nLOGOS_VAR logos_queue logos_retired_q;\nLOGOS_VAR long long logos_clock = 0;\nLOGOS_VAR unsigned long long logos_rng = 0;\nLOGOS_VAR logos_timer *logos_timers = 0;\nLOGOS_VAR int logos_timer_n = 0, logos_timer_cap = 0;\nLOGOS_VAR logos_task **logos_all = 0;\nLOGOS_VAR int logos_all_n = 0, logos_all_cap = 0;\n/* The first failure of any task; the run fails with it once every other task is quiescent. */\nLOGOS_VAR const char *logos_failure = 0;\n\n/* ---- the chooser: `SeededRng`, the runtime\'s one source of scheduling choice ---- */\n\nLOGOS_FN void logos_seed(unsigned long long seed) { logos_rng = seed; }\n\nLOGOS_FN unsigned long long logos_rng_next(void) {\n    logos_rng += 0x9E3779B97F4A7C15ULL;\n    unsigned long long z = logos_rng;\n    z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL;\n    z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL;\n    return z ^ (z >> 31);\n}\n\n/* An index in [0, n); one option draws nothing, as `SeededRng::below` does. */\nLOGOS_FN int logos_choose(int n) {\n    if (n <= 1) return 0;\n    return (int)(logos_rng_next() % (unsigned long long)n);\n}\n\n/* ---- queues ---- */\n\nLOGOS_FN logos_task *logos_queue_at(logos_queue *q, int k) { return q->at[(q->head + k) % q->cap]; }\n\nLOGOS_FN void logos_queue_push(logos_queue *q, logos_task *t) {\n    if (q->len == q->cap) {\n        int cap = q->cap ? q->cap * 2 : 8;\n        logos_task **at = (logos_task **)logos_alloc((unsigned long)cap * sizeof(logos_task *));\n        for (int i = 0; i < q->len; i++) at[i] = logos_queue_at(q, i);\n        if (q->at) logos_release(q->at);\n        q->at = at;\n        q->head = 0;\n        q->cap = cap;\n    }\n    q->at[(q->head + q->len) % q->cap] = t;\n    q->len++;\n}\n\n/* Remove and return the k-th oldest. */\nLOGOS_FN logos_task *logos_queue_take(logos_queue *q, int k) {\n    logos_task *t = logos_queue_at(q, k);\n    if (k == 0) {\n        q->at[q->head] = 0;\n        q->head = (q->head + 1) % q->cap;\n    } else {\n        for (int i = k; i + 1 < q->len; i++) q->at[(q->head + i) % q->cap] = logos_queue_at(q, i + 1);\n        q->at[(q->head + q->len - 1) % q->cap] = 0;\n    }\n    q->len--;\n    return t;\n}\n\nLOGOS_FN logos_task *logos_queue_pop(logos_queue *q) { return q->len ? logos_queue_take(q, 0) : 0; }\n\n/* Drop every entry that is `t`, keeping the others in order. */\nLOGOS_FN void logos_queue_remove(logos_queue *q, logos_task *t) {\n    int kept = 0;\n    for (int i = 0; i < q->len; i++) {\n        logos_task *x = logos_queue_at(q, i);\n        if (x != t) q->at[(q->head + kept++) % q->cap] = x;\n    }\n    for (int i = kept; i < q->len; i++) q->at[(q->head + i) % q->cap] = 0;\n    q->len = kept;\n}\n\n/* ---- timers ---- */\n\nLOGOS_FN void logos_timer_add(long long fire_at, logos_task *t, int arm) {\n    if (logos_timer_n == logos_timer_cap) {\n        int cap = logos_timer_cap ? logos_timer_cap * 2 : 16;\n        logos_timer *at = (logos_timer *)logos_alloc((unsigned long)cap * sizeof(logos_timer));\n        for (int i = 0; i < logos_timer_n; i++) at[i] = logos_timers[i];\n        if (logos_timers) logos_release(logos_timers);\n        logos_timers = at;\n        logos_timer_cap = cap;\n    }\n    logos_timers[logos_timer_n].fire_at = fire_at;\n    logos_timers[logos_timer_n].task = t;\n    logos_timers[logos_timer_n].arm = arm;\n    logos_timer_n++;\n}\n\n/* Drop every timer of `t`, keeping the others in order. */\nLOGOS_FN void logos_timer_remove(logos_task *t) {\n    int kept = 0;\n    for (int i = 0; i < logos_timer_n; i++) {\n        if (logos_timers[i].task != t) logos_timers[kept++] = logos_timers[i];\n    }\n    for (int i = kept; i < logos_timer_n; i++) logos_timers[i].task = 0;\n    logos_timer_n = kept;\n}\n\n/* ---- tasks ---- */\n\nLOGOS_FN void logos_mark_ready(logos_task *t, long long value, int nothing) {\n    t->waits_on = 0;\n    t->awaits = 0;\n    t->send_value = 0;\n    t->resume = value;\n    t->resume_nothing = nothing;\n    t->state = LOGOS_READY;\n    logos_queue_push(&logos_ready_q, t);\n}\n\n/* A new task joins the table ready \u{2014} the runtime\'s `spawn_inner`. */\nLOGOS_FN void logos_task_begin(logos_task *t) {\n    t->resume = 0;\n    t->resume_nothing = 1;\n    t->selected_arm = -1;\n    t->send_value = 0;\n    t->waits_on = 0;\n    t->awaits = 0;\n    t->sel_n = 0;\n    t->awaiters.at = 0;\n    t->awaiters.head = t->awaiters.len = t->awaiters.cap = 0;\n    if (logos_all_n == logos_all_cap) {\n        int cap = logos_all_cap ? logos_all_cap * 2 : 16;\n        logos_task **at = (logos_task **)logos_alloc((unsigned long)cap * sizeof(logos_task *));\n        for (int i = 0; i < logos_all_n; i++) at[i] = logos_all[i];\n        if (logos_all) logos_release(logos_all);\n        logos_all = at;\n        logos_all_cap = cap;\n    }\n    logos_all[logos_all_n++] = t;\n    t->state = LOGOS_READY;\n    logos_queue_push(&logos_ready_q, t);\n}\n\n/* Wake everything awaiting `t`, which has finished: each resumes with `nothing`, the result every\n   C-family task carries (a task exits `Nothing` on the tree-walker). */\nLOGOS_FN void logos_complete(logos_task *t) {\n    t->resume = 0;\n    t->resume_nothing = 1;\n    t->waits_on = 0;\n    t->awaits = 0;\n    t->send_value = 0;\n    for (int i = 0; i < LOGOS_SEL_MAX; i++) t->sel_chan[i] = 0;\n    t->sel_n = 0;\n    logos_task *w;\n    while ((w = logos_queue_pop(&t->awaiters))) logos_mark_ready(w, 0, 1);\n    logos_release(t->awaiters.at);\n    t->awaiters.at = 0;\n    t->awaiters.cap = t->awaiters.head = t->awaiters.len = 0;\n    int kept = 0;\n    for (int i = 0; i < logos_all_n; i++) {\n        if (logos_all[i] != t) logos_all[kept++] = logos_all[i];\n    }\n    for (int i = kept; i < logos_all_n; i++) logos_all[i] = 0;\n    logos_all_n = kept;\n    logos_queue_push(&logos_retired_q, t);\n}\n\n/* ---- pipes ---- */\n\nLOGOS_FN int logos_chan_has_room(logos_chan *c) { return c->len < c->capacity; }\n\nLOGOS_FN int logos_chan_can_recv(logos_chan *c) { return c->len > 0 || c->senders.len > 0 || c->closed; }\n\nLOGOS_FN void logos_chan_buffer(logos_chan *c, long long v) {\n    if (c->len == c->cap_alloc) {\n        int cap = c->cap_alloc * 2;\n        long long *buf = (long long *)logos_alloc((unsigned long)cap * sizeof(long long));\n        for (int i = 0; i < c->len; i++) buf[i] = c->buf[(c->head + i) % c->cap_alloc];\n        logos_release(c->buf);\n        c->buf = buf;\n        c->head = 0;\n        c->cap_alloc = cap;\n    }\n    c->buf[(c->head + c->len) % c->cap_alloc] = v;\n    c->len++;\n}\n\nLOGOS_FN int logos_chan_unbuffer(logos_chan *c, long long *v) {\n    if (c->len == 0) return 0;\n    *v = c->buf[c->head];\n    c->buf[c->head] = 0;\n    c->head = (c->head + 1) % c->cap_alloc;\n    c->len--;\n    return 1;\n}\n\nLOGOS_FN void logos_refill_from_blocked_sender(logos_chan *c) {\n    if (!logos_chan_has_room(c)) return;\n    logos_task *s = logos_queue_pop(&c->senders);\n    if (s) {\n        logos_chan_buffer(c, s->send_value);\n        logos_mark_ready(s, 0, 1);\n    }\n}\n\n/* Withdraw every registration a woken select made \u{2014} on each pipe it names, the one that woke it too,\n   since a select naming one pipe in two arms waits on it twice \u{2014} and its timeouts. */\nLOGOS_FN void logos_cancel_select(logos_task *t) {\n    for (int i = 0; i < t->sel_n; i++) {\n        if (t->sel_kind[i] == LOGOS_ARM_RECV) logos_queue_remove(&t->sel_chan[i]->receivers, t);\n        t->sel_chan[i] = 0;\n    }\n    t->sel_n = 0;\n    logos_timer_remove(t);\n}\n\n/* The first arm of `t`\'s waiting select that receives from `c`. */\nLOGOS_FN int logos_arm_on(logos_task *t, logos_chan *c) {\n    for (int i = 0; i < t->sel_n; i++) {\n        if (t->sel_kind[i] == LOGOS_ARM_RECV && t->sel_chan[i] == c) return i;\n    }\n    return 0;\n}\n\nLOGOS_FN void logos_resolve_select(logos_task *t, int arm, long long value, int nothing) {\n    t->resume = value;\n    t->resume_nothing = nothing;\n    t->selected_arm = arm;\n    t->state = LOGOS_READY;\n    logos_queue_push(&logos_ready_q, t);\n    logos_cancel_select(t);\n}\n\nLOGOS_FN void logos_deliver(logos_task *r, logos_chan *c, long long v) {\n    if (r->state == LOGOS_BLOCKED_SELECT) {\n        logos_resolve_select(r, logos_arm_on(r, c), v, 0);\n    } else {\n        logos_mark_ready(r, v, 0);\n    }\n}\n\n/* One value from a pipe `logos_chan_can_recv` said is ready: buffered, from a blocked sender, or\n   `nothing` from a closed pipe. */\nLOGOS_FN void logos_take_one(logos_chan *c, long long *v, int *nothing) {\n    if (logos_chan_unbuffer(c, v)) {\n        *nothing = 0;\n        logos_refill_from_blocked_sender(c);\n        return;\n    }\n    logos_task *s = logos_queue_pop(&c->senders);\n    if (s) {\n        *v = s->send_value;\n        logos_mark_ready(s, 0, 1);\n        *nothing = 0;\n        return;\n    }\n    *v = 0;\n    *nothing = 1;\n}\n\n/* ---- the operations: one `process_step` arm each ---- */\n\nLOGOS_FN void logos_op_yield(logos_task *t) { logos_mark_ready(t, 0, 1); }\n\nLOGOS_FN logos_chan *logos_op_new_chan(logos_task *t, long long capacity) {\n    logos_chan *c = (logos_chan *)logos_alloc(sizeof(logos_chan));\n    c->cap_alloc = 8;\n    c->buf = (long long *)logos_alloc((unsigned long)c->cap_alloc * sizeof(long long));\n    c->head = 0;\n    c->len = 0;\n    c->capacity = capacity < 0 ? LOGOS_CHAN_DEFAULT_CAP : capacity;\n    c->closed = 0;\n    c->receivers.at = 0;\n    c->receivers.head = c->receivers.len = c->receivers.cap = 0;\n    c->senders.at = 0;\n    c->senders.head = c->senders.len = c->senders.cap = 0;\n    logos_mark_ready(t, 0, 1);\n    return c;\n}\n\n/* The child joins the ready queue, then the parent behind it: the child runs before its parent resumes. */\nLOGOS_FN void logos_op_spawn(logos_task *t, logos_task *child) {\n    logos_task_begin(child);\n    logos_mark_ready(t, 0, 1);\n}\n\nLOGOS_FN void logos_op_send(logos_task *t, logos_chan *c, long long v) {\n    logos_task *r = logos_queue_pop(&c->receivers);\n    if (r) {\n        logos_deliver(r, c, v);\n        logos_mark_ready(t, 0, 1);\n        return;\n    }\n    if (logos_chan_has_room(c)) {\n        logos_chan_buffer(c, v);\n        logos_mark_ready(t, 0, 1);\n        return;\n    }\n    t->send_value = v;\n    t->waits_on = c;\n    logos_queue_push(&c->senders, t);\n    t->state = LOGOS_BLOCKED_SEND;\n}\n\nLOGOS_FN void logos_op_recv(logos_task *t, logos_chan *c) {\n    long long v;\n    if (logos_chan_unbuffer(c, &v)) {\n        logos_mark_ready(t, v, 0);\n        logos_refill_from_blocked_sender(c);\n        return;\n    }\n    logos_task *s = logos_queue_pop(&c->senders);\n    if (s) {\n        logos_mark_ready(t, s->send_value, 0);\n        logos_mark_ready(s, 0, 1);\n        return;\n    }\n    if (c->closed) {\n        logos_mark_ready(t, 0, 1);\n        return;\n    }\n    t->waits_on = c;\n    logos_queue_push(&c->receivers, t);\n    t->state = LOGOS_BLOCKED_RECV;\n}\n\n/* Never blocks: resumes with 1 when the value was taken, else 0 (the value is dropped). */\nLOGOS_FN void logos_op_try_send(logos_task *t, logos_chan *c, long long v) {\n    logos_task *r = logos_queue_pop(&c->receivers);\n    if (r) {\n        logos_deliver(r, c, v);\n        logos_mark_ready(t, 1, 0);\n        return;\n    }\n    if (logos_chan_has_room(c)) {\n        logos_chan_buffer(c, v);\n        logos_mark_ready(t, 1, 0);\n        return;\n    }\n    logos_mark_ready(t, 0, 0);\n}\n\n/* Never blocks: resumes with a value, or with `nothing` when there is none. */\nLOGOS_FN void logos_op_try_recv(logos_task *t, logos_chan *c) {\n    long long v;\n    if (logos_chan_unbuffer(c, &v)) {\n        logos_mark_ready(t, v, 0);\n        logos_refill_from_blocked_sender(c);\n        return;\n    }\n    logos_task *s = logos_queue_pop(&c->senders);\n    if (s) {\n        logos_mark_ready(t, s->send_value, 0);\n        logos_mark_ready(s, 0, 1);\n        return;\n    }\n    logos_mark_ready(t, 0, 1);\n}\n\n/* A select: among its receive arms ready now, one wins \u{2014} the seeded chooser picks when several are \u{2014}\n   else it waits on every receive arm and every timeout at once. */\nLOGOS_FN void logos_op_select(logos_task *t, int n, const int *kind, logos_chan *const *chan, const long long *ticks) {\n    int ready[LOGOS_SEL_MAX];\n    int k = 0;\n    for (int i = 0; i < n; i++) {\n        if (kind[i] == LOGOS_ARM_RECV && logos_chan_can_recv(chan[i])) ready[k++] = i;\n    }\n    if (k > 0) {\n        int arm = ready[logos_choose(k)];\n        long long v;\n        int nothing;\n        logos_take_one(chan[arm], &v, &nothing);\n        t->resume = v;\n        t->resume_nothing = nothing;\n        t->selected_arm = arm;\n        t->state = LOGOS_READY;\n        logos_queue_push(&logos_ready_q, t);\n        return;\n    }\n    t->sel_n = n;\n    for (int i = 0; i < n; i++) {\n        t->sel_kind[i] = kind[i];\n        t->sel_chan[i] = kind[i] == LOGOS_ARM_RECV ? chan[i] : 0;\n        if (kind[i] == LOGOS_ARM_RECV) {\n            logos_queue_push(&chan[i]->receivers, t);\n        } else {\n            logos_timer_add(logos_clock + (ticks[i] < 0 ? 0 : ticks[i]), t, i);\n        }\n    }\n    t->state = LOGOS_BLOCKED_SELECT;\n}\n\nLOGOS_FN void logos_op_sleep(logos_task *t, long long ticks) {\n    logos_timer_add(logos_clock + (ticks < 0 ? 0 : ticks), t, -1);\n    t->state = LOGOS_BLOCKED_TIMER;\n}\n\nLOGOS_FN void logos_op_await(logos_task *t, logos_task *target) {\n    if (!target || target->state == LOGOS_DONE) {\n        logos_mark_ready(t, 0, 1);\n        return;\n    }\n    t->awaits = target;\n    logos_queue_push(&target->awaiters, t);\n    t->state = LOGOS_BLOCKED_AWAIT;\n}\n\n/* `Stop h`: the target leaves every queue it waits in and finishes, waking its awaiters with\n   `nothing`; the stopping task goes on. A finished target is untouched. */\nLOGOS_FN void logos_op_abort(logos_task *t, logos_task *target) {\n    if (target && target->state != LOGOS_DONE) {\n        logos_queue_remove(&logos_ready_q, target);\n        switch (target->state) {\n            case LOGOS_BLOCKED_RECV: logos_queue_remove(&target->waits_on->receivers, target); break;\n            case LOGOS_BLOCKED_SEND: logos_queue_remove(&target->waits_on->senders, target); break;\n            case LOGOS_BLOCKED_SELECT:\n                for (int i = 0; i < target->sel_n; i++) {\n                    if (target->sel_kind[i] == LOGOS_ARM_RECV) logos_queue_remove(&target->sel_chan[i]->receivers, target);\n                }\n                break;\n            case LOGOS_BLOCKED_AWAIT: logos_queue_remove(&target->awaits->awaiters, target); break;\n            default: break;\n        }\n        logos_timer_remove(target);\n        target->state = LOGOS_DONE;\n        logos_complete(target);\n    }\n    logos_mark_ready(t, 0, 1);\n}\n\n/* `Close c`: every blocked receive resumes with `nothing` \u{2014} a waiting select once, on its first arm\n   naming `c` \u{2014} and later receives of the drained pipe answer `nothing` too. */\nLOGOS_FN void logos_op_close(logos_task *t, logos_chan *c) {\n    c->closed = 1;\n    int n = c->receivers.len;\n    logos_task **waiting = n ? (logos_task **)logos_alloc((unsigned long)n * sizeof(logos_task *)) : 0;\n    for (int i = 0; i < n; i++) waiting[i] = logos_queue_at(&c->receivers, i);\n    for (int i = 0; i < c->receivers.cap; i++) c->receivers.at[i] = 0;\n    c->receivers.len = 0;\n    c->receivers.head = 0;\n    for (int i = 0; i < n; i++) {\n        logos_task *r = waiting[i];\n        if (r->state == LOGOS_BLOCKED_SELECT) {\n            logos_resolve_select(r, logos_arm_on(r, c), 0, 1);\n        } else if (r->state == LOGOS_BLOCKED_RECV) {\n            logos_mark_ready(r, 0, 1);\n        }\n    }\n    if (waiting) logos_release(waiting);\n    logos_mark_ready(t, 0, 1);\n}\n\n/* The task\'s body returned. */\nLOGOS_FN void logos_op_exit(logos_task *t) {\n    t->state = LOGOS_DONE;\n    logos_complete(t);\n}\n\n/* The task failed: the run keeps its first failure and every other task still runs to quiescence. */\nLOGOS_FN void logos_op_fail(logos_task *t, const char *message) {\n    if (!logos_failure) logos_failure = message;\n    logos_op_exit(t);\n}\n\n/* ---- the scheduler loop\'s two moves ---- */\n\n/* The next task to run, by the policy knob. */\nLOGOS_FN logos_task *logos_pick_ready(void) {\n    int n = logos_ready_q.len;\n    if (n == 0) return 0;\n    int k = 0;\n#if LOGOS_SCHED_POLICY == LOGOS_SCHED_LIFO\n    k = n - 1;\n#elif LOGOS_SCHED_POLICY == LOGOS_SCHED_RANDOM\n    k = logos_choose(n);\n#elif LOGOS_SCHED_POLICY == LOGOS_SCHED_PRIORITY\n    long long best = logos_queue_at(&logos_ready_q, 0)->priority;\n    for (int i = 1; i < n; i++) {\n        long long p = logos_queue_at(&logos_ready_q, i)->priority;\n        if (p > best) {\n            best = p;\n            k = i;\n        }\n    }\n#endif\n    return logos_queue_take(&logos_ready_q, k);\n}\n\n/* Nothing is ready: the clock jumps to the earliest timer and every timer due then fires, same-tick\n   ties in the order the seeded chooser draws. Answers 0 when no timer is pending. */\nLOGOS_FN int logos_advance_timers(void) {\n    if (logos_timer_n == 0) return 0;\n    long long earliest = logos_timers[0].fire_at;\n    for (int i = 1; i < logos_timer_n; i++) {\n        if (logos_timers[i].fire_at < earliest) earliest = logos_timers[i].fire_at;\n    }\n    logos_clock = earliest;\n    int due_n = 0;\n    for (int i = 0; i < logos_timer_n; i++) due_n += logos_timers[i].fire_at == earliest;\n    logos_timer *due = (logos_timer *)logos_alloc((unsigned long)due_n * sizeof(logos_timer));\n    int d = 0, kept = 0;\n    for (int i = 0; i < logos_timer_n; i++) {\n        if (logos_timers[i].fire_at == earliest) {\n            due[d++] = logos_timers[i];\n        } else {\n            logos_timers[kept++] = logos_timers[i];\n        }\n    }\n    for (int i = kept; i < logos_timer_n; i++) logos_timers[i].task = 0;\n    logos_timer_n = kept;\n    int *pool = (int *)logos_alloc((unsigned long)due_n * sizeof(int));\n    for (int i = 0; i < due_n; i++) pool[i] = i;\n    int left = due_n;\n    while (left > 0) {\n        int pick = logos_choose(left);\n        logos_timer fired = due[pool[pick]];\n        for (int i = pick; i + 1 < left; i++) pool[i] = pool[i + 1];\n        left--;\n        logos_task *t = fired.task;\n        if (t->state != LOGOS_BLOCKED_TIMER && t->state != LOGOS_BLOCKED_SELECT) continue;\n        if (fired.arm >= 0) {\n            int selecting = t->state == LOGOS_BLOCKED_SELECT;\n            t->selected_arm = fired.arm;\n            t->resume = 0;\n            t->resume_nothing = 1;\n            t->state = LOGOS_READY;\n            logos_queue_push(&logos_ready_q, t);\n            if (selecting) logos_cancel_select(t);\n        } else {\n            logos_mark_ready(t, 0, 1);\n        }\n    }\n    logos_release(pool);\n    logos_release(due);\n    return 1;\n}\n\n/* At quiescence: some task never finished \u{2014} the run deadlocked. */\nLOGOS_FN int logos_deadlocked(void) {\n    for (int i = 0; i < logos_all_n; i++) {\n        if (logos_all[i]->state != LOGOS_DONE) return 1;\n    }\n    return 0;\n}\n";
Expand description

The C family’s scheduler: logicaffeine_runtime::Scheduler::process_step ported once, in C every tier compiles — the host C and RISC-V coroutine runtimes, and the stepped tier’s frames CUDA and the bytecode walker run. A tier defines its qualifiers, its allocator and its own task fields before this text, and supplies only the yield (see the file’s header).