skip to content
==> include/mesh/lease.h <==
1/* @ajax/mesh-lease: the lease (mesh-host lease.rs): mesh-rt's node loop played by a host thread
2 * against the mailbox, for executors without resident kernels -- wasm (CPU programs) and, in the
3 * Rust, Metal. One maintained owner of the node-loop protocol; the executor supplies only a runner
4 * that runs the taken tickets (wasm: calls into an instance).
5 *
6 * A lease lane owns `count` node records from `first` (wasm: one lane per node):
7 * - start: writes its node records (N_SM = the node number), P_ONLINE += count;
8 * - each turn it takes published tickets in order -- E_SEQ == t + 1, at most the runner's
9 *   max_take, none while H_BLINK is set if the lane is gated by it (a wasm lane is never relaunched
10 *   by a GPU blink and ignores it) -- each by a CAS on P_RING_HEAD, so several lanes of one slot
11 *   share its ring without a lock and no lane ever holds an unpublished ticket;
12 * - the runner runs them and completes each exactly as mesh-rt's nodes do (mesh_lease_complete):
13 *   P_RESULTS, P_MARKS = t + 1 (release), P_DONE += 1, the node record (tasks, last op, busy ns,
14 *   heartbeat), a trace record;
15 * - a fault (mesh_lease_fault, the first kept) leaves the tickets incomplete: the driver fails the
16 *   slot and shuts it down;
17 * - P_SHUTDOWN with nothing published: P_HALTED += count and the lane ends.
18 *
19 * mesh_round is the lockstep round (train), with the bounded wait in the host lane: publish
20 * ex_counter(k) = n, wait PEER_POLLS x PEER_POLL_NS for every member's counter >= n.
21 *
22 * A gated (GPU) lease counts each run in the slot's pipe flight word (pipe flight_begin/end); a
23 * wasm lane's pushes count themselves (host calls). */
24#ifndef MESH_LEASE_H
25#define MESH_LEASE_H
26
27#include "mesh/abi/control_block.h"
28#include "mesh/mailbox.h"
29
30#include <stdatomic.h>
31#include <stdbool.h>
32#include <stddef.h>
33#include <stdint.h>
34
35/* A lockstep round's outcome. */
36#define MESH_ROUND_OK 1u
37#define MESH_ROUND_TIMEOUT 2u
38
39/* Idle lanes heartbeat their node records this often (mesh-rt: HEARTBEAT_NS). */
40#define MESH_LEASE_HEARTBEAT_NS 2000000ull
41
42/* Host clock in ns (CLOCK_MONOTONIC): the trace's and the node records' timebase on a lease. */
43uint64_t mesh_host_ns(void);
44
45/* A taken ticket: (ticket, op, arg, completion slot). */
46typedef struct {
47    uint32_t t, op, arg, cslot;
48} mesh_taken;
49
50/* Counters for tools: batches run, tasks, passes, lockstep rounds and the wait in them. */
51typedef struct {
52    _Atomic uint64_t buffers, tasks, passes, rounds, round_wait_ns;
53} mesh_lane_stats;
54
55typedef struct mesh_lease mesh_lease;
56
57/* What an executor does with taken tickets. */
58typedef struct {
59    /* At most this many tickets per turn. */
60    size_t (*max_take)(void *self);
61    /* Runs taken[0..n) and completes each (mesh_lease_complete); false: a fault was recorded
62     * (mesh_lease_fault) and the rest stay incomplete. */
63    bool (*run)(void *self, mesh_lease *lease, const mesh_taken *taken, size_t n);
64    /* Idle, at each heartbeat (wasm: its CPU time and memory into cpuuse). NULL: nothing. */
65    void (*heartbeat)(void *self);
66} mesh_runner;
67
68/* One lane of a running slot. */
69struct mesh_lease {
70    mesh_mailbox mb;
71    uint32_t slot;
72    uint32_t first, count; /* the node records this lane owns: first .. first + count */
73    bool blink_gate;       /* no ticket is taken while H_BLINK is set (GPU leases) */
74    _Atomic bool *done;    /* set when the lane ends (the caller's, outlives the lane) */
75    mesh_lane_stats *stats; /* the caller's */
76    uint64_t beat_at;
77};
78
79/* done and stats are the caller's and must outlive the lane (the Rust's Arcs). */
80void mesh_lease_init(mesh_lease *l, mesh_mailbox mb, uint32_t slot, uint32_t first, uint32_t count, bool blink_gate,
81                     _Atomic bool *done, mesh_lane_stats *stats);
82static inline size_t mesh_lease_ctl(const mesh_lease *l, size_t off) { return mesh_prog_ctl(l->slot) + off; }
83
84/* The node loop. Runs on its own thread until P_SHUTDOWN with nothing published. */
85void mesh_lease_run(mesh_lease *l, const mesh_runner *runner, void *self);
86
87/* mesh-rt's completion of ticket k on node: result, mark (release), P_DONE, the node record, the
88 * trace (start/end: host or GPU ns). */
89void mesh_lease_complete(mesh_lease *l, uint32_t node, const mesh_taken *k, uint32_t result, uint64_t start, uint64_t end);
90/* Records the slot's first fault (P_FAULT keeps only the first). */
91void mesh_lease_fault(const mesh_lease *l, uint32_t code);
92/* The lockstep round n (mesh_round), counted in the lane's stats. */
93uint32_t mesh_lease_exchange(mesh_lease *l, uint64_t n);
94
95/* Round n for group rank k of N (H_GROUP_RANK, H_GROUP_N): publish ex_counter(k) = n (unless
96 * already), wait bounded for every other member's counter >= n. MESH_ROUND_OK or
97 * MESH_ROUND_TIMEOUT, and the time waited in *waited_ns (may be NULL). Not in a group:
98 * MESH_ROUND_TIMEOUT at once. */
99uint32_t mesh_round(mesh_mailbox mb, uint64_t n, uint64_t *waited_ns);
100
101#endif