From: Gautam Menghani <gautam@linux.ibm.com>
Add support for perf_counts_values struct to enable the python
bindings to read and return the counter data.
Signed-off-by: Gautam Menghani <gautam@linux.ibm.com>
---
tools/perf/util/python.c | 92 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 91 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index ead3afd2d996..1cbddfe77c7c 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -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, Py_T_ULONG, "Value of event"),
+ counts_values_member_def(ena, Py_T_ULONG, "Time for which enabled"),
+ counts_values_member_def(run, Py_T_ULONG, "Time for which running"),
+ counts_values_member_def(id, Py_T_ULONG, "Unique ID for an event"),
+ counts_values_member_def(lost, Py_T_ULONG, "Num of lost samples"),
+ {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},
+ {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;
--
2.49.0.1101.gccaa498523-goog
On Mon, May 19, 2025 at 12:51:41PM -0700, Ian Rogers wrote:
> From: Gautam Menghani <gautam@linux.ibm.com>
>
> Add support for perf_counts_values struct to enable the python
> bindings to read and return the counter data.
>
> Signed-off-by: Gautam Menghani <gautam@linux.ibm.com>
> ---
> tools/perf/util/python.c | 92 +++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 91 insertions(+), 1 deletion(-)
>
> diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> index ead3afd2d996..1cbddfe77c7c 100644
> --- a/tools/perf/util/python.c
> +++ b/tools/perf/util/python.c
> @@ -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, Py_T_ULONG, "Value of event"),
> + counts_values_member_def(ena, Py_T_ULONG, "Time for which enabled"),
> + counts_values_member_def(run, Py_T_ULONG, "Time for which running"),
> + counts_values_member_def(id, Py_T_ULONG, "Unique ID for an event"),
> + counts_values_member_def(lost, Py_T_ULONG, "Num of lost samples"),
> + {NULL}
> +};
So the above is failing on a aarch64 debian (rpi5):
acme@raspberrypi:~/git/perf-tools-next $ dpkg -S /usr/include/python3.11/structmember.h
libpython3.11-dev:arm64: /usr/include/python3.11/structmember.h
acme@raspberrypi:~/git/perf-tools-next $
Where it only has:
acme@raspberrypi:~/git/perf-tools-next $ grep -r Py_T_ULONG /usr/include/
acme@raspberrypi:~/git/perf-tools-next $ grep -rw Py_T_ULONG /usr/include/
acme@raspberrypi:~/git/perf-tools-next $ grep -rw T_ULONG /usr/include/
/usr/include/python3.11/structmember.h:#define T_ULONG 12
acme@raspberrypi:~/git/perf-tools-next $
while on fedora 42 x86_64:
⬢ [acme@toolbx perf-tools-next]$ grep -rw Py_T_ULONG /usr/include/
/usr/include/python3.13/descrobject.h:#define Py_T_ULONG 12
/usr/include/python3.13/structmember.h:#define T_ULONG Py_T_ULONG
⬢ [acme@toolbx perf-tools-next]$
So I'm making it use the T_ULONG and others as all the other PyMemberDef
arrays in tools/perf/util/python.c, ok?
- Arnaldo
> +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},
> + {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;
> --
> 2.49.0.1101.gccaa498523-goog
On Thu, May 22, 2025 at 3:20 PM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> On Mon, May 19, 2025 at 12:51:41PM -0700, Ian Rogers wrote:
> > From: Gautam Menghani <gautam@linux.ibm.com>
> >
> > Add support for perf_counts_values struct to enable the python
> > bindings to read and return the counter data.
> >
> > Signed-off-by: Gautam Menghani <gautam@linux.ibm.com>
> > ---
> > tools/perf/util/python.c | 92 +++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 91 insertions(+), 1 deletion(-)
> >
> > diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> > index ead3afd2d996..1cbddfe77c7c 100644
> > --- a/tools/perf/util/python.c
> > +++ b/tools/perf/util/python.c
> > @@ -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, Py_T_ULONG, "Value of event"),
> > + counts_values_member_def(ena, Py_T_ULONG, "Time for which enabled"),
> > + counts_values_member_def(run, Py_T_ULONG, "Time for which running"),
> > + counts_values_member_def(id, Py_T_ULONG, "Unique ID for an event"),
> > + counts_values_member_def(lost, Py_T_ULONG, "Num of lost samples"),
> > + {NULL}
> > +};
>
> So the above is failing on a aarch64 debian (rpi5):
>
> acme@raspberrypi:~/git/perf-tools-next $ dpkg -S /usr/include/python3.11/structmember.h
> libpython3.11-dev:arm64: /usr/include/python3.11/structmember.h
> acme@raspberrypi:~/git/perf-tools-next $
>
> Where it only has:
>
> acme@raspberrypi:~/git/perf-tools-next $ grep -r Py_T_ULONG /usr/include/
> acme@raspberrypi:~/git/perf-tools-next $ grep -rw Py_T_ULONG /usr/include/
> acme@raspberrypi:~/git/perf-tools-next $ grep -rw T_ULONG /usr/include/
> /usr/include/python3.11/structmember.h:#define T_ULONG 12
> acme@raspberrypi:~/git/perf-tools-next $
>
> while on fedora 42 x86_64:
>
> ⬢ [acme@toolbx perf-tools-next]$ grep -rw Py_T_ULONG /usr/include/
> /usr/include/python3.13/descrobject.h:#define Py_T_ULONG 12
> /usr/include/python3.13/structmember.h:#define T_ULONG Py_T_ULONG
> ⬢ [acme@toolbx perf-tools-next]$
>
> So I'm making it use the T_ULONG and others as all the other PyMemberDef
> arrays in tools/perf/util/python.c, ok?
The fix makes sense to me. Checking the documentation it seems
Py_T_ULONG is preferred:
https://docs.python.org/3/c-api/structures.html#member-types
perhaps we can add:
```
#ifndef Py_T_ULONG
#define Py_T_ULONG T_ULONG
#endif
```
so that we use the approach matching the documentation while fixing
the RaspberryPi issue.
Thanks,
Ian
> - Arnaldo
>
> > +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},
> > + {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;
> > --
> > 2.49.0.1101.gccaa498523-goog
On Thu, May 22, 2025 at 03:32:44PM -0700, Ian Rogers wrote:
> On Thu, May 22, 2025 at 3:20 PM Arnaldo Carvalho de Melo
> <acme@kernel.org> wrote:
> >
> > On Mon, May 19, 2025 at 12:51:41PM -0700, Ian Rogers wrote:
> > > From: Gautam Menghani <gautam@linux.ibm.com>
> > >
> > > Add support for perf_counts_values struct to enable the python
> > > bindings to read and return the counter data.
> > >
> > > Signed-off-by: Gautam Menghani <gautam@linux.ibm.com>
> > > ---
> > > tools/perf/util/python.c | 92 +++++++++++++++++++++++++++++++++++++++-
> > > 1 file changed, 91 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> > > index ead3afd2d996..1cbddfe77c7c 100644
> > > --- a/tools/perf/util/python.c
> > > +++ b/tools/perf/util/python.c
> > > @@ -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, Py_T_ULONG, "Value of event"),
> > > + counts_values_member_def(ena, Py_T_ULONG, "Time for which enabled"),
> > > + counts_values_member_def(run, Py_T_ULONG, "Time for which running"),
> > > + counts_values_member_def(id, Py_T_ULONG, "Unique ID for an event"),
> > > + counts_values_member_def(lost, Py_T_ULONG, "Num of lost samples"),
> > > + {NULL}
> > > +};
> >
> > So the above is failing on a aarch64 debian (rpi5):
> >
> > acme@raspberrypi:~/git/perf-tools-next $ dpkg -S /usr/include/python3.11/structmember.h
> > libpython3.11-dev:arm64: /usr/include/python3.11/structmember.h
> > acme@raspberrypi:~/git/perf-tools-next $
> >
> > Where it only has:
> >
> > acme@raspberrypi:~/git/perf-tools-next $ grep -r Py_T_ULONG /usr/include/
> > acme@raspberrypi:~/git/perf-tools-next $ grep -rw Py_T_ULONG /usr/include/
> > acme@raspberrypi:~/git/perf-tools-next $ grep -rw T_ULONG /usr/include/
> > /usr/include/python3.11/structmember.h:#define T_ULONG 12
> > acme@raspberrypi:~/git/perf-tools-next $
> >
> > while on fedora 42 x86_64:
> >
> > ⬢ [acme@toolbx perf-tools-next]$ grep -rw Py_T_ULONG /usr/include/
> > /usr/include/python3.13/descrobject.h:#define Py_T_ULONG 12
> > /usr/include/python3.13/structmember.h:#define T_ULONG Py_T_ULONG
> > ⬢ [acme@toolbx perf-tools-next]$
> >
> > So I'm making it use the T_ULONG and others as all the other PyMemberDef
> > arrays in tools/perf/util/python.c, ok?
>
> The fix makes sense to me. Checking the documentation it seems
> Py_T_ULONG is preferred:
> https://docs.python.org/3/c-api/structures.html#member-types
> perhaps we can add:
> ```
> #ifndef Py_T_ULONG
> #define Py_T_ULONG T_ULONG
> #endif
> ```
> so that we use the approach matching the documentation while fixing
> the RaspberryPi issue.
That can be done as a followup, as there are lots of preexisting usage
for struct method definitions.
- Arnaldo
> Thanks,
> Ian
>
> > - Arnaldo
> >
> > > +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},
> > > + {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;
> > > --
> > > 2.49.0.1101.gccaa498523-goog
On Thu, May 22, 2025 at 07:36:31PM -0300, Arnaldo Carvalho de Melo wrote:
> On Thu, May 22, 2025 at 03:32:44PM -0700, Ian Rogers wrote:
> > On Thu, May 22, 2025 at 3:20 PM Arnaldo Carvalho de Melo
> > <acme@kernel.org> wrote:
> > >
> > > On Mon, May 19, 2025 at 12:51:41PM -0700, Ian Rogers wrote:
> > > > From: Gautam Menghani <gautam@linux.ibm.com>
> > > >
> > > > Add support for perf_counts_values struct to enable the python
> > > > bindings to read and return the counter data.
> > > >
> > > > Signed-off-by: Gautam Menghani <gautam@linux.ibm.com>
> > > > ---
> > > > tools/perf/util/python.c | 92 +++++++++++++++++++++++++++++++++++++++-
> > > > 1 file changed, 91 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> > > > index ead3afd2d996..1cbddfe77c7c 100644
> > > > --- a/tools/perf/util/python.c
> > > > +++ b/tools/perf/util/python.c
> > > > @@ -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, Py_T_ULONG, "Value of event"),
> > > > + counts_values_member_def(ena, Py_T_ULONG, "Time for which enabled"),
> > > > + counts_values_member_def(run, Py_T_ULONG, "Time for which running"),
> > > > + counts_values_member_def(id, Py_T_ULONG, "Unique ID for an event"),
> > > > + counts_values_member_def(lost, Py_T_ULONG, "Num of lost samples"),
> > > > + {NULL}
> > > > +};
> > >
> > > So the above is failing on a aarch64 debian (rpi5):
> > >
> > > acme@raspberrypi:~/git/perf-tools-next $ dpkg -S /usr/include/python3.11/structmember.h
> > > libpython3.11-dev:arm64: /usr/include/python3.11/structmember.h
> > > acme@raspberrypi:~/git/perf-tools-next $
> > >
> > > Where it only has:
> > >
> > > acme@raspberrypi:~/git/perf-tools-next $ grep -r Py_T_ULONG /usr/include/
> > > acme@raspberrypi:~/git/perf-tools-next $ grep -rw Py_T_ULONG /usr/include/
> > > acme@raspberrypi:~/git/perf-tools-next $ grep -rw T_ULONG /usr/include/
> > > /usr/include/python3.11/structmember.h:#define T_ULONG 12
> > > acme@raspberrypi:~/git/perf-tools-next $
> > >
> > > while on fedora 42 x86_64:
> > >
> > > ⬢ [acme@toolbx perf-tools-next]$ grep -rw Py_T_ULONG /usr/include/
> > > /usr/include/python3.13/descrobject.h:#define Py_T_ULONG 12
> > > /usr/include/python3.13/structmember.h:#define T_ULONG Py_T_ULONG
> > > ⬢ [acme@toolbx perf-tools-next]$
> > >
> > > So I'm making it use the T_ULONG and others as all the other PyMemberDef
> > > arrays in tools/perf/util/python.c, ok?
> >
> > The fix makes sense to me. Checking the documentation it seems
> > Py_T_ULONG is preferred:
> > https://docs.python.org/3/c-api/structures.html#member-types
> > perhaps we can add:
> > ```
> > #ifndef Py_T_ULONG
> > #define Py_T_ULONG T_ULONG
> > #endif
> > ```
> > so that we use the approach matching the documentation while fixing
> > the RaspberryPi issue.
>
> That can be done as a followup, as there are lots of preexisting usage
> for struct method definitions.
And there is one other issue:
LINK /tmp/build/perf/perf
GEN /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so
/git/perf-6.15.0-rc7/tools/perf/util/python.c:653:7: error: missing field 'type' initializer [-Werror,-Wmissing-field-initializers]
653 | {NULL}
| ^
/git/perf-6.15.0-rc7/tools/perf/util/python.c:695:7: error: missing field 'get' initializer [-Werror,-Wmissing-field-initializers]
695 | {NULL}
| ^
2 errors generated.
error: command 'clang' failed with exit status 1
cp: cannot stat '/tmp/build/perf/python_ext_build/lib/perf*.so': No such file or directory
I'll look at this after dinner.
- Arnaldo
On Thu, May 22, 2025 at 07:37:46PM -0300, Arnaldo Carvalho de Melo wrote:
> On Thu, May 22, 2025 at 07:36:31PM -0300, Arnaldo Carvalho de Melo wrote:
> > On Thu, May 22, 2025 at 03:32:44PM -0700, Ian Rogers wrote:
> > > On Thu, May 22, 2025 at 3:20 PM Arnaldo Carvalho de Melo
> > > <acme@kernel.org> wrote:
> > > >
> > > > On Mon, May 19, 2025 at 12:51:41PM -0700, Ian Rogers wrote:
> > > > > From: Gautam Menghani <gautam@linux.ibm.com>
> > > > >
> > > > > Add support for perf_counts_values struct to enable the python
> > > > > bindings to read and return the counter data.
> > > > >
> > > > > Signed-off-by: Gautam Menghani <gautam@linux.ibm.com>
> > > > > ---
> > > > > tools/perf/util/python.c | 92 +++++++++++++++++++++++++++++++++++++++-
> > > > > 1 file changed, 91 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> > > > > index ead3afd2d996..1cbddfe77c7c 100644
> > > > > --- a/tools/perf/util/python.c
> > > > > +++ b/tools/perf/util/python.c
> > > > > @@ -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, Py_T_ULONG, "Value of event"),
> > > > > + counts_values_member_def(ena, Py_T_ULONG, "Time for which enabled"),
> > > > > + counts_values_member_def(run, Py_T_ULONG, "Time for which running"),
> > > > > + counts_values_member_def(id, Py_T_ULONG, "Unique ID for an event"),
> > > > > + counts_values_member_def(lost, Py_T_ULONG, "Num of lost samples"),
> > > > > + {NULL}
> > > > > +};
> > > >
> > > > So the above is failing on a aarch64 debian (rpi5):
> > > >
> > > > acme@raspberrypi:~/git/perf-tools-next $ dpkg -S /usr/include/python3.11/structmember.h
> > > > libpython3.11-dev:arm64: /usr/include/python3.11/structmember.h
> > > > acme@raspberrypi:~/git/perf-tools-next $
> > > >
> > > > Where it only has:
> > > >
> > > > acme@raspberrypi:~/git/perf-tools-next $ grep -r Py_T_ULONG /usr/include/
> > > > acme@raspberrypi:~/git/perf-tools-next $ grep -rw Py_T_ULONG /usr/include/
> > > > acme@raspberrypi:~/git/perf-tools-next $ grep -rw T_ULONG /usr/include/
> > > > /usr/include/python3.11/structmember.h:#define T_ULONG 12
> > > > acme@raspberrypi:~/git/perf-tools-next $
> > > >
> > > > while on fedora 42 x86_64:
> > > >
> > > > ⬢ [acme@toolbx perf-tools-next]$ grep -rw Py_T_ULONG /usr/include/
> > > > /usr/include/python3.13/descrobject.h:#define Py_T_ULONG 12
> > > > /usr/include/python3.13/structmember.h:#define T_ULONG Py_T_ULONG
> > > > ⬢ [acme@toolbx perf-tools-next]$
> > > >
> > > > So I'm making it use the T_ULONG and others as all the other PyMemberDef
> > > > arrays in tools/perf/util/python.c, ok?
> > >
> > > The fix makes sense to me. Checking the documentation it seems
> > > Py_T_ULONG is preferred:
> > > https://docs.python.org/3/c-api/structures.html#member-types
> > > perhaps we can add:
> > > ```
> > > #ifndef Py_T_ULONG
> > > #define Py_T_ULONG T_ULONG
> > > #endif
> > > ```
> > > so that we use the approach matching the documentation while fixing
> > > the RaspberryPi issue.
> >
> > That can be done as a followup, as there are lots of preexisting usage
> > for struct method definitions.
>
> And there is one other issue:
>
> LINK /tmp/build/perf/perf
> GEN /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so
> /git/perf-6.15.0-rc7/tools/perf/util/python.c:653:7: error: missing field 'type' initializer [-Werror,-Wmissing-field-initializers]
> 653 | {NULL}
> | ^
> /git/perf-6.15.0-rc7/tools/perf/util/python.c:695:7: error: missing field 'get' initializer [-Werror,-Wmissing-field-initializers]
> 695 | {NULL}
> | ^
> 2 errors generated.
> error: command 'clang' failed with exit status 1
> cp: cannot stat '/tmp/build/perf/python_ext_build/lib/perf*.so': No such file or directory
>
>
> I'll look at this after dinner.
Doing the same thing as for all the other PyMemberDef arrays makes it
pass that hurdle:
⬢ [acme@toolbx perf-tools-next]$ git diff
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index cb5a76674a5f1078..60ff12e90b91f97c 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -650,7 +650,7 @@ static PyMemberDef pyrf_counts_values_members[] = {
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"),
- {NULL}
+ { .name = NULL, },
};
static PyObject *pyrf_counts_values_get_values(struct pyrf_counts_values *self, void *closure)
Then there is:
GEN /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so
/git/perf-6.15.0-rc7/tools/perf/util/python.c:695:8: error: missing field 'get' initializer [-Werror,-Wmissing-field-initializers]
695 | {NULL,}
| ^
1 error generated.
error: command 'clang' failed with exit status 1
I tried with the ending NULL, but it wasn't enough, so I'm going with:
⬢ [acme@toolbx perf-tools-next]$ git diff
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 5fa113daf4488120..21e2da1ec0c6342c 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -692,7 +692,7 @@ static int pyrf_counts_values_set_values(struct pyrf_counts_values *self, PyObje
static PyGetSetDef pyrf_counts_values_getset[] = {
{"values", (getter)pyrf_counts_values_get_values, (setter)pyrf_counts_values_set_values,
"Name field", NULL},
- {NULL,}
+ { .name = NULL, },
};
static PyTypeObject pyrf_counts_values__type = {
⬢ [acme@toolbx perf-tools-next]$
- Arnaldo
Hi Arnaldo, Thanks for fixing this, I should have looked at the other initializations in the file. Thanks, Gautam
On Mon, May 19, 2025 at 12:51:41PM -0700, Ian Rogers wrote:
> From: Gautam Menghani <gautam@linux.ibm.com>
>
> Add support for perf_counts_values struct to enable the python
> bindings to read and return the counter data.
This (and another one in this series) are coming from Ian, that didn't
modify them, so we need a Signed-off-by: Ian, as per:
Documentation/process/submitting-patches.rst
---
Any further SoBs (Signed-off-by:'s) following the author's SoB are from
people handling and transporting the patch, but were not involved in its
development. SoB chains should reflect the **real** route a patch took
as it was propagated to the maintainers and ultimately to Linus, with
the first SoB entry signalling primary authorship of a single author.
---
I'm adding them to my local branch, please ack this,
Thanks,
- Arnaldo
> Signed-off-by: Gautam Menghani <gautam@linux.ibm.com>
> ---
> tools/perf/util/python.c | 92 +++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 91 insertions(+), 1 deletion(-)
>
> diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> index ead3afd2d996..1cbddfe77c7c 100644
> --- a/tools/perf/util/python.c
> +++ b/tools/perf/util/python.c
> @@ -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, Py_T_ULONG, "Value of event"),
> + counts_values_member_def(ena, Py_T_ULONG, "Time for which enabled"),
> + counts_values_member_def(run, Py_T_ULONG, "Time for which running"),
> + counts_values_member_def(id, Py_T_ULONG, "Unique ID for an event"),
> + counts_values_member_def(lost, Py_T_ULONG, "Num of lost samples"),
> + {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},
> + {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;
> --
> 2.49.0.1101.gccaa498523-goog
On Wed, May 21, 2025 at 6:20 AM Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
>
> On Mon, May 19, 2025 at 12:51:41PM -0700, Ian Rogers wrote:
> > From: Gautam Menghani <gautam@linux.ibm.com>
> >
> > Add support for perf_counts_values struct to enable the python
> > bindings to read and return the counter data.
>
> This (and another one in this series) are coming from Ian, that didn't
> modify them, so we need a Signed-off-by: Ian, as per:
>
> Documentation/process/submitting-patches.rst
>
> ---
> Any further SoBs (Signed-off-by:'s) following the author's SoB are from
> people handling and transporting the patch, but were not involved in its
> development. SoB chains should reflect the **real** route a patch took
> as it was propagated to the maintainers and ultimately to Linus, with
> the first SoB entry signalling primary authorship of a single author.
> ---
>
> I'm adding them to my local branch, please ack this,
Ack. Thanks and sorry for the work, will try to do better next time.
Ian
> Thanks,
>
> - Arnaldo
>
> > Signed-off-by: Gautam Menghani <gautam@linux.ibm.com>
> > ---
> > tools/perf/util/python.c | 92 +++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 91 insertions(+), 1 deletion(-)
> >
> > diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
> > index ead3afd2d996..1cbddfe77c7c 100644
> > --- a/tools/perf/util/python.c
> > +++ b/tools/perf/util/python.c
> > @@ -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, Py_T_ULONG, "Value of event"),
> > + counts_values_member_def(ena, Py_T_ULONG, "Time for which enabled"),
> > + counts_values_member_def(run, Py_T_ULONG, "Time for which running"),
> > + counts_values_member_def(id, Py_T_ULONG, "Unique ID for an event"),
> > + counts_values_member_def(lost, Py_T_ULONG, "Num of lost samples"),
> > + {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},
> > + {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;
> > --
> > 2.49.0.1101.gccaa498523-goog
On Wed, May 21, 2025 at 06:56:44AM -0700, Ian Rogers wrote: > On Wed, May 21, 2025 at 6:20 AM Arnaldo Carvalho de Melo > <acme@kernel.org> wrote: > > > > On Mon, May 19, 2025 at 12:51:41PM -0700, Ian Rogers wrote: > > > From: Gautam Menghani <gautam@linux.ibm.com> > > > > > > Add support for perf_counts_values struct to enable the python > > > bindings to read and return the counter data. > > > > This (and another one in this series) are coming from Ian, that didn't > > modify them, so we need a Signed-off-by: Ian, as per: > > > > Documentation/process/submitting-patches.rst > > > > --- > > Any further SoBs (Signed-off-by:'s) following the author's SoB are from > > people handling and transporting the patch, but were not involved in its > > development. SoB chains should reflect the **real** route a patch took > > as it was propagated to the maintainers and ultimately to Linus, with > > the first SoB entry signalling primary authorship of a single author. > > --- > > > > I'm adding them to my local branch, please ack this, > > Ack. Thanks and sorry for the work, will try to do better next time. Thanks for confirming, - Arnaldo
© 2016 - 2025 Red Hat, Inc.