skip to content
==> 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)