skip to content
==> tests/prog_table.c <==
1/* programs.rs's reset_slot_leaves_the_gpu_run_request and table_seqlock. */
2/* sexc compiles tests without the package's cflags (reported): the feature macro is here. */
3#define _XOPEN_SOURCE 700
4#include "mesh/check.h"
5#include "mesh/manifest.h"
6#include "mesh/manifest_encode.h"
7#include "mesh/prog_table.h"
8
9#include <pthread.h>
10#include <stdatomic.h>
11#include <time.h>
12#include <stdlib.h>
13#include <string.h>
14
15static mesh_mailbox mb;
16static void *reader(void *arg) {
17    static uint8_t e[MESH_PT_BYTES];
18    mesh_pt_read_entry(mb, 3, e);
19    atomic_store((_Atomic int *)arg, 1);
20    return NULL;
21}
22
23int main(void) {
24    mb = mesh_mailbox_test();
25    for (size_t o = 0; o < MESH_PROG_CTL_BYTES; o += 4) mesh_mailbox_set(mb, mesh_prog_ctl(2) + o, 7);
26    mesh_pt_reset_slot(mb, 2);
27    int ok = 1;
28    for (size_t o = 0; o < MESH_PROG_CTL_BYTES; o += 4) ok &= mesh_mailbox_get(mb, mesh_prog_ctl(2) + o) == (o == MESH_P_RUN_REQ ? 7u : 0u);
29    CHECK(ok);
30    CHECK_U(mesh_run_req_next(0, true), 3);
31    CHECK_U(mesh_run_req_next(3, true), 5);
32    CHECK_U(mesh_run_req_next(5, false), 6);
33    CHECK_U(mesh_run_req_next(UINT32_MAX, false) >> 1, 0);
34
35    mesh_manifest m;
36    char *err = NULL;
37    const char *text = "name = \"hello\"\nabi = 6\nview_bytes = 0x1000\ncounters = [\"tasks\"]";
38    CHECK(mesh_manifest_parse(text, strlen(text), &m, &err));
39    mesh_image im;
40    memset(&im, 0, sizeof im);
41    im.view_off = 0x100000;
42    im.loads = 1;
43    uint8_t entry[MESH_PT_BYTES], ext[MESH_PX_BYTES];
44    mesh_manifest_encode_entry(&m, &im, entry);
45    mesh_manifest_encode_ext(&m, ext);
46    mesh_pt_write_entry(mb, 3, entry, ext, MESH_ST_LOADED);
47    size_t e = mesh_prog_entry(3);
48    CHECK(mesh_mailbox_get(mb, e + MESH_PT_GEN) == 2 && mesh_mailbox_get(mb, e + MESH_PT_STATE) == MESH_ST_LOADED &&
49          mesh_mailbox_get(mb, MESH_H_PROG_SEQ) == 1);
50    CHECK(mesh_mailbox_get(mb, e + MESH_PT_VIEW_OFF) == 0x100000 && mesh_mailbox_get(mb, e + MESH_PT_VIEW_BYTES) == 0x1000);
51    uint8_t x[6];
52    mesh_mailbox_read(mb, mesh_prog_ext(3), x, 6);
53    CHECK(memcmp(x, "tasks\0", 6) == 0);
54    uint32_t s;
55    CHECK(mesh_pt_find(mb, "hello", &s) && s == 3);
56    CHECK(!mesh_pt_find(mb, "hell", &s));
57    uint8_t got[MESH_PT_BYTES];
58    mesh_pt_read_entry(mb, 3, got);
59    CHECK(memcmp(got + MESH_PT_NAME, "hello", 5) == 0);
60    mesh_pt_set_state(mb, 3, MESH_ST_RUNNING);
61    mesh_pt_set_state(mb, 3, MESH_ST_RUNNING);
62    CHECK(mesh_mailbox_get(mb, e + MESH_PT_STATE) == MESH_ST_RUNNING && mesh_mailbox_get(mb, MESH_H_PROG_SEQ) == 2 &&
63          mesh_mailbox_get(mb, e + MESH_PT_GEN) == 2);
64    mesh_pt_clear(mb, 3);
65    CHECK(mesh_mailbox_get(mb, e + MESH_PT_GEN) == 4 && mesh_mailbox_get(mb, e + MESH_PT_STATE) == MESH_ST_EMPTY &&
66          mesh_mailbox_get(mb, e + MESH_PT_VIEW_OFF) == 0);
67    CHECK(!mesh_pt_find(mb, "hello", &s));
68    /* A writer mid-rewrite (odd gen) is waited out; even again: readable. */
69    mesh_mailbox_set(mb, e + MESH_PT_GEN, 5);
70    _Atomic int done = 0;
71    pthread_t th;
72    pthread_create(&th, NULL, reader, &done);
73    struct timespec ts = {0, 5000000};
74    nanosleep(&ts, NULL);
75    CHECK(!atomic_load(&done));
76    mesh_mailbox_publish(mb, e + MESH_PT_GEN, 6);
77    pthread_join(th, NULL);
78    CHECK(atomic_load(&done));
79
80    /* Pipe blocks: written under the seqlock; the flight words left alone; unchanged: no gen bump. */
81    uint8_t pp[MESH_PP_BYTES];
82    memset(pp, 0, sizeof pp);
83    pp[MESH_PP_IN_CAP] = 8;
84    mesh_mailbox_set(mb, mesh_flight_word(3, 0), 9);
85    mesh_pt_write_pipe(mb, 3, pp);
86    CHECK(mesh_mailbox_get(mb, mesh_pipe_entry(3) + MESH_PP_IN_CAP) == 8 && mesh_mailbox_get(mb, mesh_flight_word(3, 0)) == 9);
87    uint32_t g = mesh_mailbox_get(mb, e + MESH_PT_GEN);
88    mesh_pt_write_pipe(mb, 3, pp);
89    CHECK_U(mesh_mailbox_get(mb, e + MESH_PT_GEN), g);
90    CHECK_U(mesh_pt_flight_epoch(mb), 0);
91    CHECK_U(mesh_pt_flight_epoch(mb), 1);
92    mesh_pt_flight_clear(mb, 3);
93    CHECK_U(mesh_pt_flight(mb, 3, 0), 0);
94    mesh_pt_set_hold(mb, 3, true);
95    CHECK_U(mesh_mailbox_get(mb, mesh_pipe_entry(3) + MESH_PP_IN_HOLD), 1);
96    mesh_manifest_free(&m);
97    free(mb.base);
98    return mesh_check_done();
99}