==> tests/harness.h <==1/* A slot of a test mailbox, its ticket ring from the host side, and its nodes
2 * on a thread (exec's mesh_worker_run_nodes), for native programs' tests. */
3#ifndef NATIVE_TEST_HARNESS_H
4#define NATIVE_TEST_HARNESS_H
5#include "mesh/abi/control_block.h"
6#include "mesh/abi/ops.h"
7#include "mesh/abi/pipe_table.h"
8#include "mesh/abi/program_table.h"
9#include "mesh/abi/ring.h"
10#include "mesh/abi/pipe_hash.h"
11#include "mesh/check.h"
12#include "mesh/mailbox.h"
13#include "mesh/worker_node.h"
14
15#include <pthread.h>
16#include <sched.h>
17#include <stdlib.h>
18#include <string.h>
19#include <time.h>
20
21static inline void h_install(mesh_mailbox mb, uint32_t s, const char *name, uint32_t nodes, uint32_t view_off, uint32_t view_bytes) {
22 size_t e = mesh_prog_entry(s);
23 const uint32_t kv[][2] = {{MESH_PT_VIEW_OFF, view_off}, {MESH_PT_VIEW_BYTES, view_bytes}, {MESH_PT_NODES, nodes}, {MESH_PT_STATE, MESH_ST_RUNNING}};
24 for (size_t i = 0; i < 4; i++) mesh_mailbox_set(mb, e + kv[i][0], kv[i][1]);
25 uint8_t n[16] = {0};
26 memcpy(n, name, strlen(name));
27 mesh_mailbox_write(mb, e + MESH_PT_NAME, n, 16, 16);
28}
29static inline void h_inbox(mesh_mailbox mb, uint32_t s, uint32_t off, uint32_t cap, uint32_t rec, const char *type) {
30 size_t p = mesh_pipe_entry(s);
31 mesh_mailbox_set(mb, p + MESH_PP_IN_OFF, off);
32 mesh_mailbox_set(mb, p + MESH_PP_IN_CAP, cap);
33 mesh_mailbox_set(mb, p + MESH_PP_IN_REC, rec);
34 mesh_mailbox_set(mb, p + MESH_PP_IN_TYPE, mesh_pipe_type_hash((const uint8_t *)type, strlen(type)));
35}
36static inline void h_feed(mesh_mailbox mb, uint32_t from, uint32_t to) {
37 size_t p = mesh_pipe_entry(from);
38 mesh_mailbox_set(mb, p + MESH_PP_FEEDS_MASK, mesh_mailbox_get(mb, p + MESH_PP_FEEDS_MASK) | 1u << to);
39}
40
41typedef struct {
42 mesh_mailbox mb;
43 uint32_t slot, next;
44 mesh_worker_program prog;
45 atomic_bool stop;
46 pthread_t th;
47} h_slot;
48
49static inline void *h_runner(void *a) {
50 h_slot *h = a;
51 mesh_worker_run_nodes(h->mb, h->slot, &h->prog, &h->stop);
52 return NULL;
53}
54static inline void h_start(h_slot *h) {
55 atomic_store(&h->stop, false);
56 pthread_create(&h->th, NULL, h_runner, h);
57}
58static inline void h_stop(h_slot *h) {
59 mesh_mailbox_publish(h->mb, mesh_prog_ctl(h->slot) + MESH_P_SHUTDOWN, MESH_SHUTDOWN_HALT);
60 pthread_join(h->th, NULL);
61}
62static inline uint32_t h_call(h_slot *h, uint32_t op, uint32_t arg) {
63 uint32_t t = h->next++;
64 size_t c = mesh_prog_ctl(h->slot), e = c + MESH_P_RING + MESH_ENTRY_BYTES * (t % MESH_PROG_RING), k = t % MESH_PROG_RESULTS;
65 mesh_mailbox_set(h->mb, e + MESH_E_OP, op);
66 mesh_mailbox_set(h->mb, e + MESH_E_ARG, arg);
67 mesh_mailbox_set(h->mb, e + MESH_E_SLOT, (uint32_t)k);
68 mesh_mailbox_publish(h->mb, e + MESH_E_SEQ, t + 1);
69 struct timespec t0, now;
70 clock_gettime(CLOCK_MONOTONIC, &t0);
71 while (mesh_mailbox_get(h->mb, c + MESH_P_MARKS + 4 * k) != t + 1) {
72 clock_gettime(CLOCK_MONOTONIC, &now);
73 if (now.tv_sec - t0.tv_sec > 60) { fprintf(stderr, "ticket %u never completed\n", t); abort(); }
74 sched_yield();
75 }
76 return mesh_mailbox_get(h->mb, c + MESH_P_RESULTS + 4 * k);
77}
78#endif