skip to content
==> src/cpuuse.c <==
1/* cpuuse.rs: per-slot counters and the per-thread meter. */
2#include "mesh/cpuuse.h"
3
4#include <time.h>
5
6mesh_slot_use mesh_cpuuse_slots[MESH_PROG_SLOTS];
7_Atomic uint32_t mesh_cpuuse_workers, mesh_cpuuse_worker_spawns, mesh_cpuuse_worker_crashes;
8
9void mesh_slot_use_add_cpu(mesh_slot_use *u, uint64_t ns) { atomic_fetch_add_explicit(&u->cpu_ns, ns, memory_order_relaxed); }
10
11void mesh_slot_use_add_rss(mesh_slot_use *u, int64_t d) {
12    if (d >= 0) {
13        atomic_fetch_add_explicit(&u->rss, (uint64_t)d, memory_order_relaxed);
14        return;
15    }
16    uint64_t sub = (uint64_t)(-d), cur = atomic_load_explicit(&u->rss, memory_order_relaxed);
17    while (!atomic_compare_exchange_weak_explicit(&u->rss, &cur, cur > sub ? cur - sub : 0, memory_order_relaxed,
18                                                  memory_order_relaxed)) {
19    }
20}
21
22void mesh_slot_use_get(mesh_slot_use *u, uint64_t *cpu_ns, uint64_t *rss, uint32_t *units) {
23    *cpu_ns = atomic_load_explicit(&u->cpu_ns, memory_order_relaxed);
24    *rss = atomic_load_explicit(&u->rss, memory_order_relaxed);
25    *units = atomic_load_explicit(&u->units, memory_order_relaxed);
26}
27
28uint64_t mesh_thread_cpu_ns(void) {
29    struct timespec ts = {0, 0};
30    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
31    return (uint64_t)ts.tv_sec * 1000000000u + (uint64_t)ts.tv_nsec;
32}
33
34void mesh_meter_start(mesh_meter *m, uint32_t slot) {
35    atomic_fetch_add_explicit(&mesh_cpuuse_slots[slot].units, 1, memory_order_relaxed);
36    *m = (mesh_meter){slot, mesh_thread_cpu_ns(), 0};
37}
38
39void mesh_meter_tick(mesh_meter *m, uint64_t rss) {
40    uint64_t now = mesh_thread_cpu_ns();
41    mesh_slot_use *u = &mesh_cpuuse_slots[m->slot];
42    mesh_slot_use_add_cpu(u, now > m->cpu ? now - m->cpu : 0);
43    m->cpu = now;
44    if (rss != m->rss) {
45        mesh_slot_use_add_rss(u, (int64_t)rss - (int64_t)m->rss);
46        m->rss = rss;
47    }
48}
49
50void mesh_meter_end(mesh_meter *m) {
51    mesh_slot_use *u = &mesh_cpuuse_slots[m->slot];
52    uint64_t now = mesh_thread_cpu_ns();
53    mesh_slot_use_add_cpu(u, now > m->cpu ? now - m->cpu : 0);
54    mesh_slot_use_add_rss(u, -(int64_t)m->rss);
55    atomic_fetch_sub_explicit(&u->units, 1, memory_order_relaxed);
56}