mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-17 07:14:25 +00:00
perf python: Correct pyrf_evsel__read for tool PMUs
Tool PMUs assume that stat's process_counter_values is being used to
read the counters. Specifically they hold onto old values in
evsel->prev_raw_counts and give the cumulative count based off of this
value. Update pyrf_evsel__read to allocate counts and prev_raw_counts,
use evsel__read_counter rather than perf_evsel__read so tool PMUs are
read from not just perf_event_open events, make the returned
pyrf_counts_values contain the delta value rather than the cumulative
value.
Fixes: 739621f657 ("perf python: Add evsel read method")
Signed-off-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250710235126.1086011-12-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#endif
|
||||
#include <perf/mmap.h>
|
||||
#include "callchain.h"
|
||||
#include "counts.h"
|
||||
#include "evlist.h"
|
||||
#include "evsel.h"
|
||||
#include "event.h"
|
||||
@@ -889,12 +890,38 @@ static PyObject *pyrf_evsel__threads(struct pyrf_evsel *pevsel)
|
||||
return (PyObject *)pthread_map;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure evsel's counts and prev_raw_counts are allocated, the latter
|
||||
* used by tool PMUs to compute the cumulative count as expected by
|
||||
* stat's process_counter_values.
|
||||
*/
|
||||
static int evsel__ensure_counts(struct evsel *evsel)
|
||||
{
|
||||
int nthreads, ncpus;
|
||||
|
||||
if (evsel->counts != NULL)
|
||||
return 0;
|
||||
|
||||
nthreads = perf_thread_map__nr(evsel->core.threads);
|
||||
ncpus = perf_cpu_map__nr(evsel->core.cpus);
|
||||
|
||||
evsel->counts = perf_counts__new(ncpus, nthreads);
|
||||
if (evsel->counts == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
evsel->prev_raw_counts = perf_counts__new(ncpus, nthreads);
|
||||
if (evsel->prev_raw_counts == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *pyrf_evsel__read(struct pyrf_evsel *pevsel,
|
||||
PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
struct evsel *evsel = &pevsel->evsel;
|
||||
int cpu = 0, cpu_idx, thread = 0, thread_idx;
|
||||
struct perf_counts_values counts;
|
||||
struct perf_counts_values *old_count, *new_count;
|
||||
struct pyrf_counts_values *count_values = PyObject_New(struct pyrf_counts_values,
|
||||
&pyrf_counts_values__type);
|
||||
|
||||
@@ -915,8 +942,22 @@ static PyObject *pyrf_evsel__read(struct pyrf_evsel *pevsel,
|
||||
thread);
|
||||
return NULL;
|
||||
}
|
||||
perf_evsel__read(&(evsel->core), cpu_idx, thread_idx, &counts);
|
||||
count_values->values = counts;
|
||||
|
||||
if (evsel__ensure_counts(evsel))
|
||||
return PyErr_NoMemory();
|
||||
|
||||
/* Set up pointers to the old and newly read counter values. */
|
||||
old_count = perf_counts(evsel->prev_raw_counts, cpu_idx, thread_idx);
|
||||
new_count = perf_counts(evsel->counts, cpu_idx, thread_idx);
|
||||
/* Update the value in evsel->counts. */
|
||||
evsel__read_counter(evsel, cpu_idx, thread_idx);
|
||||
/* Copy the value and turn it into the delta from old_count. */
|
||||
count_values->values = *new_count;
|
||||
count_values->values.val -= old_count->val;
|
||||
count_values->values.ena -= old_count->ena;
|
||||
count_values->values.run -= old_count->run;
|
||||
/* Save the new count over the old_count for the next read. */
|
||||
*old_count = *new_count;
|
||||
return (PyObject *)count_values;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user