-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutils.h
More file actions
76 lines (63 loc) · 2.71 KB
/
Copy pathutils.h
File metadata and controls
76 lines (63 loc) · 2.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/* SPDX-License-Identifier: MIT */
/* Copyright (c) 2026 MoatLab, Virginia Tech. */
/* utils.h — small stateless utility functions. */
#ifndef PACT_UTILS_H
#define PACT_UTILS_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <unistd.h> /* getpid */
#include "pact.h" /* fast_prng_t */
#include "tsc.h" /* rdtsc */
/* Relaxed-memory-order atomic counter primitives.
*
* Used for cross-thread statistics counters where the only requirement is
* "don't tear / don't lose updates" — no ordering or release/acquire
* pairing with other state. Relaxed is the right choice and yields one
* locked instruction on x86 (`lock xadd`).
*
* Type-generic macros (function-like) — work for any integer pointer the
* compiler's __atomic_* intrinsics accept (uint32_t / uint64_t / size_t).
* Parens around `p` / `n` as the standard macro-safety idiom. */
#define atomic_inc_relaxed(p) __atomic_add_fetch((p), 1, __ATOMIC_RELAXED)
#define atomic_add_relaxed(p, n) __atomic_add_fetch((p), (n), __ATOMIC_RELAXED)
/* Fast thread-safe PRNG (xorshift64).
* Inline for hot-path use (called from PEBS sample processing). */
static inline uint64_t fast_prng_next(fast_prng_t *prng)
{
uint64_t x = prng->state;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
prng->state = x;
return x;
}
static inline void fast_prng_init(fast_prng_t *prng)
{
/* PID + TSC seeding (single-threaded, no pthread). */
prng->state = ((uint64_t)getpid() << 32) ^ rdtsc();
if (prng->state == 0) {
prng->state = 1; /* avoid zero state */
}
}
/* qsort comparator for uint64_t (ascending). */
int pact_compare_uint64(const void *a, const void *b);
/* Compute `percentile` (e.g., 50.0 for median) of `samples`. Sorts in-place.
* Returns 0 if count==0; uses linear interpolation between adjacent values. */
uint64_t pact_calculate_percentile(uint64_t *samples, size_t count, double percentile);
#ifdef PACT_CGROUP_SUPPORT
/* Read cumulative pgsteal_kswapd + pgsteal_direct from cgroup memory.stat.
* Returns 0 on any error (missing file, parse failure). */
uint64_t pact_read_cgroup_demotion_stats(const char *cgroup_path);
#endif
/* Check if all workload target PIDs have exited.
* Returns true only if at least one workload is configured AND all have died.
* Uses kill(pid, 0) probe — treats EPERM as "still alive". */
bool pact_check_all_targets_exited(pact_context_t *ctx);
/* TSC frequency detection: sleeps 10ms and measures TSC delta against
* CLOCK_MONOTONIC. Returns Hz. Used once at init. */
uint64_t pact_detect_tsc_frequency(void);
/* Pin the calling thread to a specific CPU via sched_setaffinity.
* Returns 0 on success, -1 on failure (logged via log_error). */
int pact_pin_to_cpu(int cpu);
#endif /* PACT_UTILS_H */