==> 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}