==> src/tick.c <==1/* tick for the wasm executor (alpha-rust-mesh programs/tick/wasm; the same layout and ops as
2 * programs/tick). The view past REGION holds pattern(i) per word; each task ticks word t % words
3 * to pattern(i) ^ (t + 1); OP_VERIFY samples the region against what the ticks must have left. */
4#include "mesh/rt_wasm.h"
5
6#define MAGIC 0x4b434954u /* "TICK" */
7#define TICKS 0x4u
8#define INITS 0x8u
9#define MISMATCH 0xcu
10#define REGION 0x40u
11#define OP_VERIFY 3u
12#define SAMPLES 4096u
13#define RECENT 64u
14
15static uint32_t pattern(uint32_t i) { return (i * 2654435761u) ^ 0x5a5a5a5au; }
16
17static uint32_t expect(uint32_t i, uint32_t ticks, uint32_t w) {
18 if (ticks <= i) return pattern(i);
19 uint32_t t = i + (ticks - 1 - i) / w * w;
20 return pattern(i) ^ (t + 1u);
21}
22
23static uint32_t words(const mesh_ctx *ctx) { return (mesh_view_len(mesh_ctx_view(ctx)) - REGION) / 4; }
24
25static uint32_t buf[1024];
26
27static void init(const mesh_ctx *ctx) {
28 mesh_view v = mesh_ctx_view(ctx);
29 uint32_t w = words(ctx);
30 /* In 4 KiB writes (one host call each). */
31 for (uint32_t i = 0; i < w;) {
32 uint32_t n = w - i < 1024 ? w - i : 1024;
33 for (uint32_t k = 0; k < n; k++) buf[k] = pattern(i + k);
34 mesh_view_write_u32s(v, REGION + 4 * i, buf, n);
35 i += n;
36 }
37 mesh_view_set_u32(v, 0x0, MAGIC);
38 mesh_view_set_u32(v, TICKS, 0);
39 mesh_view_set_u32(v, INITS, mesh_view_u32(v, INITS) + 1u);
40 mesh_ctx_count(ctx, 1, 1);
41}
42
43static uint32_t task(const mesh_ctx *ctx, uint32_t op, uint32_t arg) {
44 (void)arg;
45 mesh_view v = mesh_ctx_view(ctx);
46 uint32_t w = words(ctx);
47 switch (op) {
48 case MESH_OP_TASK: {
49 uint32_t t = mesh_view_u32(v, TICKS);
50 uint32_t i = t % w;
51 mesh_view_set_u32(v, REGION + 4 * i, pattern(i) ^ (t + 1u));
52 mesh_view_set_u32(v, TICKS, t + 1u);
53 mesh_ctx_count(ctx, 0, 1);
54 return 0;
55 }
56 case OP_VERIFY: {
57 uint32_t t = mesh_view_u32(v, TICKS);
58 uint32_t bad = 0;
59 for (uint32_t s = 0; s < SAMPLES; s++) {
60 uint32_t i = (uint32_t)((uint64_t)s * w / SAMPLES);
61 if (mesh_view_u32(v, REGION + 4 * i) != expect(i, t, w)) bad++;
62 }
63 uint32_t recent = RECENT < t ? RECENT : t;
64 for (uint32_t k = 1; k <= recent; k++) {
65 uint32_t i = (t - k) % w;
66 if (mesh_view_u32(v, REGION + 4 * i) != expect(i, t, w)) bad++;
67 }
68 mesh_view_set_u32(v, MISMATCH, bad);
69 return bad;
70 }
71 default: return MESH_R_BAD_OP;
72 }
73}
74
75MESH_PROGRAM(init, task)