perf python: Add support for 'struct perf_counts_values' to return counter data

Add support for the perf_counts_values struct to enable the python
bindings to read and return the counter data.

Committer notes:

Use T_ULONG instead of Py_T_ULONG, as all the other PyMemberDef arrays,
fixing the build with older python3 versions.

Use { .name = NULL, } to finish the new PyMemberDef
pyrf_counts_values_members array, again as the other arrays to please
some clang versions, ditto for PyGetSetDef.

Signed-off-by: Gautam Menghani <gautam@linux.ibm.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20250519195148.1708988-5-irogers@google.com
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Gautam Menghani
2025-05-19 12:51:41 -07:00
committed by Arnaldo Carvalho de Melo
parent 0589aff473
commit 3b4991dcb4

View File

@@ -626,6 +626,92 @@ static int pyrf_thread_map__setup_types(void)
return PyType_Ready(&pyrf_thread_map__type);
}
struct pyrf_counts_values {
PyObject_HEAD
struct perf_counts_values values;
};
static const char pyrf_counts_values__doc[] = PyDoc_STR("perf counts values object.");
static void pyrf_counts_values__delete(struct pyrf_counts_values *pcounts_values)
{
Py_TYPE(pcounts_values)->tp_free((PyObject *)pcounts_values);
}
#define counts_values_member_def(member, ptype, help) \
{ #member, ptype, \
offsetof(struct pyrf_counts_values, values.member), \
0, help }
static PyMemberDef pyrf_counts_values_members[] = {
counts_values_member_def(val, T_ULONG, "Value of event"),
counts_values_member_def(ena, T_ULONG, "Time for which enabled"),
counts_values_member_def(run, T_ULONG, "Time for which running"),
counts_values_member_def(id, T_ULONG, "Unique ID for an event"),
counts_values_member_def(lost, T_ULONG, "Num of lost samples"),
{ .name = NULL, },
};
static PyObject *pyrf_counts_values_get_values(struct pyrf_counts_values *self, void *closure)
{
PyObject *vals = PyList_New(5);
if (!vals)
return NULL;
for (int i = 0; i < 5; i++)
PyList_SetItem(vals, i, PyLong_FromLong(self->values.values[i]));
return vals;
}
static int pyrf_counts_values_set_values(struct pyrf_counts_values *self, PyObject *list,
void *closure)
{
Py_ssize_t size;
PyObject *item = NULL;
if (!PyList_Check(list)) {
PyErr_SetString(PyExc_TypeError, "Value assigned must be a list");
return -1;
}
size = PyList_Size(list);
for (Py_ssize_t i = 0; i < size; i++) {
item = PyList_GetItem(list, i);
if (!PyLong_Check(item)) {
PyErr_SetString(PyExc_TypeError, "List members should be numbers");
return -1;
}
self->values.values[i] = PyLong_AsLong(item);
}
return 0;
}
static PyGetSetDef pyrf_counts_values_getset[] = {
{"values", (getter)pyrf_counts_values_get_values, (setter)pyrf_counts_values_set_values,
"Name field", NULL},
{ .name = NULL, },
};
static PyTypeObject pyrf_counts_values__type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "perf.counts_values",
.tp_basicsize = sizeof(struct pyrf_counts_values),
.tp_dealloc = (destructor)pyrf_counts_values__delete,
.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
.tp_doc = pyrf_counts_values__doc,
.tp_members = pyrf_counts_values_members,
.tp_getset = pyrf_counts_values_getset,
};
static int pyrf_counts_values__setup_types(void)
{
pyrf_counts_values__type.tp_new = PyType_GenericNew;
return PyType_Ready(&pyrf_counts_values__type);
}
struct pyrf_evsel {
PyObject_HEAD
@@ -1475,7 +1561,8 @@ PyMODINIT_FUNC PyInit_perf(void)
pyrf_evlist__setup_types() < 0 ||
pyrf_evsel__setup_types() < 0 ||
pyrf_thread_map__setup_types() < 0 ||
pyrf_cpu_map__setup_types() < 0)
pyrf_cpu_map__setup_types() < 0 ||
pyrf_counts_values__setup_types() < 0)
return module;
/* The page_size is placed in util object. */
@@ -1520,6 +1607,9 @@ PyMODINIT_FUNC PyInit_perf(void)
Py_INCREF(&pyrf_cpu_map__type);
PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
Py_INCREF(&pyrf_counts_values__type);
PyModule_AddObject(module, "counts_values", (PyObject *)&pyrf_counts_values__type);
dict = PyModule_GetDict(module);
if (dict == NULL)
goto error;