diff options
author | Khang Nguyen <khang.nguyen.xw@renesas.com> | 2019-10-29 16:13:15 +0700 |
---|---|---|
committer | Khang Nguyen <khang.nguyen.xw@renesas.com> | 2019-12-24 15:24:24 +0700 |
commit | 54ba967ecfb16553bb555a373212a93690a52ae5 (patch) | |
tree | ba91ca087a0cf16d28113713af51c6b6cde863f5 | |
parent | 2fc563b1979b272c68c59005ed5a1717871034b5 (diff) |
rcar-gen3: linux-renesas: Fix Perf build failure with 4.14 kernel
OE-Core started using Python3 for perf module. But older
kernel such as 4.14 does not have support for python3.
This causes build failure as follows:
| Makefile.config:391: DWARF support is off, BPF prologue is disabled
| Makefile.config:588: Missing perl devel files. Disabling perl scripting support, please install perl-ExtUtils-Embed/libperl-dev
| Makefile.config:626: Python 3 is not yet supported; please set
| Makefile.config:627: PYTHON and/or PYTHON_CONFIG appropriately.
| Makefile.config:628: If you also have Python 2 installed, then
| Makefile.config:629: try something like:
Backported python3 support, as a suggestion here:
https://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/meta/recipes-kernel/perf?id=92469aad50b623afa423c19d82ed2e3c667c5e6a
This fix was backported from:
https://lists.yoctoproject.org/pipermail/meta-intel/2019-September/006191.html
Signed-off-by: Khang Nguyen <khang.nguyen.xw@renesas.com>
Signed-off-by: Takamitsu Honda <takamitsu.honda.pv@renesas.com>
Change-Id: Ieaad61fb9bd4888e6226c8e00d4807f738cc0b55
4 files changed, 1844 insertions, 0 deletions
diff --git a/meta-rcar-gen3/recipes-kernel/linux-libc-headers/linux-libc-headers/0001-perf-tools-Add-Python-3-support.patch b/meta-rcar-gen3/recipes-kernel/linux-libc-headers/linux-libc-headers/0001-perf-tools-Add-Python-3-support.patch new file mode 100644 index 0000000..74ce61e --- /dev/null +++ b/meta-rcar-gen3/recipes-kernel/linux-libc-headers/linux-libc-headers/0001-perf-tools-Add-Python-3-support.patch @@ -0,0 +1,917 @@ +From 8804547988bb772a00cd4bb832fe4e1a79f552b7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= <jskarvad@redhat.com> +Date: Fri, 19 Jan 2018 21:56:41 +0100 +Subject: [PATCH] perf tools: Add Python 3 support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Added Python 3 support while keeping Python 2.7 compatibility. + +Committer notes: + +This doesn't make it to auto detect python 3, one has to explicitely ask +it to build with python 3 devel files, here are the instructions +provided by Jaroslav: + + --- + $ cp -a tools/perf tools/python3-perf + $ make V=1 prefix=/usr -C tools/perf PYTHON=/usr/bin/python2 all + $ make V=1 prefix=/usr -C tools/python3-perf PYTHON=/usr/bin/python3 all + $ make V=1 prefix=/usr -C tools/python3-perf PYTHON=/usr/bin/python3 DESTDIR=%{buildroot} install-python_ext + $ make V=1 prefix=/usr -C tools/perf PYTHON=/usr/bin/python2 DESTDIR=%{buildroot} install-python_ext + --- + +We need to make this automatic, just like the existing tests for checking if +the python2 devel files are in place, allowing the build with python3 if +available, fallbacking to python2 and then just disabling it if none are +available. + +So, using the PYTHON variable to build it using O= we get: + +Before this patch: + + $ rpm -q python3 python3-devel + python3-3.6.4-7.fc27.x86_64 + python3-devel-3.6.4-7.fc27.x86_64 + $ rm -rf /tmp/build/perf/ ; mkdir -p /tmp/build/perf ; make O=/tmp/build/perf PYTHON=/usr/bin/python3 -C tools/perf install-bin + make: Entering directory '/home/acme/git/linux/tools/perf' + <SNIP> + Makefile.config:670: Python 3 is not yet supported; please set + Makefile.config:671: PYTHON and/or PYTHON_CONFIG appropriately. + Makefile.config:672: If you also have Python 2 installed, then + Makefile.config:673: try something like: + Makefile.config:674: + Makefile.config:675: make PYTHON=python2 + Makefile.config:676: + Makefile.config:677: Otherwise, disable Python support entirely: + Makefile.config:678: + Makefile.config:679: make NO_LIBPYTHON=1 + Makefile.config:680: + Makefile.config:681: *** . Stop. + make[1]: *** [Makefile.perf:212: sub-make] Error 2 + make: *** [Makefile:110: install-bin] Error 2 + make: Leaving directory '/home/acme/git/linux/tools/perf' + $ + +After: + + $ make O=/tmp/build/perf PYTHON=python3 -C tools/perf install-bin + $ ldd ~/bin/perf | grep python + libpython3.6m.so.1.0 => /lib64/libpython3.6m.so.1.0 (0x00007f58a31e8000) + $ rpm -qf /lib64/libpython3.6m.so.1.0 + python3-libs-3.6.4-7.fc27.x86_64 + $ + +Now verify that when using the binding the right ELF file is loaded, +using perf trace: + + $ perf trace -e open* perf test python + 0.051 ( 0.016 ms): perf/3927 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC ) = 3 +<SNIP> + 18: 'import perf' in python : + 8.849 ( 0.013 ms): sh/3929 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC ) = 3 +<SNIP> + 25.572 ( 0.008 ms): python3/3931 openat(dfd: CWD, filename: /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so, flags: CLOEXEC) = 3 +<SNIP> + Ok +<SNIP> + $ + +And using tools/perf/python/twatch.py, to show PERF_RECORD_ metaevents: + + $ python3 tools/perf/python/twatch.py + cpu: 3, pid: 16060, tid: 16060 { type: fork, pid: 5207, ppid: 16060, tid: 5207, ptid: 16060, time: 10798513015459} + cpu: 3, pid: 16060, tid: 16060 { type: fork, pid: 5208, ppid: 16060, tid: 5208, ptid: 16060, time: 10798513562503} + cpu: 0, pid: 5208, tid: 5208 { type: comm, pid: 5208, tid: 5208, comm: grep } + cpu: 2, pid: 5207, tid: 5207 { type: comm, pid: 5207, tid: 5207, comm: ps } + cpu: 2, pid: 5207, tid: 5207 { type: exit, pid: 5207, ppid: 5207, tid: 5207, ptid: 5207, time: 10798551337484} + cpu: 3, pid: 5208, tid: 5208 { type: exit, pid: 5208, ppid: 5208, tid: 5208, ptid: 5208, time: 10798551292153} + cpu: 3, pid: 601, tid: 601 { type: fork, pid: 5209, ppid: 601, tid: 5209, ptid: 601, time: 10801779977324} + ^CTraceback (most recent call last): + File "tools/perf/python/twatch.py", line 68, in <module> + main() + File "tools/perf/python/twatch.py", line 40, in main + evlist.poll(timeout = -1) + KeyboardInterrupt + $ + + # ps ax|grep twatch + 5197 pts/8 S+ 0:00 python3 tools/perf/python/twatch.py + # ls -la /proc/5197/smaps + -r--r--r--. 1 acme acme 0 Feb 19 13:14 /proc/5197/smaps + # grep python /proc/5197/smaps + 558111307000-558111309000 r-xp 00000000 fd:00 3151710 /usr/bin/python3.6 + 558111508000-558111509000 r--p 00001000 fd:00 3151710 /usr/bin/python3.6 + 558111509000-55811150a000 rw-p 00002000 fd:00 3151710 /usr/bin/python3.6 + 7ffad6fc1000-7ffad7008000 r-xp 00000000 00:2d 220196 /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so + 7ffad7008000-7ffad7207000 ---p 00047000 00:2d 220196 /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so + 7ffad7207000-7ffad7208000 r--p 00046000 00:2d 220196 /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so + 7ffad7208000-7ffad7215000 rw-p 00047000 00:2d 220196 /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so + 7ffadea77000-7ffaded3d000 r-xp 00000000 fd:00 3151795 /usr/lib64/libpython3.6m.so.1.0 + 7ffaded3d000-7ffadef3c000 ---p 002c6000 fd:00 3151795 /usr/lib64/libpython3.6m.so.1.0 + 7ffadef3c000-7ffadef42000 r--p 002c5000 fd:00 3151795 /usr/lib64/libpython3.6m.so.1.0 + 7ffadef42000-7ffadefa5000 rw-p 002cb000 fd:00 3151795 /usr/lib64/libpython3.6m.so.1.0 + # + +And with this patch, but building normally, without specifying the +PYTHON=python3 part, which will make it use python2 if its devel files are +available, like in this test: + + $ make O=/tmp/build/perf -C tools/perf install-bin + $ ldd ~/bin/perf | grep python + libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0 (0x00007f6a44410000) + $ ldd /tmp/build/perf/python_ext_build/lib/perf.so | grep python + libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0 (0x00007fed28a2c000) + $ + + [acme@jouet perf]$ tools/perf/python/twatch.py + cpu: 0, pid: 2817, tid: 2817 { type: fork, pid: 2817, ppid: 2817, tid: 8910, ptid: 2817, time: 11126454335306} + cpu: 0, pid: 2817, tid: 2817 { type: comm, pid: 2817, tid: 8910, comm: worker } + $ ps ax | grep twatch.py + 8909 pts/8 S+ 0:00 /usr/bin/python tools/perf/python/twatch.py + $ grep python /proc/8909/smaps + 5579de658000-5579de659000 r-xp 00000000 fd:00 3156044 /usr/bin/python2.7 + 5579de858000-5579de859000 r--p 00000000 fd:00 3156044 /usr/bin/python2.7 + 5579de859000-5579de85a000 rw-p 00001000 fd:00 3156044 /usr/bin/python2.7 + 7f0de01f7000-7f0de023e000 r-xp 00000000 00:2d 230695 /tmp/build/perf/python/perf.so + 7f0de023e000-7f0de043d000 ---p 00047000 00:2d 230695 /tmp/build/perf/python/perf.so + 7f0de043d000-7f0de043e000 r--p 00046000 00:2d 230695 /tmp/build/perf/python/perf.so + 7f0de043e000-7f0de044b000 rw-p 00047000 00:2d 230695 /tmp/build/perf/python/perf.so + 7f0de6f0f000-7f0de6f13000 r-xp 00000000 fd:00 134975 /usr/lib64/python2.7/lib-dynload/_localemodule.so + 7f0de6f13000-7f0de7113000 ---p 00004000 fd:00 134975 /usr/lib64/python2.7/lib-dynload/_localemodule.so + 7f0de7113000-7f0de7114000 r--p 00004000 fd:00 134975 /usr/lib64/python2.7/lib-dynload/_localemodule.so + 7f0de7114000-7f0de7115000 rw-p 00005000 fd:00 134975 /usr/lib64/python2.7/lib-dynload/_localemodule.so + 7f0de7e73000-7f0de8052000 r-xp 00000000 fd:00 3173292 /usr/lib64/libpython2.7.so.1.0 + 7f0de8052000-7f0de8251000 ---p 001df000 fd:00 3173292 /usr/lib64/libpython2.7.so.1.0 + 7f0de8251000-7f0de8255000 r--p 001de000 fd:00 3173292 /usr/lib64/libpython2.7.so.1.0 + 7f0de8255000-7f0de8291000 rw-p 001e2000 fd:00 3173292 /usr/lib64/libpython2.7.so.1.0 + $ + +Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com> +Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Cc: Adrian Hunter <adrian.hunter@intel.com> +Cc: David Ahern <dsahern@gmail.com> +Cc: Jiri Olsa <jolsa@kernel.org> +Cc: Namhyung Kim <namhyung@kernel.org> +Cc: Wang Nan <wangnan0@huawei.com> +LPU-Reference: 20180119205641.24242-1-jskarvad@redhat.com +Link: https://lkml.kernel.org/n/tip-8d7dt9kqp83vsz25hagug8fu@git.kernel.org +[ Removed explicit check for python version, allowing it to really build with python3 ] +Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> + +Upstream status: Backport [https://github.com/torvalds/linux/commit/66dfdff03d196e51322c6a85c0d8db8bb2bdd655] +Signed-off-by: Naveen Saini <naveen.kumar.saini@intel.com> +--- + tools/perf/Makefile.config | 23 +-- + tools/perf/Makefile.perf | 4 +- + .../scripts/python/Perf-Trace-Util/Context.c | 34 +++- + tools/perf/util/python.c | 95 ++++++++--- + .../scripting-engines/trace-event-python.c | 147 +++++++++++++----- + tools/perf/util/setup.py | 6 +- + 6 files changed, 221 insertions(+), 88 deletions(-) + +diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config +index f362ee46506a..ecdc3770d899 100644 +--- a/tools/perf/Makefile.config ++++ b/tools/perf/Makefile.config +@@ -622,25 +622,10 @@ else + ifneq ($(feature-libpython), 1) + $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev) + else +- ifneq ($(feature-libpython-version), 1) +- $(warning Python 3 is not yet supported; please set) +- $(warning PYTHON and/or PYTHON_CONFIG appropriately.) +- $(warning If you also have Python 2 installed, then) +- $(warning try something like:) +- $(warning $(and ,)) +- $(warning $(and ,) make PYTHON=python2) +- $(warning $(and ,)) +- $(warning Otherwise, disable Python support entirely:) +- $(warning $(and ,)) +- $(warning $(and ,) make NO_LIBPYTHON=1) +- $(warning $(and ,)) +- $(error $(and ,)) +- else +- LDFLAGS += $(PYTHON_EMBED_LDFLAGS) +- EXTLIBS += $(PYTHON_EMBED_LIBADD) +- LANG_BINDINGS += $(obj-perf)python/perf.so +- $(call detected,CONFIG_LIBPYTHON) +- endif ++ LDFLAGS += $(PYTHON_EMBED_LDFLAGS) ++ EXTLIBS += $(PYTHON_EMBED_LIBADD) ++ LANG_BINDINGS += $(obj-perf)python/perf.so ++ $(call detected,CONFIG_LIBPYTHON) + endif + endif + endif +diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf +index 349ea5133d83..6879321c612d 100644 +--- a/tools/perf/Makefile.perf ++++ b/tools/perf/Makefile.perf +@@ -294,7 +294,7 @@ PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/ + PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/ + export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP + +-python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so ++python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf*.so + + PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) + PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) +@@ -444,7 +444,7 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_D + $(PYTHON_WORD) util/setup.py \ + --quiet build_ext; \ + mkdir -p $(OUTPUT)python && \ +- cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ ++ cp $(PYTHON_EXTBUILD_LIB)perf*.so $(OUTPUT)python/ + + please_set_SHELL_PATH_to_a_more_modern_shell: + $(Q)$$(:) +diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c +index fcd1dd667906..1a0d27757eec 100644 +--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c ++++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c +@@ -23,7 +23,17 @@ + #include "../../../perf.h" + #include "../../../util/trace-event.h" + ++#if PY_MAJOR_VERSION < 3 ++#define _PyCapsule_GetPointer(arg1, arg2) \ ++ PyCObject_AsVoidPtr(arg1) ++ + PyMODINIT_FUNC initperf_trace_context(void); ++#else ++#define _PyCapsule_GetPointer(arg1, arg2) \ ++ PyCapsule_GetPointer((arg1), (arg2)) ++ ++PyMODINIT_FUNC PyInit_perf_trace_context(void); ++#endif + + static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args) + { +@@ -34,7 +44,7 @@ static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args) + if (!PyArg_ParseTuple(args, "O", &context)) + return NULL; + +- scripting_context = PyCObject_AsVoidPtr(context); ++ scripting_context = _PyCapsule_GetPointer(context, NULL); + retval = common_pc(scripting_context); + + return Py_BuildValue("i", retval); +@@ -50,7 +60,7 @@ static PyObject *perf_trace_context_common_flags(PyObject *obj, + if (!PyArg_ParseTuple(args, "O", &context)) + return NULL; + +- scripting_context = PyCObject_AsVoidPtr(context); ++ scripting_context = _PyCapsule_GetPointer(context, NULL); + retval = common_flags(scripting_context); + + return Py_BuildValue("i", retval); +@@ -66,7 +76,7 @@ static PyObject *perf_trace_context_common_lock_depth(PyObject *obj, + if (!PyArg_ParseTuple(args, "O", &context)) + return NULL; + +- scripting_context = PyCObject_AsVoidPtr(context); ++ scripting_context = _PyCapsule_GetPointer(context, NULL); + retval = common_lock_depth(scripting_context); + + return Py_BuildValue("i", retval); +@@ -82,7 +92,25 @@ static PyMethodDef ContextMethods[] = { + { NULL, NULL, 0, NULL} + }; + ++#if PY_MAJOR_VERSION < 3 + PyMODINIT_FUNC initperf_trace_context(void) + { + (void) Py_InitModule("perf_trace_context", ContextMethods); + } ++#else ++PyMODINIT_FUNC PyInit_perf_trace_context(void) ++{ ++ static struct PyModuleDef moduledef = { ++ PyModuleDef_HEAD_INIT, ++ "perf_trace_context", /* m_name */ ++ "", /* m_doc */ ++ -1, /* m_size */ ++ ContextMethods, /* m_methods */ ++ NULL, /* m_reload */ ++ NULL, /* m_traverse */ ++ NULL, /* m_clear */ ++ NULL, /* m_free */ ++ }; ++ return PyModule_Create(&moduledef); ++} ++#endif +diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c +index 8e49d9cafcfc..16620c37fd8c 100644 +--- a/tools/perf/util/python.c ++++ b/tools/perf/util/python.c +@@ -12,6 +12,30 @@ + #include "print_binary.h" + #include "thread_map.h" + ++#if PY_MAJOR_VERSION < 3 ++#define _PyUnicode_FromString(arg) \ ++ PyString_FromString(arg) ++#define _PyUnicode_AsString(arg) \ ++ PyString_AsString(arg) ++#define _PyUnicode_FromFormat(...) \ ++ PyString_FromFormat(__VA_ARGS__) ++#define _PyLong_FromLong(arg) \ ++ PyInt_FromLong(arg) ++ ++#else ++ ++#define _PyUnicode_FromString(arg) \ ++ PyUnicode_FromString(arg) ++#define _PyUnicode_FromFormat(...) \ ++ PyUnicode_FromFormat(__VA_ARGS__) ++#define _PyLong_FromLong(arg) \ ++ PyLong_FromLong(arg) ++#endif ++ ++#ifndef Py_TYPE ++#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) ++#endif ++ + /* + * Provide these two so that we don't have to link against callchain.c and + * start dragging hist.c, etc. +@@ -49,7 +73,11 @@ int eprintf(int level, int var, const char *fmt, ...) + # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, + #endif + ++#if PY_MAJOR_VERSION < 3 + PyMODINIT_FUNC initperf(void); ++#else ++PyMODINIT_FUNC PyInit_perf(void); ++#endif + + #define member_def(type, member, ptype, help) \ + { #member, ptype, \ +@@ -107,7 +135,7 @@ static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent) + pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { + ret = PyErr_NoMemory(); + } else { +- ret = PyString_FromString(s); ++ ret = _PyUnicode_FromString(s); + free(s); + } + return ret; +@@ -138,7 +166,7 @@ static PyMemberDef pyrf_task_event__members[] = { + + static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent) + { +- return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " ++ return _PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " + "ptid: %u, time: %" PRIu64 "}", + pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", + pevent->event.fork.pid, +@@ -171,7 +199,7 @@ static PyMemberDef pyrf_comm_event__members[] = { + + static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent) + { +- return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", ++ return _PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", + pevent->event.comm.pid, + pevent->event.comm.tid, + pevent->event.comm.comm); +@@ -202,7 +230,7 @@ static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent) + { + struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1); + +- return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 ++ return _PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 + ", stream_id: %" PRIu64 " }", + pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", + te->time, te->id, te->stream_id); +@@ -237,7 +265,7 @@ static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent) + pevent->event.lost.id, pevent->event.lost.lost) < 0) { + ret = PyErr_NoMemory(); + } else { +- ret = PyString_FromString(s); ++ ret = _PyUnicode_FromString(s); + free(s); + } + return ret; +@@ -264,7 +292,7 @@ static PyMemberDef pyrf_read_event__members[] = { + + static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent) + { +- return PyString_FromFormat("{ type: read, pid: %u, tid: %u }", ++ return _PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }", + pevent->event.read.pid, + pevent->event.read.tid); + /* +@@ -299,7 +327,7 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent) + if (asprintf(&s, "{ type: sample }") < 0) { + ret = PyErr_NoMemory(); + } else { +- ret = PyString_FromString(s); ++ ret = _PyUnicode_FromString(s); + free(s); + } + return ret; +@@ -330,7 +358,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field) + } + if (field->flags & FIELD_IS_STRING && + is_printable_array(data + offset, len)) { +- ret = PyString_FromString((char *)data + offset); ++ ret = _PyUnicode_FromString((char *)data + offset); + } else { + ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); + field->flags &= ~FIELD_IS_STRING; +@@ -352,7 +380,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field) + static PyObject* + get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) + { +- const char *str = PyString_AsString(PyObject_Str(attr_name)); ++ const char *str = _PyUnicode_AsString(PyObject_Str(attr_name)); + struct perf_evsel *evsel = pevent->evsel; + struct format_field *field; + +@@ -416,7 +444,7 @@ static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent) + !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { + ret = PyErr_NoMemory(); + } else { +- ret = PyString_FromString(s); ++ ret = _PyUnicode_FromString(s); + free(s); + } + return ret; +@@ -528,7 +556,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, + static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) + { + cpu_map__put(pcpus->cpus); +- pcpus->ob_type->tp_free((PyObject*)pcpus); ++ Py_TYPE(pcpus)->tp_free((PyObject*)pcpus); + } + + static Py_ssize_t pyrf_cpu_map__length(PyObject *obj) +@@ -597,7 +625,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, + static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) + { + thread_map__put(pthreads->threads); +- pthreads->ob_type->tp_free((PyObject*)pthreads); ++ Py_TYPE(pthreads)->tp_free((PyObject*)pthreads); + } + + static Py_ssize_t pyrf_thread_map__length(PyObject *obj) +@@ -759,7 +787,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel, + static void pyrf_evsel__delete(struct pyrf_evsel *pevsel) + { + perf_evsel__exit(&pevsel->evsel); +- pevsel->ob_type->tp_free((PyObject*)pevsel); ++ Py_TYPE(pevsel)->tp_free((PyObject*)pevsel); + } + + static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, +@@ -850,7 +878,7 @@ static int pyrf_evlist__init(struct pyrf_evlist *pevlist, + static void pyrf_evlist__delete(struct pyrf_evlist *pevlist) + { + perf_evlist__exit(&pevlist->evlist); +- pevlist->ob_type->tp_free((PyObject*)pevlist); ++ Py_TYPE(pevlist)->tp_free((PyObject*)pevlist); + } + + static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, +@@ -902,12 +930,16 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist, + + for (i = 0; i < evlist->pollfd.nr; ++i) { + PyObject *file; ++#if PY_MAJOR_VERSION < 3 + FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r"); + + if (fp == NULL) + goto free_list; + + file = PyFile_FromFile(fp, "perf", "r", NULL); ++#else ++ file = PyFile_FromFd(evlist->pollfd.entries[i].fd, "perf", "r", -1, NULL, NULL, NULL, 1); ++#endif + if (file == NULL) + goto free_list; + +@@ -1194,9 +1226,9 @@ static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel, + + tp_format = trace_event__tp_format(sys, name); + if (IS_ERR(tp_format)) +- return PyInt_FromLong(-1); ++ return _PyLong_FromLong(-1); + +- return PyInt_FromLong(tp_format->id); ++ return _PyLong_FromLong(tp_format->id); + } + + static PyMethodDef perf__methods[] = { +@@ -1209,11 +1241,31 @@ static PyMethodDef perf__methods[] = { + { .ml_name = NULL, } + }; + ++#if PY_MAJOR_VERSION < 3 + PyMODINIT_FUNC initperf(void) ++#else ++PyMODINIT_FUNC PyInit_perf(void) ++#endif + { + PyObject *obj; + int i; +- PyObject *dict, *module = Py_InitModule("perf", perf__methods); ++ PyObject *dict; ++#if PY_MAJOR_VERSION < 3 ++ PyObject *module = Py_InitModule("perf", perf__methods); ++#else ++ static struct PyModuleDef moduledef = { ++ PyModuleDef_HEAD_INIT, ++ "perf", /* m_name */ ++ "", /* m_doc */ ++ -1, /* m_size */ ++ perf__methods, /* m_methods */ ++ NULL, /* m_reload */ ++ NULL, /* m_traverse */ ++ NULL, /* m_clear */ ++ NULL, /* m_free */ ++ }; ++ PyObject *module = PyModule_Create(&moduledef); ++#endif + + if (module == NULL || + pyrf_event__setup_types() < 0 || +@@ -1221,7 +1273,11 @@ PyMODINIT_FUNC initperf(void) + pyrf_evsel__setup_types() < 0 || + pyrf_thread_map__setup_types() < 0 || + pyrf_cpu_map__setup_types() < 0) ++#if PY_MAJOR_VERSION < 3 + return; ++#else ++ return module; ++#endif + + /* The page_size is placed in util object. */ + page_size = sysconf(_SC_PAGE_SIZE); +@@ -1270,7 +1326,7 @@ PyMODINIT_FUNC initperf(void) + goto error; + + for (i = 0; perf__constants[i].name != NULL; i++) { +- obj = PyInt_FromLong(perf__constants[i].value); ++ obj = _PyLong_FromLong(perf__constants[i].value); + if (obj == NULL) + goto error; + PyDict_SetItemString(dict, perf__constants[i].name, obj); +@@ -1280,6 +1336,9 @@ PyMODINIT_FUNC initperf(void) + error: + if (PyErr_Occurred()) + PyErr_SetString(PyExc_ImportError, "perf: Init failed!"); ++#if PY_MAJOR_VERSION >= 3 ++ return module; ++#endif + } + + /* +diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c +index f03fa7a835a1..8db28d4ff4b6 100644 +--- a/tools/perf/util/scripting-engines/trace-event-python.c ++++ b/tools/perf/util/scripting-engines/trace-event-python.c +@@ -50,7 +50,37 @@ + #include "print_binary.h" + #include "stat.h" + ++#if PY_MAJOR_VERSION < 3 ++#define _PyUnicode_FromString(arg) \ ++ PyString_FromString(arg) ++#define _PyUnicode_FromStringAndSize(arg1, arg2) \ ++ PyString_FromStringAndSize((arg1), (arg2)) ++#define _PyBytes_FromStringAndSize(arg1, arg2) \ ++ PyString_FromStringAndSize((arg1), (arg2)) ++#define _PyLong_FromLong(arg) \ ++ PyInt_FromLong(arg) ++#define _PyLong_AsLong(arg) \ ++ PyInt_AsLong(arg) ++#define _PyCapsule_New(arg1, arg2, arg3) \ ++ PyCObject_FromVoidPtr((arg1), (arg2)) ++ + PyMODINIT_FUNC initperf_trace_context(void); ++#else ++#define _PyUnicode_FromString(arg) \ ++ PyUnicode_FromString(arg) ++#define _PyUnicode_FromStringAndSize(arg1, arg2) \ ++ PyUnicode_FromStringAndSize((arg1), (arg2)) ++#define _PyBytes_FromStringAndSize(arg1, arg2) \ ++ PyBytes_FromStringAndSize((arg1), (arg2)) ++#define _PyLong_FromLong(arg) \ ++ PyLong_FromLong(arg) ++#define _PyLong_AsLong(arg) \ ++ PyLong_AsLong(arg) ++#define _PyCapsule_New(arg1, arg2, arg3) \ ++ PyCapsule_New((arg1), (arg2), (arg3)) ++ ++PyMODINIT_FUNC PyInit_perf_trace_context(void); ++#endif + + #define TRACE_EVENT_TYPE_MAX \ + ((1 << (sizeof(unsigned short) * 8)) - 1) +@@ -136,7 +166,7 @@ static int get_argument_count(PyObject *handler) + PyObject *arg_count_obj = PyObject_GetAttrString(code_obj, + "co_argcount"); + if (arg_count_obj) { +- arg_count = (int) PyInt_AsLong(arg_count_obj); ++ arg_count = (int) _PyLong_AsLong(arg_count_obj); + Py_DECREF(arg_count_obj); + } + Py_DECREF(code_obj); +@@ -183,10 +213,10 @@ static void define_value(enum print_arg_type field_type, + + value = eval_flag(field_value); + +- PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); +- PyTuple_SetItem(t, n++, PyString_FromString(field_name)); +- PyTuple_SetItem(t, n++, PyInt_FromLong(value)); +- PyTuple_SetItem(t, n++, PyString_FromString(field_str)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(value)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_str)); + + try_call_object(handler_name, t); + +@@ -224,10 +254,10 @@ static void define_field(enum print_arg_type field_type, + if (!t) + Py_FatalError("couldn't create Python tuple"); + +- PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); +- PyTuple_SetItem(t, n++, PyString_FromString(field_name)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); + if (field_type == PRINT_FLAGS) +- PyTuple_SetItem(t, n++, PyString_FromString(delim)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim)); + + try_call_object(handler_name, t); + +@@ -326,12 +356,12 @@ static PyObject *get_field_numeric_entry(struct event_format *event, + if (field->flags & FIELD_IS_SIGNED) { + if ((long long)val >= LONG_MIN && + (long long)val <= LONG_MAX) +- obj = PyInt_FromLong(val); ++ obj = _PyLong_FromLong(val); + else + obj = PyLong_FromLongLong(val); + } else { + if (val <= LONG_MAX) +- obj = PyInt_FromLong(val); ++ obj = _PyLong_FromLong(val); + else + obj = PyLong_FromUnsignedLongLong(val); + } +@@ -390,9 +420,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample, + pydict_set_item_string_decref(pysym, "end", + PyLong_FromUnsignedLongLong(node->sym->end)); + pydict_set_item_string_decref(pysym, "binding", +- PyInt_FromLong(node->sym->binding)); ++ _PyLong_FromLong(node->sym->binding)); + pydict_set_item_string_decref(pysym, "name", +- PyString_FromStringAndSize(node->sym->name, ++ _PyUnicode_FromStringAndSize(node->sym->name, + node->sym->namelen)); + pydict_set_item_string_decref(pyelem, "sym", pysym); + } +@@ -407,7 +437,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample, + dsoname = map->dso->name; + } + pydict_set_item_string_decref(pyelem, "dso", +- PyString_FromString(dsoname)); ++ _PyUnicode_FromString(dsoname)); + } + + callchain_cursor_advance(&callchain_cursor); +@@ -484,16 +514,16 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, + if (!dict_sample) + Py_FatalError("couldn't create Python dictionary"); + +- pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); +- pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( ++ pydict_set_item_string_decref(dict, "ev_name", _PyUnicode_FromString(perf_evsel__name(evsel))); ++ pydict_set_item_string_decref(dict, "attr", _PyUnicode_FromStringAndSize( + (const char *)&evsel->attr, sizeof(evsel->attr))); + + pydict_set_item_string_decref(dict_sample, "pid", +- PyInt_FromLong(sample->pid)); ++ _PyLong_FromLong(sample->pid)); + pydict_set_item_string_decref(dict_sample, "tid", +- PyInt_FromLong(sample->tid)); ++ _PyLong_FromLong(sample->tid)); + pydict_set_item_string_decref(dict_sample, "cpu", +- PyInt_FromLong(sample->cpu)); ++ _PyLong_FromLong(sample->cpu)); + pydict_set_item_string_decref(dict_sample, "ip", + PyLong_FromUnsignedLongLong(sample->ip)); + pydict_set_item_string_decref(dict_sample, "time", +@@ -503,17 +533,17 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, + set_sample_read_in_dict(dict_sample, sample, evsel); + pydict_set_item_string_decref(dict, "sample", dict_sample); + +- pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( ++ pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize( + (const char *)sample->raw_data, sample->raw_size)); + pydict_set_item_string_decref(dict, "comm", +- PyString_FromString(thread__comm_str(al->thread))); ++ _PyUnicode_FromString(thread__comm_str(al->thread))); + if (al->map) { + pydict_set_item_string_decref(dict, "dso", +- PyString_FromString(al->map->dso->name)); ++ _PyUnicode_FromString(al->map->dso->name)); + } + if (al->sym) { + pydict_set_item_string_decref(dict, "symbol", +- PyString_FromString(al->sym->name)); ++ _PyUnicode_FromString(al->sym->name)); + } + + pydict_set_item_string_decref(dict, "callchain", callchain); +@@ -573,9 +603,9 @@ static void python_process_tracepoint(struct perf_sample *sample, + scripting_context->event_data = data; + scripting_context->pevent = evsel->tp_format->pevent; + +- context = PyCObject_FromVoidPtr(scripting_context, NULL); ++ context = _PyCapsule_New(scripting_context, NULL, NULL); + +- PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(handler_name)); + PyTuple_SetItem(t, n++, context); + + /* ip unwinding */ +@@ -584,18 +614,18 @@ static void python_process_tracepoint(struct perf_sample *sample, + Py_INCREF(callchain); + + if (!dict) { +- PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); +- PyTuple_SetItem(t, n++, PyInt_FromLong(s)); +- PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); +- PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); +- PyTuple_SetItem(t, n++, PyString_FromString(comm)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(s)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(ns)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(pid)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(comm)); + PyTuple_SetItem(t, n++, callchain); + } else { +- pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); +- pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); +- pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); +- pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); +- pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); ++ pydict_set_item_string_decref(dict, "common_cpu", _PyLong_FromLong(cpu)); ++ pydict_set_item_string_decref(dict, "common_s", _PyLong_FromLong(s)); ++ pydict_set_item_string_decref(dict, "common_ns", _PyLong_FromLong(ns)); ++ pydict_set_item_string_decref(dict, "common_pid", _PyLong_FromLong(pid)); ++ pydict_set_item_string_decref(dict, "common_comm", _PyUnicode_FromString(comm)); + pydict_set_item_string_decref(dict, "common_callchain", callchain); + } + for (field = event->format.fields; field; field = field->next) { +@@ -614,7 +644,7 @@ static void python_process_tracepoint(struct perf_sample *sample, + } + if (field->flags & FIELD_IS_STRING && + is_printable_array(data + offset, len)) { +- obj = PyString_FromString((char *) data + offset); ++ obj = _PyUnicode_FromString((char *) data + offset); + } else { + obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); + field->flags &= ~FIELD_IS_STRING; +@@ -664,7 +694,7 @@ static PyObject *tuple_new(unsigned int sz) + static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) + { + #if BITS_PER_LONG == 64 +- return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); ++ return PyTuple_SetItem(t, pos, _PyLong_FromLong(val)); + #endif + #if BITS_PER_LONG == 32 + return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); +@@ -673,12 +703,12 @@ static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) + + static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) + { +- return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); ++ return PyTuple_SetItem(t, pos, _PyLong_FromLong(val)); + } + + static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) + { +- return PyTuple_SetItem(t, pos, PyString_FromString(s)); ++ return PyTuple_SetItem(t, pos, _PyUnicode_FromString(s)); + } + + static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) +@@ -1024,8 +1054,8 @@ process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp, + return; + } + +- PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); +- PyTuple_SetItem(t, n++, PyInt_FromLong(thread)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(thread)); + + tuple_set_u64(t, n++, tstamp); + tuple_set_u64(t, n++, count->val); +@@ -1207,27 +1237,58 @@ static void set_table_handlers(struct tables *tables) + SET_TABLE_HANDLER(call_return); + } + ++#if PY_MAJOR_VERSION < 3 ++static void _free_command_line(const char **command_line, int num) ++{ ++ free(command_line); ++} ++#else ++static void _free_command_line(wchar_t **command_line, int num) ++{ ++ int i; ++ for (i = 0; i < num; i++) ++ PyMem_RawFree(command_line[i]); ++ free(command_line); ++} ++#endif ++ ++ + /* + * Start trace script + */ + static int python_start_script(const char *script, int argc, const char **argv) + { + struct tables *tables = &tables_global; ++#if PY_MAJOR_VERSION < 3 + const char **command_line; ++#else ++ wchar_t **command_line; ++#endif + char buf[PATH_MAX]; + int i, err = 0; + FILE *fp; + ++#if PY_MAJOR_VERSION < 3 + command_line = malloc((argc + 1) * sizeof(const char *)); + command_line[0] = script; + for (i = 1; i < argc + 1; i++) + command_line[i] = argv[i - 1]; ++#else ++ command_line = malloc((argc + 1) * sizeof(wchar_t *)); ++ command_line[0] = Py_DecodeLocale(script, NULL); ++ for (i = 1; i < argc + 1; i++) ++ command_line[i] = Py_DecodeLocale(argv[i - 1], NULL); ++#endif + + Py_Initialize(); + ++#if PY_MAJOR_VERSION < 3 + initperf_trace_context(); +- + PySys_SetArgv(argc + 1, (char **)command_line); ++#else ++ PyInit_perf_trace_context(); ++ PySys_SetArgv(argc + 1, command_line); ++#endif + + fp = fopen(script, "r"); + if (!fp) { +@@ -1257,12 +1318,12 @@ static int python_start_script(const char *script, int argc, const char **argv) + goto error; + } + +- free(command_line); ++ _free_command_line(command_line, argc + 1); + + return err; + error: + Py_Finalize(); +- free(command_line); ++ _free_command_line(command_line, argc + 1); + + return err; + } +diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py +index 23f1bf175179..a5f9e236cc71 100644 +--- a/tools/perf/util/setup.py ++++ b/tools/perf/util/setup.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/python2 ++#!/usr/bin/python + + from os import getenv + +@@ -37,11 +37,11 @@ build_tmp = getenv('PYTHON_EXTBUILD_TMP') + libtraceevent = getenv('LIBTRACEEVENT') + libapikfs = getenv('LIBAPI') + +-ext_sources = [f.strip() for f in file('util/python-ext-sources') ++ext_sources = [f.strip() for f in open('util/python-ext-sources') + if len(f.strip()) > 0 and f[0] != '#'] + + # use full paths with source files +-ext_sources = map(lambda x: '%s/%s' % (src_perf, x) , ext_sources) ++ext_sources = list(map(lambda x: '%s/%s' % (src_perf, x) , ext_sources)) + + perf = Extension('perf', + sources = ext_sources, +-- +2.17.1 + diff --git a/meta-rcar-gen3/recipes-kernel/linux-libc-headers/linux-libc-headers_4.14.bb b/meta-rcar-gen3/recipes-kernel/linux-libc-headers/linux-libc-headers_4.14.bb index 78f0ef1..2887f2f 100644 --- a/meta-rcar-gen3/recipes-kernel/linux-libc-headers/linux-libc-headers_4.14.bb +++ b/meta-rcar-gen3/recipes-kernel/linux-libc-headers/linux-libc-headers_4.14.bb @@ -11,6 +11,11 @@ SRC_URI = "${RENESAS_BSP_URL};branch=${BRANCH}" LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7" +# Add python3 support to fix Perf build failure +SRC_URI_append = " \ + file://0001-perf-tools-Add-Python-3-support.patch \ +" + # Enable RPMSG_VIRTIO depend on ICCOM SRC_URI_append = " \ ${@oe.utils.conditional("USE_ICCOM", "1", " file://0001-rpmsg-Add-message-to-be-able-to-configure-RPMSG_VIRT.patch", "", d)} \ diff --git a/meta-rcar-gen3/recipes-kernel/linux/linux-renesas/0001-perf-tools-Add-Python-3-support.patch b/meta-rcar-gen3/recipes-kernel/linux/linux-renesas/0001-perf-tools-Add-Python-3-support.patch new file mode 100644 index 0000000..74ce61e --- /dev/null +++ b/meta-rcar-gen3/recipes-kernel/linux/linux-renesas/0001-perf-tools-Add-Python-3-support.patch @@ -0,0 +1,917 @@ +From 8804547988bb772a00cd4bb832fe4e1a79f552b7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jaroslav=20=C5=A0karvada?= <jskarvad@redhat.com> +Date: Fri, 19 Jan 2018 21:56:41 +0100 +Subject: [PATCH] perf tools: Add Python 3 support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Added Python 3 support while keeping Python 2.7 compatibility. + +Committer notes: + +This doesn't make it to auto detect python 3, one has to explicitely ask +it to build with python 3 devel files, here are the instructions +provided by Jaroslav: + + --- + $ cp -a tools/perf tools/python3-perf + $ make V=1 prefix=/usr -C tools/perf PYTHON=/usr/bin/python2 all + $ make V=1 prefix=/usr -C tools/python3-perf PYTHON=/usr/bin/python3 all + $ make V=1 prefix=/usr -C tools/python3-perf PYTHON=/usr/bin/python3 DESTDIR=%{buildroot} install-python_ext + $ make V=1 prefix=/usr -C tools/perf PYTHON=/usr/bin/python2 DESTDIR=%{buildroot} install-python_ext + --- + +We need to make this automatic, just like the existing tests for checking if +the python2 devel files are in place, allowing the build with python3 if +available, fallbacking to python2 and then just disabling it if none are +available. + +So, using the PYTHON variable to build it using O= we get: + +Before this patch: + + $ rpm -q python3 python3-devel + python3-3.6.4-7.fc27.x86_64 + python3-devel-3.6.4-7.fc27.x86_64 + $ rm -rf /tmp/build/perf/ ; mkdir -p /tmp/build/perf ; make O=/tmp/build/perf PYTHON=/usr/bin/python3 -C tools/perf install-bin + make: Entering directory '/home/acme/git/linux/tools/perf' + <SNIP> + Makefile.config:670: Python 3 is not yet supported; please set + Makefile.config:671: PYTHON and/or PYTHON_CONFIG appropriately. + Makefile.config:672: If you also have Python 2 installed, then + Makefile.config:673: try something like: + Makefile.config:674: + Makefile.config:675: make PYTHON=python2 + Makefile.config:676: + Makefile.config:677: Otherwise, disable Python support entirely: + Makefile.config:678: + Makefile.config:679: make NO_LIBPYTHON=1 + Makefile.config:680: + Makefile.config:681: *** . Stop. + make[1]: *** [Makefile.perf:212: sub-make] Error 2 + make: *** [Makefile:110: install-bin] Error 2 + make: Leaving directory '/home/acme/git/linux/tools/perf' + $ + +After: + + $ make O=/tmp/build/perf PYTHON=python3 -C tools/perf install-bin + $ ldd ~/bin/perf | grep python + libpython3.6m.so.1.0 => /lib64/libpython3.6m.so.1.0 (0x00007f58a31e8000) + $ rpm -qf /lib64/libpython3.6m.so.1.0 + python3-libs-3.6.4-7.fc27.x86_64 + $ + +Now verify that when using the binding the right ELF file is loaded, +using perf trace: + + $ perf trace -e open* perf test python + 0.051 ( 0.016 ms): perf/3927 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC ) = 3 +<SNIP> + 18: 'import perf' in python : + 8.849 ( 0.013 ms): sh/3929 openat(dfd: CWD, filename: /etc/ld.so.cache, flags: CLOEXEC ) = 3 +<SNIP> + 25.572 ( 0.008 ms): python3/3931 openat(dfd: CWD, filename: /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so, flags: CLOEXEC) = 3 +<SNIP> + Ok +<SNIP> + $ + +And using tools/perf/python/twatch.py, to show PERF_RECORD_ metaevents: + + $ python3 tools/perf/python/twatch.py + cpu: 3, pid: 16060, tid: 16060 { type: fork, pid: 5207, ppid: 16060, tid: 5207, ptid: 16060, time: 10798513015459} + cpu: 3, pid: 16060, tid: 16060 { type: fork, pid: 5208, ppid: 16060, tid: 5208, ptid: 16060, time: 10798513562503} + cpu: 0, pid: 5208, tid: 5208 { type: comm, pid: 5208, tid: 5208, comm: grep } + cpu: 2, pid: 5207, tid: 5207 { type: comm, pid: 5207, tid: 5207, comm: ps } + cpu: 2, pid: 5207, tid: 5207 { type: exit, pid: 5207, ppid: 5207, tid: 5207, ptid: 5207, time: 10798551337484} + cpu: 3, pid: 5208, tid: 5208 { type: exit, pid: 5208, ppid: 5208, tid: 5208, ptid: 5208, time: 10798551292153} + cpu: 3, pid: 601, tid: 601 { type: fork, pid: 5209, ppid: 601, tid: 5209, ptid: 601, time: 10801779977324} + ^CTraceback (most recent call last): + File "tools/perf/python/twatch.py", line 68, in <module> + main() + File "tools/perf/python/twatch.py", line 40, in main + evlist.poll(timeout = -1) + KeyboardInterrupt + $ + + # ps ax|grep twatch + 5197 pts/8 S+ 0:00 python3 tools/perf/python/twatch.py + # ls -la /proc/5197/smaps + -r--r--r--. 1 acme acme 0 Feb 19 13:14 /proc/5197/smaps + # grep python /proc/5197/smaps + 558111307000-558111309000 r-xp 00000000 fd:00 3151710 /usr/bin/python3.6 + 558111508000-558111509000 r--p 00001000 fd:00 3151710 /usr/bin/python3.6 + 558111509000-55811150a000 rw-p 00002000 fd:00 3151710 /usr/bin/python3.6 + 7ffad6fc1000-7ffad7008000 r-xp 00000000 00:2d 220196 /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so + 7ffad7008000-7ffad7207000 ---p 00047000 00:2d 220196 /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so + 7ffad7207000-7ffad7208000 r--p 00046000 00:2d 220196 /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so + 7ffad7208000-7ffad7215000 rw-p 00047000 00:2d 220196 /tmp/build/perf/python/perf.cpython-36m-x86_64-linux-gnu.so + 7ffadea77000-7ffaded3d000 r-xp 00000000 fd:00 3151795 /usr/lib64/libpython3.6m.so.1.0 + 7ffaded3d000-7ffadef3c000 ---p 002c6000 fd:00 3151795 /usr/lib64/libpython3.6m.so.1.0 + 7ffadef3c000-7ffadef42000 r--p 002c5000 fd:00 3151795 /usr/lib64/libpython3.6m.so.1.0 + 7ffadef42000-7ffadefa5000 rw-p 002cb000 fd:00 3151795 /usr/lib64/libpython3.6m.so.1.0 + # + +And with this patch, but building normally, without specifying the +PYTHON=python3 part, which will make it use python2 if its devel files are +available, like in this test: + + $ make O=/tmp/build/perf -C tools/perf install-bin + $ ldd ~/bin/perf | grep python + libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0 (0x00007f6a44410000) + $ ldd /tmp/build/perf/python_ext_build/lib/perf.so | grep python + libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0 (0x00007fed28a2c000) + $ + + [acme@jouet perf]$ tools/perf/python/twatch.py + cpu: 0, pid: 2817, tid: 2817 { type: fork, pid: 2817, ppid: 2817, tid: 8910, ptid: 2817, time: 11126454335306} + cpu: 0, pid: 2817, tid: 2817 { type: comm, pid: 2817, tid: 8910, comm: worker } + $ ps ax | grep twatch.py + 8909 pts/8 S+ 0:00 /usr/bin/python tools/perf/python/twatch.py + $ grep python /proc/8909/smaps + 5579de658000-5579de659000 r-xp 00000000 fd:00 3156044 /usr/bin/python2.7 + 5579de858000-5579de859000 r--p 00000000 fd:00 3156044 /usr/bin/python2.7 + 5579de859000-5579de85a000 rw-p 00001000 fd:00 3156044 /usr/bin/python2.7 + 7f0de01f7000-7f0de023e000 r-xp 00000000 00:2d 230695 /tmp/build/perf/python/perf.so + 7f0de023e000-7f0de043d000 ---p 00047000 00:2d 230695 /tmp/build/perf/python/perf.so + 7f0de043d000-7f0de043e000 r--p 00046000 00:2d 230695 /tmp/build/perf/python/perf.so + 7f0de043e000-7f0de044b000 rw-p 00047000 00:2d 230695 /tmp/build/perf/python/perf.so + 7f0de6f0f000-7f0de6f13000 r-xp 00000000 fd:00 134975 /usr/lib64/python2.7/lib-dynload/_localemodule.so + 7f0de6f13000-7f0de7113000 ---p 00004000 fd:00 134975 /usr/lib64/python2.7/lib-dynload/_localemodule.so + 7f0de7113000-7f0de7114000 r--p 00004000 fd:00 134975 /usr/lib64/python2.7/lib-dynload/_localemodule.so + 7f0de7114000-7f0de7115000 rw-p 00005000 fd:00 134975 /usr/lib64/python2.7/lib-dynload/_localemodule.so + 7f0de7e73000-7f0de8052000 r-xp 00000000 fd:00 3173292 /usr/lib64/libpython2.7.so.1.0 + 7f0de8052000-7f0de8251000 ---p 001df000 fd:00 3173292 /usr/lib64/libpython2.7.so.1.0 + 7f0de8251000-7f0de8255000 r--p 001de000 fd:00 3173292 /usr/lib64/libpython2.7.so.1.0 + 7f0de8255000-7f0de8291000 rw-p 001e2000 fd:00 3173292 /usr/lib64/libpython2.7.so.1.0 + $ + +Signed-off-by: Jaroslav Škarvada <jskarvad@redhat.com> +Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Cc: Adrian Hunter <adrian.hunter@intel.com> +Cc: David Ahern <dsahern@gmail.com> +Cc: Jiri Olsa <jolsa@kernel.org> +Cc: Namhyung Kim <namhyung@kernel.org> +Cc: Wang Nan <wangnan0@huawei.com> +LPU-Reference: 20180119205641.24242-1-jskarvad@redhat.com +Link: https://lkml.kernel.org/n/tip-8d7dt9kqp83vsz25hagug8fu@git.kernel.org +[ Removed explicit check for python version, allowing it to really build with python3 ] +Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> + +Upstream status: Backport [https://github.com/torvalds/linux/commit/66dfdff03d196e51322c6a85c0d8db8bb2bdd655] +Signed-off-by: Naveen Saini <naveen.kumar.saini@intel.com> +--- + tools/perf/Makefile.config | 23 +-- + tools/perf/Makefile.perf | 4 +- + .../scripts/python/Perf-Trace-Util/Context.c | 34 +++- + tools/perf/util/python.c | 95 ++++++++--- + .../scripting-engines/trace-event-python.c | 147 +++++++++++++----- + tools/perf/util/setup.py | 6 +- + 6 files changed, 221 insertions(+), 88 deletions(-) + +diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config +index f362ee46506a..ecdc3770d899 100644 +--- a/tools/perf/Makefile.config ++++ b/tools/perf/Makefile.config +@@ -622,25 +622,10 @@ else + ifneq ($(feature-libpython), 1) + $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev) + else +- ifneq ($(feature-libpython-version), 1) +- $(warning Python 3 is not yet supported; please set) +- $(warning PYTHON and/or PYTHON_CONFIG appropriately.) +- $(warning If you also have Python 2 installed, then) +- $(warning try something like:) +- $(warning $(and ,)) +- $(warning $(and ,) make PYTHON=python2) +- $(warning $(and ,)) +- $(warning Otherwise, disable Python support entirely:) +- $(warning $(and ,)) +- $(warning $(and ,) make NO_LIBPYTHON=1) +- $(warning $(and ,)) +- $(error $(and ,)) +- else +- LDFLAGS += $(PYTHON_EMBED_LDFLAGS) +- EXTLIBS += $(PYTHON_EMBED_LIBADD) +- LANG_BINDINGS += $(obj-perf)python/perf.so +- $(call detected,CONFIG_LIBPYTHON) +- endif ++ LDFLAGS += $(PYTHON_EMBED_LDFLAGS) ++ EXTLIBS += $(PYTHON_EMBED_LIBADD) ++ LANG_BINDINGS += $(obj-perf)python/perf.so ++ $(call detected,CONFIG_LIBPYTHON) + endif + endif + endif +diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf +index 349ea5133d83..6879321c612d 100644 +--- a/tools/perf/Makefile.perf ++++ b/tools/perf/Makefile.perf +@@ -294,7 +294,7 @@ PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/ + PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/ + export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP + +-python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so ++python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf*.so + + PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) + PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) +@@ -444,7 +444,7 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_D + $(PYTHON_WORD) util/setup.py \ + --quiet build_ext; \ + mkdir -p $(OUTPUT)python && \ +- cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ ++ cp $(PYTHON_EXTBUILD_LIB)perf*.so $(OUTPUT)python/ + + please_set_SHELL_PATH_to_a_more_modern_shell: + $(Q)$$(:) +diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c +index fcd1dd667906..1a0d27757eec 100644 +--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c ++++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c +@@ -23,7 +23,17 @@ + #include "../../../perf.h" + #include "../../../util/trace-event.h" + ++#if PY_MAJOR_VERSION < 3 ++#define _PyCapsule_GetPointer(arg1, arg2) \ ++ PyCObject_AsVoidPtr(arg1) ++ + PyMODINIT_FUNC initperf_trace_context(void); ++#else ++#define _PyCapsule_GetPointer(arg1, arg2) \ ++ PyCapsule_GetPointer((arg1), (arg2)) ++ ++PyMODINIT_FUNC PyInit_perf_trace_context(void); ++#endif + + static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args) + { +@@ -34,7 +44,7 @@ static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args) + if (!PyArg_ParseTuple(args, "O", &context)) + return NULL; + +- scripting_context = PyCObject_AsVoidPtr(context); ++ scripting_context = _PyCapsule_GetPointer(context, NULL); + retval = common_pc(scripting_context); + + return Py_BuildValue("i", retval); +@@ -50,7 +60,7 @@ static PyObject *perf_trace_context_common_flags(PyObject *obj, + if (!PyArg_ParseTuple(args, "O", &context)) + return NULL; + +- scripting_context = PyCObject_AsVoidPtr(context); ++ scripting_context = _PyCapsule_GetPointer(context, NULL); + retval = common_flags(scripting_context); + + return Py_BuildValue("i", retval); +@@ -66,7 +76,7 @@ static PyObject *perf_trace_context_common_lock_depth(PyObject *obj, + if (!PyArg_ParseTuple(args, "O", &context)) + return NULL; + +- scripting_context = PyCObject_AsVoidPtr(context); ++ scripting_context = _PyCapsule_GetPointer(context, NULL); + retval = common_lock_depth(scripting_context); + + return Py_BuildValue("i", retval); +@@ -82,7 +92,25 @@ static PyMethodDef ContextMethods[] = { + { NULL, NULL, 0, NULL} + }; + ++#if PY_MAJOR_VERSION < 3 + PyMODINIT_FUNC initperf_trace_context(void) + { + (void) Py_InitModule("perf_trace_context", ContextMethods); + } ++#else ++PyMODINIT_FUNC PyInit_perf_trace_context(void) ++{ ++ static struct PyModuleDef moduledef = { ++ PyModuleDef_HEAD_INIT, ++ "perf_trace_context", /* m_name */ ++ "", /* m_doc */ ++ -1, /* m_size */ ++ ContextMethods, /* m_methods */ ++ NULL, /* m_reload */ ++ NULL, /* m_traverse */ ++ NULL, /* m_clear */ ++ NULL, /* m_free */ ++ }; ++ return PyModule_Create(&moduledef); ++} ++#endif +diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c +index 8e49d9cafcfc..16620c37fd8c 100644 +--- a/tools/perf/util/python.c ++++ b/tools/perf/util/python.c +@@ -12,6 +12,30 @@ + #include "print_binary.h" + #include "thread_map.h" + ++#if PY_MAJOR_VERSION < 3 ++#define _PyUnicode_FromString(arg) \ ++ PyString_FromString(arg) ++#define _PyUnicode_AsString(arg) \ ++ PyString_AsString(arg) ++#define _PyUnicode_FromFormat(...) \ ++ PyString_FromFormat(__VA_ARGS__) ++#define _PyLong_FromLong(arg) \ ++ PyInt_FromLong(arg) ++ ++#else ++ ++#define _PyUnicode_FromString(arg) \ ++ PyUnicode_FromString(arg) ++#define _PyUnicode_FromFormat(...) \ ++ PyUnicode_FromFormat(__VA_ARGS__) ++#define _PyLong_FromLong(arg) \ ++ PyLong_FromLong(arg) ++#endif ++ ++#ifndef Py_TYPE ++#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) ++#endif ++ + /* + * Provide these two so that we don't have to link against callchain.c and + * start dragging hist.c, etc. +@@ -49,7 +73,11 @@ int eprintf(int level, int var, const char *fmt, ...) + # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, + #endif + ++#if PY_MAJOR_VERSION < 3 + PyMODINIT_FUNC initperf(void); ++#else ++PyMODINIT_FUNC PyInit_perf(void); ++#endif + + #define member_def(type, member, ptype, help) \ + { #member, ptype, \ +@@ -107,7 +135,7 @@ static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent) + pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { + ret = PyErr_NoMemory(); + } else { +- ret = PyString_FromString(s); ++ ret = _PyUnicode_FromString(s); + free(s); + } + return ret; +@@ -138,7 +166,7 @@ static PyMemberDef pyrf_task_event__members[] = { + + static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent) + { +- return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " ++ return _PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " + "ptid: %u, time: %" PRIu64 "}", + pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", + pevent->event.fork.pid, +@@ -171,7 +199,7 @@ static PyMemberDef pyrf_comm_event__members[] = { + + static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent) + { +- return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", ++ return _PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", + pevent->event.comm.pid, + pevent->event.comm.tid, + pevent->event.comm.comm); +@@ -202,7 +230,7 @@ static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent) + { + struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1); + +- return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 ++ return _PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 + ", stream_id: %" PRIu64 " }", + pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", + te->time, te->id, te->stream_id); +@@ -237,7 +265,7 @@ static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent) + pevent->event.lost.id, pevent->event.lost.lost) < 0) { + ret = PyErr_NoMemory(); + } else { +- ret = PyString_FromString(s); ++ ret = _PyUnicode_FromString(s); + free(s); + } + return ret; +@@ -264,7 +292,7 @@ static PyMemberDef pyrf_read_event__members[] = { + + static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent) + { +- return PyString_FromFormat("{ type: read, pid: %u, tid: %u }", ++ return _PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }", + pevent->event.read.pid, + pevent->event.read.tid); + /* +@@ -299,7 +327,7 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent) + if (asprintf(&s, "{ type: sample }") < 0) { + ret = PyErr_NoMemory(); + } else { +- ret = PyString_FromString(s); ++ ret = _PyUnicode_FromString(s); + free(s); + } + return ret; +@@ -330,7 +358,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field) + } + if (field->flags & FIELD_IS_STRING && + is_printable_array(data + offset, len)) { +- ret = PyString_FromString((char *)data + offset); ++ ret = _PyUnicode_FromString((char *)data + offset); + } else { + ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); + field->flags &= ~FIELD_IS_STRING; +@@ -352,7 +380,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field) + static PyObject* + get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) + { +- const char *str = PyString_AsString(PyObject_Str(attr_name)); ++ const char *str = _PyUnicode_AsString(PyObject_Str(attr_name)); + struct perf_evsel *evsel = pevent->evsel; + struct format_field *field; + +@@ -416,7 +444,7 @@ static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent) + !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { + ret = PyErr_NoMemory(); + } else { +- ret = PyString_FromString(s); ++ ret = _PyUnicode_FromString(s); + free(s); + } + return ret; +@@ -528,7 +556,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, + static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) + { + cpu_map__put(pcpus->cpus); +- pcpus->ob_type->tp_free((PyObject*)pcpus); ++ Py_TYPE(pcpus)->tp_free((PyObject*)pcpus); + } + + static Py_ssize_t pyrf_cpu_map__length(PyObject *obj) +@@ -597,7 +625,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, + static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) + { + thread_map__put(pthreads->threads); +- pthreads->ob_type->tp_free((PyObject*)pthreads); ++ Py_TYPE(pthreads)->tp_free((PyObject*)pthreads); + } + + static Py_ssize_t pyrf_thread_map__length(PyObject *obj) +@@ -759,7 +787,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel, + static void pyrf_evsel__delete(struct pyrf_evsel *pevsel) + { + perf_evsel__exit(&pevsel->evsel); +- pevsel->ob_type->tp_free((PyObject*)pevsel); ++ Py_TYPE(pevsel)->tp_free((PyObject*)pevsel); + } + + static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, +@@ -850,7 +878,7 @@ static int pyrf_evlist__init(struct pyrf_evlist *pevlist, + static void pyrf_evlist__delete(struct pyrf_evlist *pevlist) + { + perf_evlist__exit(&pevlist->evlist); +- pevlist->ob_type->tp_free((PyObject*)pevlist); ++ Py_TYPE(pevlist)->tp_free((PyObject*)pevlist); + } + + static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, +@@ -902,12 +930,16 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist, + + for (i = 0; i < evlist->pollfd.nr; ++i) { + PyObject *file; ++#if PY_MAJOR_VERSION < 3 + FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r"); + + if (fp == NULL) + goto free_list; + + file = PyFile_FromFile(fp, "perf", "r", NULL); ++#else ++ file = PyFile_FromFd(evlist->pollfd.entries[i].fd, "perf", "r", -1, NULL, NULL, NULL, 1); ++#endif + if (file == NULL) + goto free_list; + +@@ -1194,9 +1226,9 @@ static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel, + + tp_format = trace_event__tp_format(sys, name); + if (IS_ERR(tp_format)) +- return PyInt_FromLong(-1); ++ return _PyLong_FromLong(-1); + +- return PyInt_FromLong(tp_format->id); ++ return _PyLong_FromLong(tp_format->id); + } + + static PyMethodDef perf__methods[] = { +@@ -1209,11 +1241,31 @@ static PyMethodDef perf__methods[] = { + { .ml_name = NULL, } + }; + ++#if PY_MAJOR_VERSION < 3 + PyMODINIT_FUNC initperf(void) ++#else ++PyMODINIT_FUNC PyInit_perf(void) ++#endif + { + PyObject *obj; + int i; +- PyObject *dict, *module = Py_InitModule("perf", perf__methods); ++ PyObject *dict; ++#if PY_MAJOR_VERSION < 3 ++ PyObject *module = Py_InitModule("perf", perf__methods); ++#else ++ static struct PyModuleDef moduledef = { ++ PyModuleDef_HEAD_INIT, ++ "perf", /* m_name */ ++ "", /* m_doc */ ++ -1, /* m_size */ ++ perf__methods, /* m_methods */ ++ NULL, /* m_reload */ ++ NULL, /* m_traverse */ ++ NULL, /* m_clear */ ++ NULL, /* m_free */ ++ }; ++ PyObject *module = PyModule_Create(&moduledef); ++#endif + + if (module == NULL || + pyrf_event__setup_types() < 0 || +@@ -1221,7 +1273,11 @@ PyMODINIT_FUNC initperf(void) + pyrf_evsel__setup_types() < 0 || + pyrf_thread_map__setup_types() < 0 || + pyrf_cpu_map__setup_types() < 0) ++#if PY_MAJOR_VERSION < 3 + return; ++#else ++ return module; ++#endif + + /* The page_size is placed in util object. */ + page_size = sysconf(_SC_PAGE_SIZE); +@@ -1270,7 +1326,7 @@ PyMODINIT_FUNC initperf(void) + goto error; + + for (i = 0; perf__constants[i].name != NULL; i++) { +- obj = PyInt_FromLong(perf__constants[i].value); ++ obj = _PyLong_FromLong(perf__constants[i].value); + if (obj == NULL) + goto error; + PyDict_SetItemString(dict, perf__constants[i].name, obj); +@@ -1280,6 +1336,9 @@ PyMODINIT_FUNC initperf(void) + error: + if (PyErr_Occurred()) + PyErr_SetString(PyExc_ImportError, "perf: Init failed!"); ++#if PY_MAJOR_VERSION >= 3 ++ return module; ++#endif + } + + /* +diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c +index f03fa7a835a1..8db28d4ff4b6 100644 +--- a/tools/perf/util/scripting-engines/trace-event-python.c ++++ b/tools/perf/util/scripting-engines/trace-event-python.c +@@ -50,7 +50,37 @@ + #include "print_binary.h" + #include "stat.h" + ++#if PY_MAJOR_VERSION < 3 ++#define _PyUnicode_FromString(arg) \ ++ PyString_FromString(arg) ++#define _PyUnicode_FromStringAndSize(arg1, arg2) \ ++ PyString_FromStringAndSize((arg1), (arg2)) ++#define _PyBytes_FromStringAndSize(arg1, arg2) \ ++ PyString_FromStringAndSize((arg1), (arg2)) ++#define _PyLong_FromLong(arg) \ ++ PyInt_FromLong(arg) ++#define _PyLong_AsLong(arg) \ ++ PyInt_AsLong(arg) ++#define _PyCapsule_New(arg1, arg2, arg3) \ ++ PyCObject_FromVoidPtr((arg1), (arg2)) ++ + PyMODINIT_FUNC initperf_trace_context(void); ++#else ++#define _PyUnicode_FromString(arg) \ ++ PyUnicode_FromString(arg) ++#define _PyUnicode_FromStringAndSize(arg1, arg2) \ ++ PyUnicode_FromStringAndSize((arg1), (arg2)) ++#define _PyBytes_FromStringAndSize(arg1, arg2) \ ++ PyBytes_FromStringAndSize((arg1), (arg2)) ++#define _PyLong_FromLong(arg) \ ++ PyLong_FromLong(arg) ++#define _PyLong_AsLong(arg) \ ++ PyLong_AsLong(arg) ++#define _PyCapsule_New(arg1, arg2, arg3) \ ++ PyCapsule_New((arg1), (arg2), (arg3)) ++ ++PyMODINIT_FUNC PyInit_perf_trace_context(void); ++#endif + + #define TRACE_EVENT_TYPE_MAX \ + ((1 << (sizeof(unsigned short) * 8)) - 1) +@@ -136,7 +166,7 @@ static int get_argument_count(PyObject *handler) + PyObject *arg_count_obj = PyObject_GetAttrString(code_obj, + "co_argcount"); + if (arg_count_obj) { +- arg_count = (int) PyInt_AsLong(arg_count_obj); ++ arg_count = (int) _PyLong_AsLong(arg_count_obj); + Py_DECREF(arg_count_obj); + } + Py_DECREF(code_obj); +@@ -183,10 +213,10 @@ static void define_value(enum print_arg_type field_type, + + value = eval_flag(field_value); + +- PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); +- PyTuple_SetItem(t, n++, PyString_FromString(field_name)); +- PyTuple_SetItem(t, n++, PyInt_FromLong(value)); +- PyTuple_SetItem(t, n++, PyString_FromString(field_str)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(value)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_str)); + + try_call_object(handler_name, t); + +@@ -224,10 +254,10 @@ static void define_field(enum print_arg_type field_type, + if (!t) + Py_FatalError("couldn't create Python tuple"); + +- PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); +- PyTuple_SetItem(t, n++, PyString_FromString(field_name)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); + if (field_type == PRINT_FLAGS) +- PyTuple_SetItem(t, n++, PyString_FromString(delim)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim)); + + try_call_object(handler_name, t); + +@@ -326,12 +356,12 @@ static PyObject *get_field_numeric_entry(struct event_format *event, + if (field->flags & FIELD_IS_SIGNED) { + if ((long long)val >= LONG_MIN && + (long long)val <= LONG_MAX) +- obj = PyInt_FromLong(val); ++ obj = _PyLong_FromLong(val); + else + obj = PyLong_FromLongLong(val); + } else { + if (val <= LONG_MAX) +- obj = PyInt_FromLong(val); ++ obj = _PyLong_FromLong(val); + else + obj = PyLong_FromUnsignedLongLong(val); + } +@@ -390,9 +420,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample, + pydict_set_item_string_decref(pysym, "end", + PyLong_FromUnsignedLongLong(node->sym->end)); + pydict_set_item_string_decref(pysym, "binding", +- PyInt_FromLong(node->sym->binding)); ++ _PyLong_FromLong(node->sym->binding)); + pydict_set_item_string_decref(pysym, "name", +- PyString_FromStringAndSize(node->sym->name, ++ _PyUnicode_FromStringAndSize(node->sym->name, + node->sym->namelen)); + pydict_set_item_string_decref(pyelem, "sym", pysym); + } +@@ -407,7 +437,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample, + dsoname = map->dso->name; + } + pydict_set_item_string_decref(pyelem, "dso", +- PyString_FromString(dsoname)); ++ _PyUnicode_FromString(dsoname)); + } + + callchain_cursor_advance(&callchain_cursor); +@@ -484,16 +514,16 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, + if (!dict_sample) + Py_FatalError("couldn't create Python dictionary"); + +- pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); +- pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( ++ pydict_set_item_string_decref(dict, "ev_name", _PyUnicode_FromString(perf_evsel__name(evsel))); ++ pydict_set_item_string_decref(dict, "attr", _PyUnicode_FromStringAndSize( + (const char *)&evsel->attr, sizeof(evsel->attr))); + + pydict_set_item_string_decref(dict_sample, "pid", +- PyInt_FromLong(sample->pid)); ++ _PyLong_FromLong(sample->pid)); + pydict_set_item_string_decref(dict_sample, "tid", +- PyInt_FromLong(sample->tid)); ++ _PyLong_FromLong(sample->tid)); + pydict_set_item_string_decref(dict_sample, "cpu", +- PyInt_FromLong(sample->cpu)); ++ _PyLong_FromLong(sample->cpu)); + pydict_set_item_string_decref(dict_sample, "ip", + PyLong_FromUnsignedLongLong(sample->ip)); + pydict_set_item_string_decref(dict_sample, "time", +@@ -503,17 +533,17 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample, + set_sample_read_in_dict(dict_sample, sample, evsel); + pydict_set_item_string_decref(dict, "sample", dict_sample); + +- pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( ++ pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize( + (const char *)sample->raw_data, sample->raw_size)); + pydict_set_item_string_decref(dict, "comm", +- PyString_FromString(thread__comm_str(al->thread))); ++ _PyUnicode_FromString(thread__comm_str(al->thread))); + if (al->map) { + pydict_set_item_string_decref(dict, "dso", +- PyString_FromString(al->map->dso->name)); ++ _PyUnicode_FromString(al->map->dso->name)); + } + if (al->sym) { + pydict_set_item_string_decref(dict, "symbol", +- PyString_FromString(al->sym->name)); ++ _PyUnicode_FromString(al->sym->name)); + } + + pydict_set_item_string_decref(dict, "callchain", callchain); +@@ -573,9 +603,9 @@ static void python_process_tracepoint(struct perf_sample *sample, + scripting_context->event_data = data; + scripting_context->pevent = evsel->tp_format->pevent; + +- context = PyCObject_FromVoidPtr(scripting_context, NULL); ++ context = _PyCapsule_New(scripting_context, NULL, NULL); + +- PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(handler_name)); + PyTuple_SetItem(t, n++, context); + + /* ip unwinding */ +@@ -584,18 +614,18 @@ static void python_process_tracepoint(struct perf_sample *sample, + Py_INCREF(callchain); + + if (!dict) { +- PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); +- PyTuple_SetItem(t, n++, PyInt_FromLong(s)); +- PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); +- PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); +- PyTuple_SetItem(t, n++, PyString_FromString(comm)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(s)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(ns)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(pid)); ++ PyTuple_SetItem(t, n++, _PyUnicode_FromString(comm)); + PyTuple_SetItem(t, n++, callchain); + } else { +- pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); +- pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); +- pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); +- pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); +- pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); ++ pydict_set_item_string_decref(dict, "common_cpu", _PyLong_FromLong(cpu)); ++ pydict_set_item_string_decref(dict, "common_s", _PyLong_FromLong(s)); ++ pydict_set_item_string_decref(dict, "common_ns", _PyLong_FromLong(ns)); ++ pydict_set_item_string_decref(dict, "common_pid", _PyLong_FromLong(pid)); ++ pydict_set_item_string_decref(dict, "common_comm", _PyUnicode_FromString(comm)); + pydict_set_item_string_decref(dict, "common_callchain", callchain); + } + for (field = event->format.fields; field; field = field->next) { +@@ -614,7 +644,7 @@ static void python_process_tracepoint(struct perf_sample *sample, + } + if (field->flags & FIELD_IS_STRING && + is_printable_array(data + offset, len)) { +- obj = PyString_FromString((char *) data + offset); ++ obj = _PyUnicode_FromString((char *) data + offset); + } else { + obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); + field->flags &= ~FIELD_IS_STRING; +@@ -664,7 +694,7 @@ static PyObject *tuple_new(unsigned int sz) + static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) + { + #if BITS_PER_LONG == 64 +- return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); ++ return PyTuple_SetItem(t, pos, _PyLong_FromLong(val)); + #endif + #if BITS_PER_LONG == 32 + return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); +@@ -673,12 +703,12 @@ static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) + + static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) + { +- return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); ++ return PyTuple_SetItem(t, pos, _PyLong_FromLong(val)); + } + + static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) + { +- return PyTuple_SetItem(t, pos, PyString_FromString(s)); ++ return PyTuple_SetItem(t, pos, _PyUnicode_FromString(s)); + } + + static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) +@@ -1024,8 +1054,8 @@ process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp, + return; + } + +- PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); +- PyTuple_SetItem(t, n++, PyInt_FromLong(thread)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu)); ++ PyTuple_SetItem(t, n++, _PyLong_FromLong(thread)); + + tuple_set_u64(t, n++, tstamp); + tuple_set_u64(t, n++, count->val); +@@ -1207,27 +1237,58 @@ static void set_table_handlers(struct tables *tables) + SET_TABLE_HANDLER(call_return); + } + ++#if PY_MAJOR_VERSION < 3 ++static void _free_command_line(const char **command_line, int num) ++{ ++ free(command_line); ++} ++#else ++static void _free_command_line(wchar_t **command_line, int num) ++{ ++ int i; ++ for (i = 0; i < num; i++) ++ PyMem_RawFree(command_line[i]); ++ free(command_line); ++} ++#endif ++ ++ + /* + * Start trace script + */ + static int python_start_script(const char *script, int argc, const char **argv) + { + struct tables *tables = &tables_global; ++#if PY_MAJOR_VERSION < 3 + const char **command_line; ++#else ++ wchar_t **command_line; ++#endif + char buf[PATH_MAX]; + int i, err = 0; + FILE *fp; + ++#if PY_MAJOR_VERSION < 3 + command_line = malloc((argc + 1) * sizeof(const char *)); + command_line[0] = script; + for (i = 1; i < argc + 1; i++) + command_line[i] = argv[i - 1]; ++#else ++ command_line = malloc((argc + 1) * sizeof(wchar_t *)); ++ command_line[0] = Py_DecodeLocale(script, NULL); ++ for (i = 1; i < argc + 1; i++) ++ command_line[i] = Py_DecodeLocale(argv[i - 1], NULL); ++#endif + + Py_Initialize(); + ++#if PY_MAJOR_VERSION < 3 + initperf_trace_context(); +- + PySys_SetArgv(argc + 1, (char **)command_line); ++#else ++ PyInit_perf_trace_context(); ++ PySys_SetArgv(argc + 1, command_line); ++#endif + + fp = fopen(script, "r"); + if (!fp) { +@@ -1257,12 +1318,12 @@ static int python_start_script(const char *script, int argc, const char **argv) + goto error; + } + +- free(command_line); ++ _free_command_line(command_line, argc + 1); + + return err; + error: + Py_Finalize(); +- free(command_line); ++ _free_command_line(command_line, argc + 1); + + return err; + } +diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py +index 23f1bf175179..a5f9e236cc71 100644 +--- a/tools/perf/util/setup.py ++++ b/tools/perf/util/setup.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/python2 ++#!/usr/bin/python + + from os import getenv + +@@ -37,11 +37,11 @@ build_tmp = getenv('PYTHON_EXTBUILD_TMP') + libtraceevent = getenv('LIBTRACEEVENT') + libapikfs = getenv('LIBAPI') + +-ext_sources = [f.strip() for f in file('util/python-ext-sources') ++ext_sources = [f.strip() for f in open('util/python-ext-sources') + if len(f.strip()) > 0 and f[0] != '#'] + + # use full paths with source files +-ext_sources = map(lambda x: '%s/%s' % (src_perf, x) , ext_sources) ++ext_sources = list(map(lambda x: '%s/%s' % (src_perf, x) , ext_sources)) + + perf = Extension('perf', + sources = ext_sources, +-- +2.17.1 + diff --git a/meta-rcar-gen3/recipes-kernel/linux/linux-renesas_4.14.bb b/meta-rcar-gen3/recipes-kernel/linux/linux-renesas_4.14.bb index 27705e3..b2a2f66 100644 --- a/meta-rcar-gen3/recipes-kernel/linux/linux-renesas_4.14.bb +++ b/meta-rcar-gen3/recipes-kernel/linux/linux-renesas_4.14.bb @@ -29,6 +29,11 @@ SRC_URI_append = " \ ${@oe.utils.conditional("USE_AVB", "1", " file://usb-video-class.cfg", "", d)} \ " +# Add python3 support to fix Perf build failure +SRC_URI_append = " \ + file://0001-perf-tools-Add-Python-3-support.patch \ +" + # Enable RPMSG_VIRTIO depend on ICCOM SUPPORT_ICCOM = " \ file://0001-rpmsg-Add-message-to-be-able-to-configure-RPMSG_VIRT.patch \ |