Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Gautam Menghani and committed by
Arnaldo Carvalho de Melo
3b4991dc 0589aff4

+91 -1
+91 -1
tools/perf/util/python.c
··· 626 626 return PyType_Ready(&pyrf_thread_map__type); 627 627 } 628 628 629 + struct pyrf_counts_values { 630 + PyObject_HEAD 631 + 632 + struct perf_counts_values values; 633 + }; 634 + 635 + static const char pyrf_counts_values__doc[] = PyDoc_STR("perf counts values object."); 636 + 637 + static void pyrf_counts_values__delete(struct pyrf_counts_values *pcounts_values) 638 + { 639 + Py_TYPE(pcounts_values)->tp_free((PyObject *)pcounts_values); 640 + } 641 + 642 + #define counts_values_member_def(member, ptype, help) \ 643 + { #member, ptype, \ 644 + offsetof(struct pyrf_counts_values, values.member), \ 645 + 0, help } 646 + 647 + static PyMemberDef pyrf_counts_values_members[] = { 648 + counts_values_member_def(val, T_ULONG, "Value of event"), 649 + counts_values_member_def(ena, T_ULONG, "Time for which enabled"), 650 + counts_values_member_def(run, T_ULONG, "Time for which running"), 651 + counts_values_member_def(id, T_ULONG, "Unique ID for an event"), 652 + counts_values_member_def(lost, T_ULONG, "Num of lost samples"), 653 + { .name = NULL, }, 654 + }; 655 + 656 + static PyObject *pyrf_counts_values_get_values(struct pyrf_counts_values *self, void *closure) 657 + { 658 + PyObject *vals = PyList_New(5); 659 + 660 + if (!vals) 661 + return NULL; 662 + for (int i = 0; i < 5; i++) 663 + PyList_SetItem(vals, i, PyLong_FromLong(self->values.values[i])); 664 + 665 + return vals; 666 + } 667 + 668 + static int pyrf_counts_values_set_values(struct pyrf_counts_values *self, PyObject *list, 669 + void *closure) 670 + { 671 + Py_ssize_t size; 672 + PyObject *item = NULL; 673 + 674 + if (!PyList_Check(list)) { 675 + PyErr_SetString(PyExc_TypeError, "Value assigned must be a list"); 676 + return -1; 677 + } 678 + 679 + size = PyList_Size(list); 680 + for (Py_ssize_t i = 0; i < size; i++) { 681 + item = PyList_GetItem(list, i); 682 + if (!PyLong_Check(item)) { 683 + PyErr_SetString(PyExc_TypeError, "List members should be numbers"); 684 + return -1; 685 + } 686 + self->values.values[i] = PyLong_AsLong(item); 687 + } 688 + 689 + return 0; 690 + } 691 + 692 + static PyGetSetDef pyrf_counts_values_getset[] = { 693 + {"values", (getter)pyrf_counts_values_get_values, (setter)pyrf_counts_values_set_values, 694 + "Name field", NULL}, 695 + { .name = NULL, }, 696 + }; 697 + 698 + static PyTypeObject pyrf_counts_values__type = { 699 + PyVarObject_HEAD_INIT(NULL, 0) 700 + .tp_name = "perf.counts_values", 701 + .tp_basicsize = sizeof(struct pyrf_counts_values), 702 + .tp_dealloc = (destructor)pyrf_counts_values__delete, 703 + .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 704 + .tp_doc = pyrf_counts_values__doc, 705 + .tp_members = pyrf_counts_values_members, 706 + .tp_getset = pyrf_counts_values_getset, 707 + }; 708 + 709 + static int pyrf_counts_values__setup_types(void) 710 + { 711 + pyrf_counts_values__type.tp_new = PyType_GenericNew; 712 + return PyType_Ready(&pyrf_counts_values__type); 713 + } 714 + 629 715 struct pyrf_evsel { 630 716 PyObject_HEAD 631 717 ··· 1561 1475 pyrf_evlist__setup_types() < 0 || 1562 1476 pyrf_evsel__setup_types() < 0 || 1563 1477 pyrf_thread_map__setup_types() < 0 || 1564 - pyrf_cpu_map__setup_types() < 0) 1478 + pyrf_cpu_map__setup_types() < 0 || 1479 + pyrf_counts_values__setup_types() < 0) 1565 1480 return module; 1566 1481 1567 1482 /* The page_size is placed in util object. */ ··· 1606 1519 1607 1520 Py_INCREF(&pyrf_cpu_map__type); 1608 1521 PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type); 1522 + 1523 + Py_INCREF(&pyrf_counts_values__type); 1524 + PyModule_AddObject(module, "counts_values", (PyObject *)&pyrf_counts_values__type); 1609 1525 1610 1526 dict = PyModule_GetDict(module); 1611 1527 if (dict == NULL)