==> src/host_block.c <==1/* The host status block under a mutex. */
2#include "mesh/host_block.h"
3#include "mesh/abi/host_status.h"
4#include "mesh/chan.h"
5
6#include <string.h>
7
8void mesh_host_block_init(mesh_host_block *h) {
9 memset(h->block, 0, sizeof h->block);
10 pthread_mutex_init(&h->mu, NULL);
11 h->started_us = mesh_mono_us();
12 mesh_net_counters_init(&h->net);
13}
14
15static void put(mesh_host_block *h, size_t off, const void *b, size_t n) {
16 pthread_mutex_lock(&h->mu);
17 memcpy(h->block + off, b, n);
18 pthread_mutex_unlock(&h->mu);
19}
20
21static void le32(uint8_t b[4], uint32_t v) { for (int i = 0; i < 4; i++) b[i] = (uint8_t)(v >> (8 * i)); }
22
23void mesh_host_block_set_u32(mesh_host_block *h, size_t off, uint32_t v) {
24 uint8_t b[4];
25 le32(b, v);
26 put(h, off, b, 4);
27}
28
29void mesh_host_block_set_f32(mesh_host_block *h, size_t off, float v) {
30 uint32_t u;
31 memcpy(&u, &v, 4);
32 mesh_host_block_set_u32(h, off, u);
33}
34
35void mesh_host_block_set_u64(mesh_host_block *h, size_t off, uint64_t v) {
36 uint8_t b[8];
37 for (int i = 0; i < 8; i++) b[i] = (uint8_t)(v >> (8 * i));
38 put(h, off, b, 8);
39}
40
41void mesh_host_block_set_many(mesh_host_block *h, const mesh_host_field *f, size_t n) {
42 pthread_mutex_lock(&h->mu);
43 for (size_t i = 0; i < n; i++) memcpy(h->block + f[i].off, f[i].bytes, f[i].len);
44 pthread_mutex_unlock(&h->mu);
45}
46
47static uint32_t get32(const uint8_t *b) { return (uint32_t)b[0] | (uint32_t)b[1] << 8 | (uint32_t)b[2] << 16 | (uint32_t)b[3] << 24; }
48
49void mesh_host_block_add_u32(mesh_host_block *h, size_t off, uint32_t n) {
50 pthread_mutex_lock(&h->mu);
51 le32(h->block + off, get32(h->block + off) + n);
52 pthread_mutex_unlock(&h->mu);
53}
54
55void mesh_host_block_set_str(mesh_host_block *h, size_t off, size_t len, const char *s) {
56 uint8_t b[256];
57 size_t k = strlen(s);
58 if (len > sizeof b) len = sizeof b;
59 if (k > len - 1) k = len - 1;
60 memset(b, 0, len);
61 memcpy(b, s, k);
62 put(h, off, b, len);
63}
64
65uint64_t mesh_host_block_uptime_ms(const mesh_host_block *h) { return (uint64_t)((mesh_mono_us() - h->started_us) / 1000); }
66
67uint32_t mesh_host_block_get_u32(mesh_host_block *h, size_t off) {
68 pthread_mutex_lock(&h->mu);
69 uint32_t v = get32(h->block + off);
70 pthread_mutex_unlock(&h->mu);
71 return v;
72}
73
74float mesh_host_block_get_f32(mesh_host_block *h, size_t off) {
75 uint32_t u = mesh_host_block_get_u32(h, off);
76 float f;
77 memcpy(&f, &u, 4);
78 return f;
79}
80
81void mesh_host_block_bytes(mesh_host_block *h, uint8_t out[MESH_SNAP_HOST]) {
82 pthread_mutex_lock(&h->mu);
83 memcpy(out, h->block, MESH_SNAP_HOST);
84 pthread_mutex_unlock(&h->mu);
85 uint64_t up = mesh_host_block_uptime_ms(h);
86 for (int i = 0; i < 8; i++) out[MESH_S_UPTIME_MS + (size_t)i] = (uint8_t)(up >> (8 * i));
87 mesh_net_counters_fill(&h->net, out);
88}