-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathperf.c
More file actions
107 lines (92 loc) · 3.29 KB
/
Copy pathperf.c
File metadata and controls
107 lines (92 loc) · 3.29 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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/* SPDX-License-Identifier: MIT */
/* Copyright (c) 2026 MoatLab, Virginia Tech. */
/* perf.c — perf event setup at init time.
*
* setup_* helpers (setup_counting_event, setup_pebs_event,
* setup_pmu_cha_perf_events, setup_workload_counting_events,
* start_pmu_perf_events, discover_cha_pmus) live in pmu.c — included via pmu.h.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
#include "pact.h"
#include "config.h" /* PACT_PEBS_SAMPLE_PERIOD */
#include "pmu.h"
#include "perf.h"
#ifndef PEBS_SAMPLE_PERIOD
#define PEBS_SAMPLE_PERIOD PACT_PEBS_SAMPLE_PERIOD
#endif
void init_perf_event(perf_event_t *perf_event)
{
perf_event->fd = -1;
perf_event->id = -1;
perf_event->value = 0;
perf_event->time_enabled = 0;
perf_event->time_running = 0;
}
void init_per_cpu_state(per_cpu_state_t *cpu_state)
{
cpu_state->cpu_id = -1;
cpu_state->fd_pebs = -1;
init_perf_event(&cpu_state->leader);
cpu_state->pebs_sampling_period = PEBS_SAMPLE_PERIOD; /* may be overridden in pact_init */
cpu_state->pebs_mmap = NULL;
}
static void setup_one_cpu_perf(per_cpu_state_t *cs, bool skip)
{
/* Dummy leader owns the perf mmap that sampling events attach to —
* must be created before setup_pebs_event(). */
if (setup_dummy_leader_event(&cs->leader, -1, cs->cpu_id) < 0) {
log_warning("perf_events", "Skipping CPU %d (dummy leader failed — CPU offline?)",
cs->cpu_id);
cs->fd_pebs = -1;
return;
}
if (skip) {
cs->fd_pebs = -1;
} else {
int r = setup_pebs_event(cs, -1, cs->cpu_id);
if (r < 0) {
log_warning("perf_events", "PEBS setup failed on CPU %d", cs->cpu_id);
cs->fd_pebs = -1;
}
}
}
static int count_configured_pebs_cpus(pact_context_t *pact, int nr_cpus)
{
int n = 0;
for (int cpu = 0; cpu < nr_cpus; cpu++) {
per_cpu_state_t *cpu_state = &pact->cpu_states[cpu];
if (cpu_state->fd_pebs >= 0 && cpu_state->pebs_mmap) {
n++;
}
}
return n;
}
void setup_pact_perf_events(pact_context_t *pact)
{
pact_workload_t *wl = pact->workload;
/* Discover and configure CHA PMUs for the workload. */
discover_cha_pmus(wl->cha_pmus, &wl->nr_cha, wl->cpu_mask);
setup_pmu_cha_perf_events(wl->cha_pmus, &wl->nr_cha);
log_info("setup_pact_perf_events", "Workload (PID %d): Discovered %d CHAs", wl->target_pid,
wl->nr_cha);
for (int cpu = 0; cpu < pact->nr_all_cpus; cpu++) {
per_cpu_state_t *cpu_state = &pact->cpu_states[cpu];
setup_one_cpu_perf(cpu_state, /*skip=*/false);
}
/* Per-workload counting (single per-PID inherit fd per event) — kernel
* attributes LLC misses across all child threads of the workload. */
setup_workload_counting_events(wl);
int configured = count_configured_pebs_cpus(pact, pact->nr_all_cpus);
if (configured == 0) {
log_error("setup_pact_perf_events",
"PEBS not set up on any CPU! Check permissions and CPU support.");
} else {
log_info("setup_pact_perf_events", "PEBS set up on %d CPUs", configured);
log_info("setup_pact_perf_events",
"PEBS validation will occur when workload generates LLC misses");
}
start_pmu_perf_events(pact);
}