skip to content
==> src/main.c <==
1/* The native lifecycle fixture (mesh-worker src/bin/test_worker.rs; mesh-native's
2 * tests, mesh-lifecheck --native): op 0: arg * 3 + 7 (+ 1000 x param, so two
3 * images tell apart); OP_INIT: the view magic; 3: sleep arg ms; 4: param; 5:
4 * the pid; 9: panic; 10: allocate and touch arg MiB (a memory cap kills it);
5 * 11: read past the view (a fault); 12: spin arg ms (CPU); 13: SIGTERM itself
6 * if arg == 0, else exit(arg), mid-task (no core dump).  Its setup sleeps
7 * MESH_TEST_SETUP_MS (a slow model load). */
8#include "mesh/worker.h"
9
10#include "mesh/abi/ops.h"
11
12#include <signal.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <time.h>
17#include <unistd.h>
18
19#define MAGIC 0x57544e4eu /* "NNTW" */
20
21static void sleep_ms(uint64_t ms) {
22    struct timespec t = {(time_t)(ms / 1000), (long)(ms % 1000) * 1000000L};
23    nanosleep(&t, NULL);
24}
25
26static void init(const mesh_worker_ctx *ctx, void *u) {
27    (void)u;
28    mesh_ctx_set_u32(ctx, 0, MAGIC);
29    mesh_ctx_set_u32(ctx, 4, 0);
30}
31
32static uint32_t task(const mesh_worker_ctx *ctx, uint32_t op, uint32_t arg, void *u) {
33    (void)u;
34    switch (op) {
35    case MESH_OP_TASK:
36        mesh_ctx_count(ctx, 0, 1);
37        mesh_ctx_set_u32(ctx, 4, arg);
38        return arg * 3 + 7 + 1000 * mesh_ctx_param(ctx);
39    case 3:
40        sleep_ms(arg);
41        return arg;
42    case 4: return mesh_ctx_param(ctx);
43    case 5: return (uint32_t)getpid();
44    case 9: mesh_worker_panic("deliberate crash (op 9, arg %u)", (unsigned)arg);
45    case 10: {
46        size_t n = (size_t)arg << 20;
47        volatile uint8_t *v = calloc(n ? n : 1, 1);
48        if (!v) mesh_worker_panic("out of memory (%u MiB)", (unsigned)arg);
49        for (size_t i = 0; i < n; i += 4096) v[i] = 1;
50        free((void *)v);
51        return (uint32_t)(n >> 20);
52    }
53    case 11: return mesh_ctx_view_u32(ctx, mesh_ctx_view_len(ctx));
54    case 12: {
55        uint64_t t0 = mesh_worker_now_ns();
56        volatile uint64_t x = 0;
57        while (mesh_worker_now_ns() - t0 < (uint64_t)arg * 1000000u) x = x * 6364136223846793005u + 1;
58        return (uint32_t)x;
59    }
60    case 13:
61        if (arg == 0) raise(SIGTERM);
62        exit((int)arg);
63    default: return MESH_R_BAD_OP;
64    }
65}
66
67int main(void) {
68    const char *ms = getenv("MESH_TEST_SETUP_MS");
69    if (ms) sleep_ms(strtoull(ms, NULL, 10));
70    printf("test worker %d set up\n", (int)getpid());
71    fflush(stdout);
72    mesh_worker_run(&(mesh_worker_program){init, task, NULL});
73}