==> include/mesh/worker_ctx.h <==1/* @ajax/mesh-worker-ctx: what a native worker program's init and task see
2 * (mesh-worker lib.rs: Mb, View, Ctx): mesh-rt's Ctx API on a CPU thread.
3 * A node is one thread: there are no lanes (lane() is 0, leader() true). */
4#ifndef MESH_WORKER_CTX_H
5#define MESH_WORKER_CTX_H
6
7#include "mesh/mailbox.h"
8
9#include <stdbool.h>
10#include <stddef.h>
11#include <stdint.h>
12
13/* A process-local monotonic clock in ns (CLOCK_MONOTONIC; macOS: CLOCK_UPTIME_RAW). */
14uint64_t mesh_worker_now_ns(void);
15
16/* A byte window of the mailbox (a view or part of one). Offsets are bytes
17 * from its start; u32/f32 accessors need 4-aligned offsets, u64 8-aligned.
18 * An access out of range (or misaligned) reads 0 / drops the write and
19 * records P_FAULT (meshd fails the program, as on the GPU). */
20typedef struct {
21 uint8_t *base;
22 uint32_t len;
23 uint8_t *ctl; /* the caller's control block, where a fault is recorded */
24} mesh_view;
25
26uint32_t mesh_view_len(mesh_view v);
27uint32_t mesh_view_u32(mesh_view v, uint32_t off);
28float mesh_view_f32(mesh_view v, uint32_t off);
29uint64_t mesh_view_u64(mesh_view v, uint32_t off);
30uint8_t mesh_view_u8(mesh_view v, uint32_t off);
31void mesh_view_set_u32(mesh_view v, uint32_t off, uint32_t x);
32void mesh_view_set_f32(mesh_view v, uint32_t off, float x);
33void mesh_view_set_u64(mesh_view v, uint32_t off, uint64_t x);
34void mesh_view_set_u8(mesh_view v, uint32_t off, uint8_t x);
35/* Atomic add on a u32 word (other nodes and processes may add too). */
36uint32_t mesh_view_add_u32(mesh_view v, uint32_t off, uint32_t x);
37/* Bulk copies (not atomic: publish them with a later set_u32). False (and a fault) when out of range. */
38bool mesh_view_read(mesh_view v, uint32_t off, uint8_t *out, size_t n);
39bool mesh_view_write(mesh_view v, uint32_t off, const uint8_t *b, size_t n);
40bool mesh_view_write_f32s(mesh_view v, uint32_t off, const float *x, size_t n);
41bool mesh_view_read_f32s(mesh_view v, uint32_t off, float *out, size_t n);
42/* A sub-window [off, off + len); false (and a fault) when out of range. */
43bool mesh_view_sub(mesh_view v, uint32_t off, uint32_t len, mesh_view *out);
44
45/* Node `node` of slot `slot` (its entry read at creation, under the seqlock). */
46typedef struct {
47 mesh_mailbox mb;
48 size_t ctl;
49 mesh_view view;
50 uint32_t slot, node, nodes, peer_mode;
51 uint32_t input_off, input_len, req_off, req_max, resp_off, resp_max;
52 uint32_t ticket; /* the running task's ring ticket; the node loop sets it */
53} mesh_worker_ctx;
54
55void mesh_worker_ctx_new(mesh_mailbox mb, uint32_t slot, uint32_t node, mesh_worker_ctx *out);
56/* One stable copy of slot s's table entry (PT_GEN even and unchanged), PT_BYTES / 4 words. */
57void mesh_worker_entry(mesh_mailbox mb, uint32_t s, uint32_t out[32]);
58
59/* ids */
60static inline uint32_t mesh_ctx_slot(const mesh_worker_ctx *c) { return c->slot; }
61static inline uint32_t mesh_ctx_node(const mesh_worker_ctx *c) { return c->node; }
62static inline uint32_t mesh_ctx_nodes(const mesh_worker_ctx *c) { return c->nodes; }
63static inline uint32_t mesh_ctx_lane(const mesh_worker_ctx *c) { (void)c; return 0; }
64static inline bool mesh_ctx_leader(const mesh_worker_ctx *c) { (void)c; return true; }
65static inline uint32_t mesh_ctx_ticket(const mesh_worker_ctx *c) { return c->ticket; }
66static inline uint32_t mesh_ctx_peer_mode(const mesh_worker_ctx *c) { return c->peer_mode; }
67uint32_t mesh_ctx_system(const mesh_worker_ctx *c); /* H_PEER */
68uint32_t mesh_ctx_systems(const mesh_worker_ctx *c); /* H_SYSTEMS */
69/* The lockstep group's (rank, size), or false (a native program is never lockstep). */
70bool mesh_ctx_group(const mesh_worker_ctx *c, uint32_t *rank, uint32_t *size);
71uint32_t mesh_ctx_param(const mesh_worker_ctx *c); /* PX_PARAM */
72uint32_t mesh_ctx_sms(const mesh_worker_ctx *c); /* H_SMS */
73
74/* own view */
75static inline mesh_view mesh_ctx_view(const mesh_worker_ctx *c) { return c->view; }
76static inline uint32_t mesh_ctx_view_len(const mesh_worker_ctx *c) { return c->view.len; }
77static inline uint32_t mesh_ctx_view_u32(const mesh_worker_ctx *c, uint32_t off) { return mesh_view_u32(c->view, off); }
78static inline float mesh_ctx_view_f32(const mesh_worker_ctx *c, uint32_t off) { return mesh_view_f32(c->view, off); }
79static inline uint64_t mesh_ctx_view_u64(const mesh_worker_ctx *c, uint32_t off) { return mesh_view_u64(c->view, off); }
80static inline uint8_t mesh_ctx_view_u8(const mesh_worker_ctx *c, uint32_t off) { return mesh_view_u8(c->view, off); }
81static inline void mesh_ctx_set_u32(const mesh_worker_ctx *c, uint32_t off, uint32_t v) { mesh_view_set_u32(c->view, off, v); }
82static inline void mesh_ctx_set_f32(const mesh_worker_ctx *c, uint32_t off, float v) { mesh_view_set_f32(c->view, off, v); }
83static inline void mesh_ctx_set_u64(const mesh_worker_ctx *c, uint32_t off, uint64_t v) { mesh_view_set_u64(c->view, off, v); }
84static inline void mesh_ctx_set_u8(const mesh_worker_ctx *c, uint32_t off, uint8_t v) { mesh_view_set_u8(c->view, off, v); }
85
86/* Other programs: slot s's view if `reads` lists it and the slot holds a
87 * program (the mask re-read at each call); false otherwise (an undeclared
88 * read also records FAULT_PEER_VIEW). */
89bool mesh_ctx_peer_view(const mesh_worker_ctx *c, uint32_t s, mesh_view *out);
90/* The slot holding program name: true and *slot, or false. */
91bool mesh_ctx_find(const mesh_worker_ctx *c, const char *name, uint32_t *slot);
92uint32_t mesh_ctx_prog_state(const mesh_worker_ctx *c, uint32_t s);
93/* Slot s's name into out (at least 17 bytes). */
94void mesh_ctx_prog_name(const mesh_worker_ctx *c, uint32_t s, char out[17]);
95/* The whole mailbox, for a READS_ALL program; false otherwise. */
96bool mesh_ctx_mailbox(const mesh_worker_ctx *c, mesh_mailbox *out);
97
98/* input queue (manifest `input`) */
99uint32_t mesh_ctx_input_pending(const mesh_worker_ctx *c);
100/* The next input byte; false when empty. Nodes may pop concurrently. */
101bool mesh_ctx_input_pop(const mesh_worker_ctx *c, uint8_t *out);
102
103/* pipes (manifest `inbox`, `feeds`) */
104/* Pushes one record into slot s's inbox: PIPE_OK, PIPE_NONE (full: keep it,
105 * try later), or a negative PIPE_* code. A slot this program does not feed,
106 * or a wrong size, records FAULT_PIPE. */
107int32_t mesh_ctx_push_code(const mesh_worker_ctx *c, uint32_t s, const uint8_t *rec, size_t n);
108bool mesh_ctx_push(const mesh_worker_ctx *c, uint32_t s, const uint8_t *rec, size_t n);
109/* Pops the own inbox's next record into out (its record size): false when empty. */
110bool mesh_ctx_pop(const mesh_worker_ctx *c, uint8_t *out, size_t n);
111/* Records waiting in slot s's inbox: true and *len, or false. */
112bool mesh_ctx_pipe_len(const mesh_worker_ctx *c, uint32_t s, uint32_t *len);
113static inline uint64_t mesh_ctx_host_ns(const mesh_worker_ctx *c) { (void)c; return mesh_worker_now_ns(); }
114
115/* request window (manifest `request`, op OP_REQ) */
116mesh_view mesh_ctx_request(const mesh_worker_ctx *c);
117mesh_view mesh_ctx_response(const mesh_worker_ctx *c);
118/* Publishes len response bytes (P_RESP_LEN, then P_RESP_SEQ = P_REQ_SEQ, release). */
119void mesh_ctx_respond(const mesh_worker_ctx *c, uint32_t len);
120
121/* counters (manifest `counters`) */
122void mesh_ctx_count(const mesh_worker_ctx *c, uint32_t i, uint32_t n);
123uint32_t mesh_ctx_counter(const mesh_worker_ctx *c, uint32_t i);
124/* Asks meshd to start/stop slot s (P_RUN_REQ): READS_ALL programs only. */
125bool mesh_ctx_request_run(const mesh_worker_ctx *c, uint32_t s, bool on);
126
127#endif