==> src/pipesrc.c <==1/* pipesrc: the pipe demo's source on the wasm executor (alpha-rust-mesh programs/pipesrc/wasm;
2 * mesh-abi views::pipedemo). Each continuous task pushes up to S_BATCH records: msgs into
3 * pipehash's inbox (mode 0, the GPU hashes them), or digests it hashed itself straight into a sink
4 * (mode 1). A full pipe ends the task (backpressure: nothing is dropped, the record is pushed by a
5 * later task); no consumer loaded counts as gone. Every record carries the host clock at its push. */
6#include "mesh/abi/view_pipedemo.h"
7#include "mesh/rt_wasm.h"
8
9static void init(const mesh_ctx *ctx) {
10 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_MODE, MESH_PIPEDEMO_MODE_GPU);
11 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_BATCH, MESH_PIPEDEMO_SRC_BATCH);
12}
13
14static bool dst(const mesh_ctx *ctx, uint32_t mode, uint32_t *slot) {
15 switch (mode) {
16 case MESH_PIPEDEMO_MODE_GPU: return mesh_ctx_find(ctx, "pipehash", 8, slot);
17 case MESH_PIPEDEMO_MODE_DIRECT: return mesh_ctx_find(ctx, "pipesink", 8, slot) || mesh_ctx_find(ctx, "pipesink-w", 10, slot);
18 default: return false;
19 }
20}
21
22static void gone(const mesh_ctx *ctx) {
23 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_GONE, mesh_ctx_view_u32(ctx, MESH_PIPEDEMO_S_GONE) + 1u);
24 mesh_ctx_count(ctx, 2, 1);
25}
26
27static uint32_t send(const mesh_ctx *ctx) {
28 uint32_t mode = mesh_ctx_view_u32(ctx, MESH_PIPEDEMO_S_MODE);
29 if (mode == MESH_PIPEDEMO_MODE_OFF) return 0;
30 uint64_t iv = (uint64_t)mesh_ctx_view_u32(ctx, MESH_PIPEDEMO_S_INTERVAL_US) * 1000u;
31 /* Paced: wait out the interval in the task (bounded), so the pace is not the driver's tick. */
32 uint64_t now = mesh_ctx_host_ns(ctx);
33 uint64_t last = mesh_ctx_view_u64(ctx, MESH_PIPEDEMO_S_LAST_NS);
34 if (iv > 0 && now - last < iv) {
35 if (iv - (now - last) > 2000000u) return 0;
36 while (now - last < iv) now = mesh_ctx_host_ns(ctx);
37 }
38 mesh_ctx_set_u64(ctx, MESH_PIPEDEMO_S_LAST_NS, now);
39 uint32_t d;
40 if (!dst(ctx, mode, &d)) {
41 gone(ctx);
42 return 0;
43 }
44 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_DST, d + 1u);
45 uint32_t seq = mesh_ctx_view_u32(ctx, MESH_PIPEDEMO_S_NEXT_SEQ), sent = 0, full = 0;
46 uint32_t batch = mesh_ctx_view_u32(ctx, MESH_PIPEDEMO_S_BATCH);
47 for (uint32_t i = 0; i < batch; i++) {
48 uint32_t m[16];
49 mesh_pipedemo_msg(seq, mesh_ctx_host_ns(ctx), MESH_PIPEDEMO_ORIGIN_WASM, m);
50 int32_t code;
51 if (mode == MESH_PIPEDEMO_MODE_GPU) {
52 code = mesh_ctx_push_code(ctx, d, m, sizeof m);
53 } else {
54 uint32_t g[12];
55 mesh_pipedemo_digest(m, 0, g);
56 code = mesh_ctx_push_code(ctx, d, g, sizeof g);
57 }
58 if (code == MESH_PIPE_OK) {
59 seq++;
60 sent++;
61 } else if (code == MESH_PIPE_NONE) {
62 full = 1;
63 break;
64 } else {
65 gone(ctx);
66 break;
67 }
68 }
69 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_NEXT_SEQ, seq);
70 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_SENT, mesh_ctx_view_u32(ctx, MESH_PIPEDEMO_S_SENT) + sent);
71 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_FULL, mesh_ctx_view_u32(ctx, MESH_PIPEDEMO_S_FULL) + full);
72 mesh_ctx_count(ctx, 0, sent);
73 mesh_ctx_count(ctx, 1, full);
74 return sent;
75}
76
77static uint32_t task(const mesh_ctx *ctx, uint32_t op, uint32_t arg) {
78 switch (op) {
79 case MESH_OP_TASK: return send(ctx);
80 case MESH_PIPEDEMO_OP_MODE:
81 if (arg > MESH_PIPEDEMO_MODE_OFF) return MESH_R_BAD_OP;
82 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_MODE, arg);
83 return 0;
84 case MESH_PIPEDEMO_OP_BATCH:
85 if (arg < 1 || arg > 4096) return MESH_R_BAD_OP;
86 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_BATCH, arg);
87 return 0;
88 case MESH_PIPEDEMO_OP_INTERVAL: mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_INTERVAL_US, arg); return 0;
89 case MESH_PIPEDEMO_OP_RESET:
90 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_SENT, 0);
91 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_FULL, 0);
92 mesh_ctx_set_u32(ctx, MESH_PIPEDEMO_S_GONE, 0);
93 return 0;
94 default: return MESH_R_BAD_OP;
95 }
96}
97
98MESH_PROGRAM(init, task)