From nobody Sun Dec 14 20:29:46 2025 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB117136658; Thu, 13 Mar 2025 07:52:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741852324; cv=none; b=bxgZl9e90xFH0LN52vsSaFOrToa32YizJxO9nd9teByMVOBuUfm+Bj/9PEXu3cheJelDb1/uTUcUjdAVToxOTgGNg9CCy4FM6T9ZUDtHY7HFZ/qdowoy91Xv+GIFtHxe0OtJCGve0snKzELb3YAuS2sOJw1EsJtKT2nh6zgcXKg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741852324; c=relaxed/simple; bh=IZta752DMiFilkSGUh8pMgDgzaLT6BNV+6WYkcI9x2I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FdFzFub0/9EA6k9LppimHxOrl1tMjWgevavcVMfGW12A3QVCP6/C+YxarvHaZXcJwk16Y2SSLxyxYr+3ie8xe7c9OErIDXHTw0a3qFniE5JN4obgeSo6D6k1TcDIEksIg/3OVjCAgvNpZQRqbaWhwUinpRDfc+O3Kxhq0KypeLY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=mu/PQ2M2; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="mu/PQ2M2" Received: from pps.filterd (m0356516.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 52CKZlQm026626; Thu, 13 Mar 2025 07:51:50 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=H/N7ewqYIt0kJY0Y4 VDOyf3KfbMPDokJi0c+Oro4new=; b=mu/PQ2M2ApPmRsm3tNcOtZbAFpb277KYy faNTBlLUN9fa48gvYuYWh2Bno0YKN1rTvSLQ55hbNRCZmf/PNejqcbY+yXGH83tb VSybhy1ooVWDVAKlZrkDfrhHmAyyVZWYA+WXso7fhv5im7r/bqVjEX0vSEgHercH yWQa9yyJOEKkvwB0l/3w1TxH+sqnH3XnzT9C2WEcvCq2U6fx7cp6BBekB+CTYe2+ 8zESC52gypl9g2Kf6o0Nb5PAjEmuEDLsVbyFYH3xFwastKJiURiYMOAeYi/VghYs VXbfp8ZwL3XO//kNTlpLpoLdnp+Y1+vFvgD9MW2OTapLKxVAfWfJw== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 45bhepja1x-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Mar 2025 07:51:49 +0000 (GMT) Received: from m0356516.ppops.net (m0356516.ppops.net [127.0.0.1]) by pps.reinject (8.18.0.8/8.18.0.8) with ESMTP id 52D7NLB2031574; Thu, 13 Mar 2025 07:51:49 GMT Received: from ppma21.wdc07v.mail.ibm.com (5b.69.3da9.ip4.static.sl-reverse.com [169.61.105.91]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 45bhepja1v-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Mar 2025 07:51:49 +0000 (GMT) Received: from pps.filterd (ppma21.wdc07v.mail.ibm.com [127.0.0.1]) by ppma21.wdc07v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 52D54ALf027040; Thu, 13 Mar 2025 07:51:48 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 45atsr0hut-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Mar 2025 07:51:48 +0000 Received: from smtpav04.fra02v.mail.ibm.com (smtpav04.fra02v.mail.ibm.com [10.20.54.103]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 52D7piEn53936588 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 13 Mar 2025 07:51:45 GMT Received: from smtpav04.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D1EFE20040; Thu, 13 Mar 2025 07:51:44 +0000 (GMT) Received: from smtpav04.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3AE222004B; Thu, 13 Mar 2025 07:51:42 +0000 (GMT) Received: from li-c6426e4c-27cf-11b2-a85c-95d65bc0de0e.in.ibm.com (unknown [9.204.206.66]) by smtpav04.fra02v.mail.ibm.com (Postfix) with ESMTP; Thu, 13 Mar 2025 07:51:42 +0000 (GMT) From: Gautam Menghani To: peterz@infradead.org, mingo@redhat.com, acme@kernel.org, namhyung@kernel.org, mark.rutland@arm.com, alexander.shishkin@linux.intel.com, jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com, kan.liang@linux.intel.com Cc: Gautam Menghani , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Madhavan Srinivasan Subject: [RFC PATCH 1/3] libperf: Introduce wrappers for perf structs to be exposed to python Date: Thu, 13 Mar 2025 13:21:22 +0530 Message-ID: <20250313075126.547881-2-gautam@linux.ibm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250313075126.547881-1-gautam@linux.ibm.com> References: <20250313075126.547881-1-gautam@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-GUID: K1j2sVaeCzgBkjLM2B-SHS00DJzVnCBA X-Proofpoint-ORIG-GUID: 4zjNmVmmG8DpkqiQu2uMhpSDbzEG3Ylo X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1093,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-03-13_03,2025-03-11_02,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 priorityscore=1501 impostorscore=0 bulkscore=0 phishscore=0 spamscore=0 suspectscore=0 mlxscore=0 malwarescore=0 clxscore=1015 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2502280000 definitions=main-2503130058 Content-Type: text/plain; charset="utf-8" Create wrapper objects for the perf structs (which are used by libperf) to be used by python. Also define other helper functions that will be used by the C extension module for python. Co-developed-by: Madhavan Srinivasan Signed-off-by: Madhavan Srinivasan Signed-off-by: Gautam Menghani --- tools/lib/perf/include/perf/py_perf.h | 431 ++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 tools/lib/perf/include/perf/py_perf.h diff --git a/tools/lib/perf/include/perf/py_perf.h b/tools/lib/perf/include= /perf/py_perf.h new file mode 100644 index 000000000000..26eeb05eaf67 --- /dev/null +++ b/tools/lib/perf/include/perf/py_perf.h @@ -0,0 +1,431 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LIBPERF_PY_PERF_H +#define __LIBPERF_PY_PERF_H + +#define PY_SSIZE_T_CLEAN +#include +#include +#include +#include +#include +#include +#include +#include + +// perf_thread_map declaration +typedef struct { + PyObject_HEAD + struct perf_thread_map *thread_map; +} py_perf_thread_map; + +static void py_perf_thread_map_dealloc(py_perf_thread_map *thread_map) +{ + free(thread_map->thread_map); + Py_DECREF(thread_map); + PyObject_Del((PyObject *)thread_map); +} + +static PyTypeObject py_perf_thread_map_type =3D { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name =3D "libperf.py_perf_thread_map", + .tp_doc =3D "Perf thread map object", + .tp_basicsize =3D sizeof(py_perf_thread_map), + .tp_dealloc =3D (destructor)py_perf_thread_map_dealloc, + .tp_flags =3D Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + +// perf_evsel declarations +typedef struct { + PyObject_HEAD + struct perf_evsel *evsel; +} py_perf_evsel; + +static void py_perf_evsel_dealloc(py_perf_evsel *evsel) +{ + Py_DECREF(evsel); + PyObject_Del((PyObject *)evsel); +} + +static PyTypeObject py_perf_evsel_type =3D { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name =3D "libperf.py_perf_evsel", + .tp_doc =3D "Perf evsel object", + .tp_basicsize =3D sizeof(py_perf_evsel), + .tp_dealloc =3D (destructor)py_perf_evsel_dealloc, + .tp_flags =3D Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + +// perf_evlist declarations +typedef struct { + PyObject_HEAD + struct perf_evlist *evlist; +} py_perf_evlist; + +static void py_perf_evlist_dealloc(py_perf_evlist *evlist) +{ + free(evlist->evlist); + Py_DECREF(evlist); + PyObject_Del((PyObject *)evlist); +} + +typedef struct { + PyObject_HEAD + PyObject *evlist; + struct list_head *current; +} py_perf_evlist_iterator; + +static PyObject *evlist_iterator_next(py_perf_evlist_iterator *iter) { + + py_perf_evsel *pyperf_evsel =3D PyObject_New(py_perf_evsel, &py_perf_evse= l_type); + struct list_head *head; + + if (((py_perf_evlist *)(iter->evlist))->evlist =3D=3D NULL) { + PyErr_SetString(PyExc_RuntimeError, "perf_evlist has been closed"); + return NULL; + } + head =3D &((py_perf_evlist *)(iter->evlist))->evlist->entries; + if (iter->current =3D=3D head) { + PyErr_SetNone(PyExc_StopIteration); + return NULL; + } + pyperf_evsel->evsel =3D list_entry(iter->current, struct perf_evsel, node= ); + iter->current =3D iter->current->next; + Py_INCREF(iter->evlist); + + return (PyObject *)pyperf_evsel; +} + +static PyTypeObject py_perf_evlist_iterator_type =3D { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name =3D "libperf.evlist_iterator_type", + .tp_basicsize =3D sizeof(py_perf_evlist_iterator), + .tp_itemsize =3D 0, + .tp_flags =3D Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_doc =3D "evlist_iterator object", + .tp_iter =3D PyObject_SelfIter, + .tp_iternext =3D (iternextfunc) evlist_iterator_next, +}; + +static PyObject *py_perf_evlist_iter(py_perf_evlist *self) { + py_perf_evlist_iterator *iter =3D PyObject_New(py_perf_evlist_iterator, &= py_perf_evlist_iterator_type); + if (!iter) + return NULL; + iter->current =3D self->evlist->entries.next; + iter->evlist =3D (PyObject *)self; + Py_INCREF(self); + return (PyObject *)iter; +} + +static PyTypeObject py_perf_evlist_type =3D { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name =3D "libperf.py_perf_evlist", + .tp_doc =3D "Perf evlist object", + .tp_basicsize =3D sizeof(py_perf_evlist), + .tp_dealloc =3D (destructor)py_perf_evlist_dealloc, + .tp_iter =3D (getiterfunc) py_perf_evlist_iter, + .tp_flags =3D Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + +// perf_cpu_map declarations +typedef struct { + PyObject_HEAD + struct perf_cpu_map *map; +} py_perf_cpu_map; + +static void py_perf_cpu_map_dealloc(py_perf_cpu_map *cpu_map) +{ + free(cpu_map->map); + Py_DECREF(cpu_map); + PyObject_Del((PyObject *)cpu_map); +} + +static PyTypeObject py_perf_cpu_map_type =3D { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name =3D "libperf.py_perf_cpu_map", + .tp_doc =3D "Perf cpu_map object", + .tp_basicsize =3D sizeof(py_perf_cpu_map), + .tp_dealloc =3D (destructor)py_perf_cpu_map_dealloc, + .tp_flags =3D Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + +// perf_event_attr declarations +typedef struct { + PyObject_HEAD + struct perf_event_attr *attr; +} py_perf_event_attr; + +#define PY_STRUCT_GET_SET_FUNC_LONG(name, c_type, element) \ +static PyObject *py_##name##_##element##_get(py_##name *self, void *closur= e) \ +{ \ + return PyLong_FromLong(self->c_type->element); \ +} \ + \ +static int py_##name##_##element##_set(py_##name *self, PyObject *value, v= oid *closure) \ +{ \ + \ + if (!PyLong_Check(value)) \ + return -1; \ + \ + self->c_type->element =3D PyLong_AsLong(value); \ + \ + return 0; \ +} + +#define GET_SET_DEF(name, element) \ + {#element, (getter)py_##name##_##element##_get, (setter)py_##name##_##ele= ment##_set, NULL, NULL} + +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, type) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, size) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, config) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, sample_period) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, sample_freq) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, sample_type) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, read_format) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, disabled) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, inherit) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, pinned) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, exclusive) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, exclude_user) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, exclude_kernel) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, exclude_hv) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, exclude_idle) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, mmap) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, comm) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, freq) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, inherit_stat) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, enable_on_exec) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, task) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, watermark) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, precise_ip) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, mmap_data) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, sample_id_all) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, exclude_host) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, exclude_guest) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, exclude_callchain_kerne= l) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, exclude_callchain_user) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, mmap2) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, comm_exec) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, use_clockid) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, context_switch) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, write_backward) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, namespaces) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, ksymbol) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, bpf_event) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, aux_output) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, cgroup) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, text_poke) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, build_id) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, inherit_thread) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, remove_on_exec) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, sigtrap) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, __reserved_1) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, wakeup_events) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, wakeup_watermark) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, bp_type) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, bp_addr) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, kprobe_func) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, uprobe_path) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, config1) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, bp_len) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, kprobe_addr) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, probe_offset) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, config2) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, branch_sample_type) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, sample_regs_user) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, sample_stack_user) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, clockid) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, sample_regs_intr) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, aux_watermark) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, sample_max_stack) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, __reserved_2) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, aux_sample_size) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, __reserved_3) +PY_STRUCT_GET_SET_FUNC_LONG(perf_event_attr, attr, sig_data) + + +static PyGetSetDef py_perf_event_attr_getset[] =3D { + GET_SET_DEF(perf_event_attr, type), + GET_SET_DEF(perf_event_attr, size), + GET_SET_DEF(perf_event_attr, config), + GET_SET_DEF(perf_event_attr, sample_period), + GET_SET_DEF(perf_event_attr, sample_freq), + GET_SET_DEF(perf_event_attr, sample_type), + GET_SET_DEF(perf_event_attr, read_format), + GET_SET_DEF(perf_event_attr, disabled), + GET_SET_DEF(perf_event_attr, inherit), + GET_SET_DEF(perf_event_attr, pinned), + GET_SET_DEF(perf_event_attr, exclusive), + GET_SET_DEF(perf_event_attr, exclude_user), + GET_SET_DEF(perf_event_attr, exclude_kernel), + GET_SET_DEF(perf_event_attr, exclude_hv), + GET_SET_DEF(perf_event_attr, exclude_idle), + GET_SET_DEF(perf_event_attr, mmap), + GET_SET_DEF(perf_event_attr, comm), + GET_SET_DEF(perf_event_attr, freq), + GET_SET_DEF(perf_event_attr, inherit_stat), + GET_SET_DEF(perf_event_attr, enable_on_exec), + GET_SET_DEF(perf_event_attr, task), + GET_SET_DEF(perf_event_attr, watermark), + GET_SET_DEF(perf_event_attr, precise_ip), + GET_SET_DEF(perf_event_attr, mmap_data), + GET_SET_DEF(perf_event_attr, sample_id_all), + GET_SET_DEF(perf_event_attr, exclude_host), + GET_SET_DEF(perf_event_attr, exclude_guest), + GET_SET_DEF(perf_event_attr, exclude_callchain_kernel), + GET_SET_DEF(perf_event_attr, exclude_callchain_user), + GET_SET_DEF(perf_event_attr, mmap2), + GET_SET_DEF(perf_event_attr, comm_exec), + GET_SET_DEF(perf_event_attr, use_clockid), + GET_SET_DEF(perf_event_attr, context_switch), + GET_SET_DEF(perf_event_attr, write_backward), + GET_SET_DEF(perf_event_attr, namespaces), + GET_SET_DEF(perf_event_attr, ksymbol), + GET_SET_DEF(perf_event_attr, bpf_event), + GET_SET_DEF(perf_event_attr, aux_output), + GET_SET_DEF(perf_event_attr, cgroup), + GET_SET_DEF(perf_event_attr, text_poke), + GET_SET_DEF(perf_event_attr, build_id), + GET_SET_DEF(perf_event_attr, inherit_thread), + GET_SET_DEF(perf_event_attr, remove_on_exec), + GET_SET_DEF(perf_event_attr, sigtrap), + GET_SET_DEF(perf_event_attr, __reserved_1), + GET_SET_DEF(perf_event_attr, wakeup_events), + GET_SET_DEF(perf_event_attr, wakeup_watermark), + GET_SET_DEF(perf_event_attr, bp_type), + GET_SET_DEF(perf_event_attr, bp_addr), + GET_SET_DEF(perf_event_attr, kprobe_func), + GET_SET_DEF(perf_event_attr, uprobe_path), + GET_SET_DEF(perf_event_attr, config1), + GET_SET_DEF(perf_event_attr, bp_len), + GET_SET_DEF(perf_event_attr, kprobe_addr), + GET_SET_DEF(perf_event_attr, probe_offset), + GET_SET_DEF(perf_event_attr, config2), + GET_SET_DEF(perf_event_attr, branch_sample_type), + GET_SET_DEF(perf_event_attr, sample_regs_user), + GET_SET_DEF(perf_event_attr, sample_stack_user), + GET_SET_DEF(perf_event_attr, clockid), + GET_SET_DEF(perf_event_attr, sample_regs_intr), + GET_SET_DEF(perf_event_attr, aux_watermark), + GET_SET_DEF(perf_event_attr, sample_max_stack), + GET_SET_DEF(perf_event_attr, __reserved_2), + GET_SET_DEF(perf_event_attr, aux_sample_size), + GET_SET_DEF(perf_event_attr, __reserved_3), + GET_SET_DEF(perf_event_attr, sig_data), + {NULL} +}; + +static PyObject *py_perf_event_attr_new(PyTypeObject *type, PyObject *args= , PyObject *kwds) +{ + py_perf_event_attr *self =3D (py_perf_event_attr *) type->tp_alloc(type, = 0); + + if (!self) + return NULL; + + self->attr =3D calloc(1, sizeof(struct perf_event_attr)); + + return (PyObject *)self; +} + +static void py_perf_event_attr_dealloc(py_perf_event_attr *ctr) +{ + free(ctr->attr); + Py_DECREF(ctr); + PyObject_Del((PyObject *)ctr); +} + +static PyTypeObject py_perf_event_attr_type =3D { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name =3D "libperf.py_perf_event_attr", + .tp_doc =3D "perf event attribute structure object", + .tp_basicsize =3D sizeof(py_perf_event_attr), + .tp_new =3D py_perf_event_attr_new, + .tp_dealloc =3D (destructor)py_perf_event_attr_dealloc, + .tp_flags =3D Py_TPFLAGS_DEFAULT| Py_TPFLAGS_BASETYPE, + .tp_getset =3D py_perf_event_attr_getset, +}; + +// perf_counts_values declarations +typedef struct { + PyObject_HEAD + struct perf_counts_values *values; +} py_perf_counts_values; + +static void py_perf_counts_values_dealloc(py_perf_counts_values *values) +{ + free(values->values); + Py_DECREF(values); + PyObject_Del((PyObject *)values); +} + +static PyObject * py_perf_counts_values_get_values(py_perf_counts_values *= self, void *closure) +{ + PyObject *list =3D PyList_New(5); + if (!list) + return NULL; + for (int i =3D 0; i < 5; i++) { + PyList_SetItem(list, i, PyLong_FromLong(self->values->values[i])); + } + return list; +} + +static int py_perf_counts_values_set_values(py_perf_counts_values *self, P= yObject *value, void *closure) +{ + if (!PyLong_Check(value)) { + PyErr_SetString(PyExc_TypeError, "Values must be u64"); + return -1; + } + for(int i =3D 0; i < 5; i++) { + self->values->values[i] =3D PyLong_AsLong(value); + } + return 0; +} +PY_STRUCT_GET_SET_FUNC_LONG(perf_counts_values, values, val) +PY_STRUCT_GET_SET_FUNC_LONG(perf_counts_values, values, ena) +PY_STRUCT_GET_SET_FUNC_LONG(perf_counts_values, values, run) +PY_STRUCT_GET_SET_FUNC_LONG(perf_counts_values, values, id) +PY_STRUCT_GET_SET_FUNC_LONG(perf_counts_values, values, lost) + +static PyGetSetDef py_perf_counts_values_getsetters[] =3D { + GET_SET_DEF(perf_counts_values, val), + GET_SET_DEF(perf_counts_values, ena), + GET_SET_DEF(perf_counts_values, run), + GET_SET_DEF(perf_counts_values, id), + GET_SET_DEF(perf_counts_values, lost), + {"values", (getter)py_perf_counts_values_get_values, (setter)py_perf_coun= ts_values_set_values,"values", NULL}, + {NULL} +}; + +static PyObject *py_perf_counts_values_new(PyTypeObject *type, PyObject *a= rgs, PyObject *kwds) +{ + py_perf_counts_values *self =3D (py_perf_counts_values *) type->tp_alloc(= type, 0); + + if (!self) + return NULL; + + self->values =3D calloc(1, sizeof(struct perf_counts_values)); + + return (PyObject *)self; +} + +static PyTypeObject py_perf_counts_values_type =3D { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name =3D "libperf.py_perf_counts_values", + .tp_doc =3D "Perf_counts_values object", + .tp_basicsize =3D sizeof(py_perf_counts_values), + .tp_new =3D py_perf_counts_values_new, + .tp_dealloc =3D (destructor)py_perf_counts_values_dealloc, + .tp_flags =3D Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_getset =3D py_perf_counts_values_getsetters, +}; + +static void python_push_type(const char *name, PyObject *module, PyTypeObj= ect *type) +{ + if (PyType_Ready(type) =3D=3D -1) + printf("python_push_type: failed to ready %s", name); + + Py_INCREF(type); +} + +LIBPERF_API PyMODINIT_FUNC PyInit_libperf(void); + +#endif /* __LIBPERF_PY_PERF_H */ --=20 2.47.0 From nobody Sun Dec 14 20:29:46 2025 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 025CE260372; Thu, 13 Mar 2025 07:52:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741852331; cv=none; b=q4kv8pjYVHXVGNY9oYbasI+3fPJF+5O/ndsw9XOpWGMB4Y41Wk8PYT4ai704t+126mJ+gu4J0Wf432vpYfEjpTnjZ6TkJ+R+qD0McMpqW1BfQN3cyQIReu4vGctJ37COMcY4aaM95aBAT0Wv+lWw9SDyGb6P/MrQpeSDBeX+6/w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741852331; c=relaxed/simple; bh=ofKZ9kQApiZqP/L+tkA0TgjZohU6q1uyaOBqKodqXJo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QzAmUJomuAV2gBrHSPvT+bYBqkPPS2XK4+X17SDjjhmK2scbPYCauu5Ey71+CJXc5yE47d97b+z/Y81DAZ/Fj5OVlLKRUHaFlY7eeNoDBrStyG+j/dv5Xp7v5hwSavC1hlfy4ZSZ4UdGEICPp9YTf31wVOA7rW0R/H7ZnitS7Rc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=MbYs+XDL; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="MbYs+XDL" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 52CMkZGG023136; Thu, 13 Mar 2025 07:51:59 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=cvzn5kePyIZiAGRtI VSzmJl+PnzSxTLse4RU+RSkZpk=; b=MbYs+XDLGE3XW/8gw7HwHtmbhzst6Ki7c giIOpXEYOPB1Bj/5IFP02DJhGSBkwUOM/CEmznXySFDXxO7Cl2jRPvzEVSfMUq6A 10HHgn54RMAiwny5EsEWR8HucJVqLemarYkg8gNdgk5taukaekXpRLuSKHHIVn4l BVLGT67eHfk/sJ6cD6KmrMPal9POfG5nuSEUms9iypWWWUTt8DU4kw4ZhTqJHuBm +DimyxMdv2fjL8pDQgja+hyOne5B0CA2gELpVOm8vtNg13B+j5SouEpWWnr+09Sf 8KOdy+y/0yctARmKE7DNHE0ex8HmclpW95O55YYACAFGatRk8Vipg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 45bbppvcju-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Mar 2025 07:51:59 +0000 (GMT) Received: from m0356517.ppops.net (m0356517.ppops.net [127.0.0.1]) by pps.reinject (8.18.0.8/8.18.0.8) with ESMTP id 52D7pwU6004301; Thu, 13 Mar 2025 07:51:58 GMT Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 45bbppvcjr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Mar 2025 07:51:58 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 52D4QrNj012255; Thu, 13 Mar 2025 07:51:57 GMT Received: from smtprelay07.fra02v.mail.ibm.com ([9.218.2.229]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 45atsrgjs7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Mar 2025 07:51:57 +0000 Received: from smtpav04.fra02v.mail.ibm.com (smtpav04.fra02v.mail.ibm.com [10.20.54.103]) by smtprelay07.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 52D7prTP41877948 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 13 Mar 2025 07:51:53 GMT Received: from smtpav04.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 12D2920043; Thu, 13 Mar 2025 07:51:53 +0000 (GMT) Received: from smtpav04.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 79D0C20040; Thu, 13 Mar 2025 07:51:50 +0000 (GMT) Received: from li-c6426e4c-27cf-11b2-a85c-95d65bc0de0e.in.ibm.com (unknown [9.204.206.66]) by smtpav04.fra02v.mail.ibm.com (Postfix) with ESMTP; Thu, 13 Mar 2025 07:51:50 +0000 (GMT) From: Gautam Menghani To: peterz@infradead.org, mingo@redhat.com, acme@kernel.org, namhyung@kernel.org, mark.rutland@arm.com, alexander.shishkin@linux.intel.com, jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com, kan.liang@linux.intel.com Cc: Gautam Menghani , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Madhavan Srinivasan Subject: [RFC PATCH 2/3] libperf: Introduce a C extension module for python Date: Thu, 13 Mar 2025 13:21:23 +0530 Message-ID: <20250313075126.547881-3-gautam@linux.ibm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250313075126.547881-1-gautam@linux.ibm.com> References: <20250313075126.547881-1-gautam@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: L3FhwI1KdtmemB2dxDpp1E2k0uZYj-Kt X-Proofpoint-GUID: K4OTOpxPu2XKKY_GLb3J3m8Ubhm800P2 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1093,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-03-13_03,2025-03-11_02,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 suspectscore=0 phishscore=0 lowpriorityscore=0 impostorscore=0 spamscore=0 adultscore=0 malwarescore=0 bulkscore=0 clxscore=1015 mlxscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2502280000 definitions=main-2503130058 Content-Type: text/plain; charset="utf-8" Create a C extension module for libperf that will be used by python to call the libperf functions. Co-developed-by: Madhavan Srinivasan Signed-off-by: Madhavan Srinivasan Signed-off-by: Gautam Menghani --- tools/lib/perf/Build | 1 + tools/lib/perf/Makefile | 12 +- tools/lib/perf/libperf.map | 1 + tools/lib/perf/py_perf.c | 261 +++++++++++++++++++++++++++++++++++++ 4 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 tools/lib/perf/py_perf.c diff --git a/tools/lib/perf/Build b/tools/lib/perf/Build index e8f5b7fb9973..4869da30ffb5 100644 --- a/tools/lib/perf/Build +++ b/tools/lib/perf/Build @@ -7,6 +7,7 @@ libperf-y +=3D mmap.o libperf-y +=3D zalloc.o libperf-y +=3D xyarray.o libperf-y +=3D lib.o +libperf-y +=3D py_perf.o =20 $(OUTPUT)zalloc.o: ../../lib/zalloc.c FORCE $(call rule_mkdir) diff --git a/tools/lib/perf/Makefile b/tools/lib/perf/Makefile index e9a7ac2c062e..8e16492af882 100644 --- a/tools/lib/perf/Makefile +++ b/tools/lib/perf/Makefile @@ -48,20 +48,28 @@ else CFLAGS :=3D -g -Wall endif =20 +# Check Python.h path +ifeq (,$(shell which python-config)) + $(error "Consider installing python-dev or python-devel") +endif + +PYTHON_INCLUDE =3D $(shell python-config --includes) + INCLUDES =3D \ -I$(srctree)/tools/lib/perf/include \ -I$(srctree)/tools/lib/ \ -I$(srctree)/tools/include \ -I$(srctree)/tools/arch/$(SRCARCH)/include/ \ -I$(srctree)/tools/arch/$(SRCARCH)/include/uapi \ --I$(srctree)/tools/include/uapi +-I$(srctree)/tools/include/uapi \ +-I$(PYTHON_INCLUDE) =20 # Append required CFLAGS override CFLAGS +=3D $(EXTRA_WARNINGS) override CFLAGS +=3D -Werror -Wall override CFLAGS +=3D -fPIC override CFLAGS +=3D $(INCLUDES) -override CFLAGS +=3D -fvisibility=3Dhidden +override CFLAGS +=3D -fvisibility=3Dhidden -Wno-redundant-decls =20 all: =20 diff --git a/tools/lib/perf/libperf.map b/tools/lib/perf/libperf.map index fdd8304fe9d0..0488c0591404 100644 --- a/tools/lib/perf/libperf.map +++ b/tools/lib/perf/libperf.map @@ -57,6 +57,7 @@ LIBPERF_0.0.1 { perf_mmap__read_done; perf_mmap__read_event; perf_counts_values__scale; + PyInit_libperf; local: *; }; diff --git a/tools/lib/perf/py_perf.c b/tools/lib/perf/py_perf.c new file mode 100644 index 000000000000..cf0fcb8cc6c1 --- /dev/null +++ b/tools/lib/perf/py_perf.c @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include "include/perf/py_perf.h" +#include +#include +#include +#include +#include + +static PyObject *program_perf_thread_map__new_dummy(PyObject *self, PyObje= ct *args) +{ + py_perf_thread_map *pythread_map =3D PyObject_New(py_perf_thread_map, &py= _perf_thread_map_type); + + pythread_map->thread_map =3D perf_thread_map__new_dummy(); + if (!pythread_map->thread_map) { + Py_DECREF(pythread_map); + return Py_None; + } + + return Py_BuildValue("O", pythread_map); +} + +static PyObject *program_perf_thread_map__set_pid(PyObject *self, PyObject= *args) +{ + py_perf_thread_map *pythread_map =3D NULL; + int idx, pid; + + if (!PyArg_ParseTuple(args, "Oii", &pythread_map, &idx, &pid)) { + return NULL; + } + + perf_thread_map__set_pid(pythread_map->thread_map, idx, pid); + + return Py_None; +} + +static PyObject *program_perf_evlist__new(PyObject *self, PyObject *args) +{ + py_perf_evlist *pyperf_evlist =3D PyObject_New(py_perf_evlist, &py_perf_e= vlist_type); + + pyperf_evlist->evlist =3D perf_evlist__new(); + if (!pyperf_evlist->evlist) { + Py_DECREF(pyperf_evlist); + return Py_None; + } + + return Py_BuildValue("O", pyperf_evlist); +} + +static PyObject *program_perf_evsel__new(PyObject *self, PyObject *args) +{ + struct perf_event_attr *attr; + PyObject *py_attr; + py_perf_evsel *pyperf_evsel =3D PyObject_New(py_perf_evsel, &py_perf_evse= l_type); + + if (!PyArg_ParseTuple(args, "O", &py_attr)) { + return NULL; + } + + attr =3D (py_attr =3D=3D Py_None)? NULL: ((py_perf_event_attr *)py_attr)-= >attr; + pyperf_evsel->evsel =3D perf_evsel__new(attr); + if (!pyperf_evsel->evsel) { + Py_DECREF(pyperf_evsel); + return Py_None; + } + + return Py_BuildValue("O", pyperf_evsel); +} + +static PyObject *program_perf_evlist__add(PyObject *self, PyObject *args) +{ + struct perf_evsel *evsel; + struct perf_evlist *evlist; + PyObject *pyevlist, *pyevsel; + + if (!PyArg_ParseTuple(args, "OO", &pyevlist, &pyevsel)) { + return NULL; + } + + evsel =3D (pyevsel =3D=3D Py_None)? NULL: ((py_perf_evsel *)pyevsel)->evs= el; + evlist =3D (pyevlist =3D=3D Py_None)? NULL: ((py_perf_evlist *)pyevlist)-= >evlist; + perf_evlist__add(evlist, evsel); + + return Py_None; +} + +static PyObject *program_perf_evlist__set_maps(PyObject *self, PyObject *a= rgs) +{ + struct perf_thread_map *thread_map; + struct perf_evlist *evlist; + struct perf_cpu_map *cpu_map; + PyObject *pyevlist, *pythread_map, *pycpu_map; + + if (!PyArg_ParseTuple(args, "OOO", &pyevlist, &pycpu_map, &pythread_map))= { + return NULL; + } + + evlist =3D (pyevlist =3D=3D Py_None)? NULL: ((py_perf_evlist *)pyevlist)-= >evlist; + cpu_map =3D (pycpu_map =3D=3D Py_None)? NULL: ((py_perf_cpu_map *)pycpu_m= ap)->map; + thread_map =3D (pythread_map =3D=3D Py_None)? NULL: ((py_perf_thread_map = *)pythread_map)->thread_map; + perf_evlist__set_maps(evlist, cpu_map, thread_map); + + return Py_None; +} + +static PyObject *program_perf_evlist__open(PyObject *self, PyObject *args) +{ + struct perf_evlist *evlist; + PyObject *pyevlist; + + if (!PyArg_ParseTuple(args, "O", &pyevlist)) { + return NULL; + } + evlist =3D (pyevlist =3D=3D Py_None)? NULL: ((py_perf_evlist *)pyevlist)-= >evlist; + + return Py_BuildValue("i", perf_evlist__open(evlist)); +} + +static PyObject *program_perf_evlist__enable(PyObject *self, PyObject *arg= s) +{ + struct perf_evlist *evlist; + PyObject *pyevlist; + + if (!PyArg_ParseTuple(args, "O", &pyevlist)) { + return NULL; + } + + evlist =3D (pyevlist =3D=3D Py_None)? NULL: ((py_perf_evlist *)pyevlist)-= >evlist; + perf_evlist__enable(evlist); + + return Py_None; +} + +static PyObject *program_perf_evlist__disable(PyObject *self, PyObject *ar= gs) +{ + struct perf_evlist *evlist; + PyObject *pyevlist; + + if (!PyArg_ParseTuple(args, "O", &pyevlist)) { + return NULL; + } + evlist =3D (pyevlist =3D=3D Py_None)? NULL: ((py_perf_evlist *)pyevlist)-= >evlist; + perf_evlist__disable(evlist); + + return Py_None; +} + +static PyObject *program_perf_evsel__read(PyObject *self, PyObject *args) +{ + PyObject *pyevsel, *pyperf_counts_values; + struct perf_evsel *evsel; + struct perf_counts_values *values; + int cpu_map_idx, thread; + + if (!PyArg_ParseTuple(args, "OiiO", &pyevsel, &cpu_map_idx, &thread, &pyp= erf_counts_values)) { + return NULL; + } + evsel =3D (pyevsel =3D=3D Py_None)? NULL: ((py_perf_evsel *)pyevsel)->evs= el; + values =3D (pyevsel =3D=3D Py_None)? NULL: ((py_perf_counts_values *)pype= rf_counts_values)->values; + + return Py_BuildValue("i", perf_evsel__read(evsel, cpu_map_idx, thread, va= lues)); +} + +static PyObject *program_perf_evlist__close(PyObject *self, PyObject *args) +{ + struct perf_evlist *evlist; + PyObject *pyevlist; + + if (!PyArg_ParseTuple(args, "O", &pyevlist)) { + return NULL; + } + evlist =3D (pyevlist =3D=3D Py_None)? NULL: ((py_perf_evlist *)pyevlist)-= >evlist; + perf_evlist__close(evlist); + + return Py_None; +} + +static PyObject *program_perf_evlist__delete(PyObject *self, PyObject *arg= s) +{ + struct perf_evlist *evlist; + PyObject *pyevlist; + + if (!PyArg_ParseTuple(args, "O", &pyevlist)) { + return NULL; + } + evlist =3D (pyevlist =3D=3D Py_None)? NULL: ((py_perf_evlist *)pyevlist)-= >evlist; + perf_evlist__delete(evlist); + + return Py_None; +} + +static PyObject *program_perf_thread_map__put(PyObject *self, PyObject *ar= gs) +{ + struct perf_thread_map *map; + PyObject *pyperf_thread_map; + + if (!PyArg_ParseTuple(args, "O", &pyperf_thread_map)) { + return NULL; + } + map =3D (pyperf_thread_map =3D=3D Py_None)? NULL: ((py_perf_thread_map *)= pyperf_thread_map)->thread_map; + perf_thread_map__put(map); + + return Py_None; +} + +static int libperf_print(enum libperf_print_level level, + const char *fmt, va_list ap) +{ + return vfprintf(stderr, fmt, ap); +} + +static PyObject *program_libperf_init(PyObject *self, PyObject *args) +{ + libperf_init(libperf_print); + return Py_None; +} + +PyMethodDef libperf_methods[] =3D { + {"perf_thread_map__new_dummy", program_perf_thread_map__new_dummy, METH_V= ARARGS, "Create a dummy thread map function variable"}, + {"perf_thread_map__set_pid", program_perf_thread_map__set_pid, METH_VARAR= GS, "Set PID for a thread map"}, + {"perf_evlist__new", program_perf_evlist__new, METH_VARARGS, "Create a pe= rf evlist"}, + {"perf_evsel__new", program_perf_evsel__new, METH_VARARGS, "Create a perf= evsel"}, + {"perf_evlist__add", program_perf_evlist__add, METH_VARARGS, "Add evsel t= o evlist"}, + {"perf_evlist__set_maps", program_perf_evlist__set_maps, METH_VARARGS, "p= erf_evlist__set_maps"}, + {"perf_evlist__open", program_perf_evlist__open, METH_VARARGS, "perf_evli= st__set_maps"}, + {"perf_evlist__enable", program_perf_evlist__enable, METH_VARARGS, "perf_= evlist__enable"}, + {"perf_evlist__disable", program_perf_evlist__disable, METH_VARARGS, "per= f_evlist__disable"}, + {"perf_evsel__read", program_perf_evsel__read, METH_VARARGS, "perf_evsel_= _read"}, + {"perf_evlist__close", program_perf_evlist__close, METH_VARARGS, "perf_ev= list__close"}, + {"perf_evlist__delete", program_perf_evlist__delete, METH_VARARGS, "perf_= evlist__delete"}, + {"perf_thread_map__put", program_perf_thread_map__put, METH_VARARGS, "per= f_thread_map__put"}, + {"libperf_init", program_libperf_init, METH_VARARGS, "libperf init"}, + {NULL, NULL, 0, NULL} +}; + +struct PyModuleDef libperf =3D { + PyModuleDef_HEAD_INIT, + "libperf", + "Extension module to expose libperf to python", + -1, + libperf_methods +}; + +PyMODINIT_FUNC PyInit_libperf(void) { + PyObject *m =3D PyModule_Create(&libperf); + + if (!m) + return NULL; + + python_push_type("py_perf_thread_map", m, &py_perf_thread_map_type); + python_push_type("py_perf_evlist", m, &py_perf_evlist_type); + python_push_type("evlist_iterator", m, &py_perf_evlist_iterator_type); + python_push_type("py_perf_evsel", m, &py_perf_evsel_type); + python_push_type("py_perf_cpu_map", m, &py_perf_cpu_map_type); + python_push_type("py_perf_event_attr", m, &py_perf_event_attr_type); + python_push_type("py_perf_counts_values", m, &py_perf_counts_values_type); + + PyModule_AddObject(m, "perf_event_attr", (PyObject *) & py_perf_event_att= r_type); + PyModule_AddObject(m, "perf_counts_values", (PyObject *) & py_perf_counts= _values_type); + + return m; +} --=20 2.47.0 From nobody Sun Dec 14 20:29:46 2025 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E7EF825FA10; Thu, 13 Mar 2025 07:52:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741852339; cv=none; b=ZfgxIzH8SyEm0TVGXR2OZjb759mhj6kahs3GxrIl9a32D3N+Zr5PdJ/SCrhM/8R2iaP5ZD1T2ZUAX5mFhs3JgvA1a/3tI82Xsd/JH8XvJ2epFjKHpdRK+QzQ3AaqVM8mYkSrT911pMOZoOZWg6iyje1nBet1lbVBtNWXfYAUOJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741852339; c=relaxed/simple; bh=gedR1dtFtnCRn8w58vk7alcMu7KQkECnS+oo3tCjlq0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G/Inwyp3T3Qx8gITPpotpnMdvccwjPd9N5H2TuOnxYMAVNyLRup727MpCr8EvV8OI549vWn2e/1FHNwurP6h8beck4f1y+qDw94YXCHWH1XRjDJ91rT9HluSg8ZLLlql6zN+t+LzIL8Rgri0S9VpK07k4F6MR219Ez54H40IY3g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=WDEFS6hE; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="WDEFS6hE" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 52CMWFGT023024; Thu, 13 Mar 2025 07:52:05 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=jH+b7pTyfpjSwAnXy JyeBmChyDlRKjpWN/yUwvVGuSg=; b=WDEFS6hEoXghrrRjjTaezGoLFmTZ/3+U8 zYYUF8rIMyonwNUCvu5UlUHWfrfrkTpCZKQUWZn6xGsE5gOhRsKGgHITRzzmYdpS /UIrxHiRKKJfrwho5EpWkiwS/6zBLkHM/sd7XEEuTeg0HIjPQwpone4mxSruchlp 5AWbmO7ei+RJ4RrA3vJwcKGsmyBXLZUVaVxEqs4K66R/3wtjIlqrDBQLw6Yj0K7p wep9OvkIHrLb3qseDchXpVVlrc9M4p0j2lDjJd2JhCoo7JmnRc3ECG1R0urm1G9D R+o3AAdxiG39U7bKFgTCUkvtDiASveCUGl911t/Xklx9ds3sZsrNg== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 45bbppvck4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Mar 2025 07:52:04 +0000 (GMT) Received: from m0356517.ppops.net (m0356517.ppops.net [127.0.0.1]) by pps.reinject (8.18.0.8/8.18.0.8) with ESMTP id 52D7pwU8004301; Thu, 13 Mar 2025 07:52:04 GMT Received: from ppma13.dal12v.mail.ibm.com (dd.9e.1632.ip4.static.sl-reverse.com [50.22.158.221]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 45bbppvck0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Mar 2025 07:52:04 +0000 (GMT) Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 52D51FwV026021; Thu, 13 Mar 2025 07:52:03 GMT Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 45atspgkar-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 13 Mar 2025 07:52:03 +0000 Received: from smtpav04.fra02v.mail.ibm.com (smtpav04.fra02v.mail.ibm.com [10.20.54.103]) by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 52D7q1D536897066 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 13 Mar 2025 07:52:01 GMT Received: from smtpav04.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5B0EC2004B; Thu, 13 Mar 2025 07:52:01 +0000 (GMT) Received: from smtpav04.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EA35320043; Thu, 13 Mar 2025 07:51:58 +0000 (GMT) Received: from li-c6426e4c-27cf-11b2-a85c-95d65bc0de0e.in.ibm.com (unknown [9.204.206.66]) by smtpav04.fra02v.mail.ibm.com (Postfix) with ESMTP; Thu, 13 Mar 2025 07:51:58 +0000 (GMT) From: Gautam Menghani To: peterz@infradead.org, mingo@redhat.com, acme@kernel.org, namhyung@kernel.org, mark.rutland@arm.com, alexander.shishkin@linux.intel.com, jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com, kan.liang@linux.intel.com Cc: Gautam Menghani , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 3/3] libperf: Add counting.py example to demonstrate libperf usage from python Date: Thu, 13 Mar 2025 13:21:24 +0530 Message-ID: <20250313075126.547881-4-gautam@linux.ibm.com> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20250313075126.547881-1-gautam@linux.ibm.com> References: <20250313075126.547881-1-gautam@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: DoCVUCURExpo5HknrM-ne3o0IVx3GuDv X-Proofpoint-GUID: j8dguHwLuVYkULisaGTlJsFbJjefrhfA X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1093,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-03-13_03,2025-03-11_02,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 suspectscore=0 phishscore=0 lowpriorityscore=0 impostorscore=0 spamscore=0 adultscore=0 malwarescore=0 bulkscore=0 clxscore=1015 mlxscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2502280000 definitions=main-2503130058 Content-Type: text/plain; charset="utf-8" Add a counting.py example to demonstrate usage of libperf from python using the C extension module support. Example usage: $ sudo ./counting.py count 7903256, enabled 7903670, run 7903670 count 7902787, enabled 7902787, run 7902787 Signed-off-by: Gautam Menghani --- .../perf/Documentation/examples/counting.py | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100755 tools/lib/perf/Documentation/examples/counting.py diff --git a/tools/lib/perf/Documentation/examples/counting.py b/tools/lib/= perf/Documentation/examples/counting.py new file mode 100755 index 000000000000..887111bf2e04 --- /dev/null +++ b/tools/lib/perf/Documentation/examples/counting.py @@ -0,0 +1,74 @@ +#!/usr/bin/python3 + +import sys +sys.path.append('../../') +from libperf import * + +# software ids +PERF_COUNT_SW_CPU_CLOCK =3D 0 +PERF_COUNT_SW_TASK_CLOCK =3D 1 + +# Perf event types +PERF_TYPE_HARDWARE =3D 0 +PERF_TYPE_SOFTWARE =3D 1 +PERF_TYPE_TRACEPOINT =3D 2 +PERF_TYPE_HW_CACHE =3D 3 + +# perf_event_attr_read format +PERF_FORMAT_TOTAL_TIME_ENABLED =3D 1 << 0 +PERF_FORMAT_TOTAL_TIME_RUNNING =3D 1 << 1 +PERF_FORMAT_ID =3D 1 << 2 +PERF_FORMAT_GROUP =3D 1 << 3 +PERF_FORMAT_LOST =3D 1 << 4 + +# Perf sample identifier +PERF_SAMPLE_IDENTIFIER =3D 1 << 16 + +def get_attr(config): + attr =3D perf_event_attr() + attr.type =3D PERF_TYPE_SOFTWARE + attr.config =3D config + attr.read_format =3D PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_= TIME_RUNNING + attr.disabled =3D 1 + attr.size =3D 136 + attr.sample_type =3D PERF_SAMPLE_IDENTIFIER + return attr + +libperf_init(None) +threads =3D perf_thread_map__new_dummy() +assert(threads) +perf_thread_map__set_pid(threads, 0, 0) + +evlist =3D perf_evlist__new() +assert(evlist) + +attr1 =3D get_attr(PERF_COUNT_SW_CPU_CLOCK) +evsel =3D perf_evsel__new(attr1) +assert(evsel) +perf_evlist__add(evlist, evsel) + +attr2 =3D get_attr(PERF_COUNT_SW_TASK_CLOCK) +evsel =3D perf_evsel__new(attr2) +assert(evsel) +perf_evlist__add(evlist, evsel) + +perf_evlist__set_maps(evlist, None, threads) +rc =3D perf_evlist__open(evlist) +if rc !=3D 0: + print("failed to open evsel: ", rc) + +perf_evlist__enable(evlist) + +count =3D 100000 +while count >=3D 0: + count-=3D1 + +perf_evlist__disable(evlist) +c =3D perf_counts_values() +for sel in evlist: + perf_evsel__read(sel, 0, 0, c); + print("count %lu, enabled %lu, run %lu" %(c.val, c.ena, c.run)) + +perf_evlist__close(evlist); +perf_evlist__delete(evlist); +perf_thread_map__put(threads); --=20 2.47.0