]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf python: Add support for 'struct perf_counts_values' to return counter data
authorGautam Menghani <gautam@linux.ibm.com>
Mon, 19 May 2025 19:51:41 +0000 (12:51 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 23 May 2025 01:23:52 +0000 (22:23 -0300)
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>
tools/perf/util/python.c

index ead3afd2d996e46a56a2087bd469c06a8ef550ab..21e2da1ec0c6342cd35b272dcdaf3fbc0b53df40 100644 (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;