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

perf tools: Add Python 3 support

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>

authored by

Jaroslav Škarvada and committed by
Arnaldo Carvalho de Melo
66dfdff0 d2ed5d2b

+221 -88
+4 -19
tools/perf/Makefile.config
··· 668 668 ifneq ($(feature-libpython), 1) 669 669 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev) 670 670 else 671 - ifneq ($(feature-libpython-version), 1) 672 - $(warning Python 3 is not yet supported; please set) 673 - $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 674 - $(warning If you also have Python 2 installed, then) 675 - $(warning try something like:) 676 - $(warning $(and ,)) 677 - $(warning $(and ,) make PYTHON=python2) 678 - $(warning $(and ,)) 679 - $(warning Otherwise, disable Python support entirely:) 680 - $(warning $(and ,)) 681 - $(warning $(and ,) make NO_LIBPYTHON=1) 682 - $(warning $(and ,)) 683 - $(error $(and ,)) 684 - else 685 - LDFLAGS += $(PYTHON_EMBED_LDFLAGS) 686 - EXTLIBS += $(PYTHON_EMBED_LIBADD) 687 - LANG_BINDINGS += $(obj-perf)python/perf.so 688 - $(call detected,CONFIG_LIBPYTHON) 689 - endif 671 + LDFLAGS += $(PYTHON_EMBED_LDFLAGS) 672 + EXTLIBS += $(PYTHON_EMBED_LIBADD) 673 + LANG_BINDINGS += $(obj-perf)python/perf.so 674 + $(call detected,CONFIG_LIBPYTHON) 690 675 endif 691 676 endif 692 677 endif
+2 -2
tools/perf/Makefile.perf
··· 302 302 PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/ 303 303 export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP 304 304 305 - python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 305 + python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf*.so 306 306 307 307 PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 308 308 PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) ··· 479 479 $(PYTHON_WORD) util/setup.py \ 480 480 --quiet build_ext; \ 481 481 mkdir -p $(OUTPUT)python && \ 482 - cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ 482 + cp $(PYTHON_EXTBUILD_LIB)perf*.so $(OUTPUT)python/ 483 483 484 484 please_set_SHELL_PATH_to_a_more_modern_shell: 485 485 $(Q)$$(:)
+31 -3
tools/perf/scripts/python/Perf-Trace-Util/Context.c
··· 23 23 #include "../../../perf.h" 24 24 #include "../../../util/trace-event.h" 25 25 26 + #if PY_MAJOR_VERSION < 3 27 + #define _PyCapsule_GetPointer(arg1, arg2) \ 28 + PyCObject_AsVoidPtr(arg1) 29 + 26 30 PyMODINIT_FUNC initperf_trace_context(void); 31 + #else 32 + #define _PyCapsule_GetPointer(arg1, arg2) \ 33 + PyCapsule_GetPointer((arg1), (arg2)) 34 + 35 + PyMODINIT_FUNC PyInit_perf_trace_context(void); 36 + #endif 27 37 28 38 static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args) 29 39 { ··· 44 34 if (!PyArg_ParseTuple(args, "O", &context)) 45 35 return NULL; 46 36 47 - scripting_context = PyCObject_AsVoidPtr(context); 37 + scripting_context = _PyCapsule_GetPointer(context, NULL); 48 38 retval = common_pc(scripting_context); 49 39 50 40 return Py_BuildValue("i", retval); ··· 60 50 if (!PyArg_ParseTuple(args, "O", &context)) 61 51 return NULL; 62 52 63 - scripting_context = PyCObject_AsVoidPtr(context); 53 + scripting_context = _PyCapsule_GetPointer(context, NULL); 64 54 retval = common_flags(scripting_context); 65 55 66 56 return Py_BuildValue("i", retval); ··· 76 66 if (!PyArg_ParseTuple(args, "O", &context)) 77 67 return NULL; 78 68 79 - scripting_context = PyCObject_AsVoidPtr(context); 69 + scripting_context = _PyCapsule_GetPointer(context, NULL); 80 70 retval = common_lock_depth(scripting_context); 81 71 82 72 return Py_BuildValue("i", retval); ··· 92 82 { NULL, NULL, 0, NULL} 93 83 }; 94 84 85 + #if PY_MAJOR_VERSION < 3 95 86 PyMODINIT_FUNC initperf_trace_context(void) 96 87 { 97 88 (void) Py_InitModule("perf_trace_context", ContextMethods); 98 89 } 90 + #else 91 + PyMODINIT_FUNC PyInit_perf_trace_context(void) 92 + { 93 + static struct PyModuleDef moduledef = { 94 + PyModuleDef_HEAD_INIT, 95 + "perf_trace_context", /* m_name */ 96 + "", /* m_doc */ 97 + -1, /* m_size */ 98 + ContextMethods, /* m_methods */ 99 + NULL, /* m_reload */ 100 + NULL, /* m_traverse */ 101 + NULL, /* m_clear */ 102 + NULL, /* m_free */ 103 + }; 104 + return PyModule_Create(&moduledef); 105 + } 106 + #endif
+77 -18
tools/perf/util/python.c
··· 12 12 #include "print_binary.h" 13 13 #include "thread_map.h" 14 14 15 + #if PY_MAJOR_VERSION < 3 16 + #define _PyUnicode_FromString(arg) \ 17 + PyString_FromString(arg) 18 + #define _PyUnicode_AsString(arg) \ 19 + PyString_AsString(arg) 20 + #define _PyUnicode_FromFormat(...) \ 21 + PyString_FromFormat(__VA_ARGS__) 22 + #define _PyLong_FromLong(arg) \ 23 + PyInt_FromLong(arg) 24 + 25 + #else 26 + 27 + #define _PyUnicode_FromString(arg) \ 28 + PyUnicode_FromString(arg) 29 + #define _PyUnicode_FromFormat(...) \ 30 + PyUnicode_FromFormat(__VA_ARGS__) 31 + #define _PyLong_FromLong(arg) \ 32 + PyLong_FromLong(arg) 33 + #endif 34 + 35 + #ifndef Py_TYPE 36 + #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) 37 + #endif 38 + 15 39 /* 16 40 * Provide these two so that we don't have to link against callchain.c and 17 41 * start dragging hist.c, etc. ··· 73 49 # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, 74 50 #endif 75 51 52 + #if PY_MAJOR_VERSION < 3 76 53 PyMODINIT_FUNC initperf(void); 54 + #else 55 + PyMODINIT_FUNC PyInit_perf(void); 56 + #endif 77 57 78 58 #define member_def(type, member, ptype, help) \ 79 59 { #member, ptype, \ ··· 135 107 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { 136 108 ret = PyErr_NoMemory(); 137 109 } else { 138 - ret = PyString_FromString(s); 110 + ret = _PyUnicode_FromString(s); 139 111 free(s); 140 112 } 141 113 return ret; ··· 166 138 167 139 static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent) 168 140 { 169 - return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " 141 + return _PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " 170 142 "ptid: %u, time: %" PRIu64 "}", 171 143 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", 172 144 pevent->event.fork.pid, ··· 199 171 200 172 static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent) 201 173 { 202 - return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", 174 + return _PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", 203 175 pevent->event.comm.pid, 204 176 pevent->event.comm.tid, 205 177 pevent->event.comm.comm); ··· 230 202 { 231 203 struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1); 232 204 233 - return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 205 + return _PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 234 206 ", stream_id: %" PRIu64 " }", 235 207 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", 236 208 te->time, te->id, te->stream_id); ··· 265 237 pevent->event.lost.id, pevent->event.lost.lost) < 0) { 266 238 ret = PyErr_NoMemory(); 267 239 } else { 268 - ret = PyString_FromString(s); 240 + ret = _PyUnicode_FromString(s); 269 241 free(s); 270 242 } 271 243 return ret; ··· 292 264 293 265 static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent) 294 266 { 295 - return PyString_FromFormat("{ type: read, pid: %u, tid: %u }", 267 + return _PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }", 296 268 pevent->event.read.pid, 297 269 pevent->event.read.tid); 298 270 /* ··· 327 299 if (asprintf(&s, "{ type: sample }") < 0) { 328 300 ret = PyErr_NoMemory(); 329 301 } else { 330 - ret = PyString_FromString(s); 302 + ret = _PyUnicode_FromString(s); 331 303 free(s); 332 304 } 333 305 return ret; ··· 358 330 } 359 331 if (field->flags & FIELD_IS_STRING && 360 332 is_printable_array(data + offset, len)) { 361 - ret = PyString_FromString((char *)data + offset); 333 + ret = _PyUnicode_FromString((char *)data + offset); 362 334 } else { 363 335 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); 364 336 field->flags &= ~FIELD_IS_STRING; ··· 380 352 static PyObject* 381 353 get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) 382 354 { 383 - const char *str = PyString_AsString(PyObject_Str(attr_name)); 355 + const char *str = _PyUnicode_AsString(PyObject_Str(attr_name)); 384 356 struct perf_evsel *evsel = pevent->evsel; 385 357 struct format_field *field; 386 358 ··· 444 416 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { 445 417 ret = PyErr_NoMemory(); 446 418 } else { 447 - ret = PyString_FromString(s); 419 + ret = _PyUnicode_FromString(s); 448 420 free(s); 449 421 } 450 422 return ret; ··· 556 528 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) 557 529 { 558 530 cpu_map__put(pcpus->cpus); 559 - pcpus->ob_type->tp_free((PyObject*)pcpus); 531 + Py_TYPE(pcpus)->tp_free((PyObject*)pcpus); 560 532 } 561 533 562 534 static Py_ssize_t pyrf_cpu_map__length(PyObject *obj) ··· 625 597 static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) 626 598 { 627 599 thread_map__put(pthreads->threads); 628 - pthreads->ob_type->tp_free((PyObject*)pthreads); 600 + Py_TYPE(pthreads)->tp_free((PyObject*)pthreads); 629 601 } 630 602 631 603 static Py_ssize_t pyrf_thread_map__length(PyObject *obj) ··· 787 759 static void pyrf_evsel__delete(struct pyrf_evsel *pevsel) 788 760 { 789 761 perf_evsel__exit(&pevsel->evsel); 790 - pevsel->ob_type->tp_free((PyObject*)pevsel); 762 + Py_TYPE(pevsel)->tp_free((PyObject*)pevsel); 791 763 } 792 764 793 765 static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, ··· 878 850 static void pyrf_evlist__delete(struct pyrf_evlist *pevlist) 879 851 { 880 852 perf_evlist__exit(&pevlist->evlist); 881 - pevlist->ob_type->tp_free((PyObject*)pevlist); 853 + Py_TYPE(pevlist)->tp_free((PyObject*)pevlist); 882 854 } 883 855 884 856 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, ··· 930 902 931 903 for (i = 0; i < evlist->pollfd.nr; ++i) { 932 904 PyObject *file; 905 + #if PY_MAJOR_VERSION < 3 933 906 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r"); 934 907 935 908 if (fp == NULL) 936 909 goto free_list; 937 910 938 911 file = PyFile_FromFile(fp, "perf", "r", NULL); 912 + #else 913 + file = PyFile_FromFd(evlist->pollfd.entries[i].fd, "perf", "r", -1, NULL, NULL, NULL, 1); 914 + #endif 939 915 if (file == NULL) 940 916 goto free_list; 941 917 ··· 1226 1194 1227 1195 tp_format = trace_event__tp_format(sys, name); 1228 1196 if (IS_ERR(tp_format)) 1229 - return PyInt_FromLong(-1); 1197 + return _PyLong_FromLong(-1); 1230 1198 1231 - return PyInt_FromLong(tp_format->id); 1199 + return _PyLong_FromLong(tp_format->id); 1232 1200 } 1233 1201 1234 1202 static PyMethodDef perf__methods[] = { ··· 1241 1209 { .ml_name = NULL, } 1242 1210 }; 1243 1211 1212 + #if PY_MAJOR_VERSION < 3 1244 1213 PyMODINIT_FUNC initperf(void) 1214 + #else 1215 + PyMODINIT_FUNC PyInit_perf(void) 1216 + #endif 1245 1217 { 1246 1218 PyObject *obj; 1247 1219 int i; 1248 - PyObject *dict, *module = Py_InitModule("perf", perf__methods); 1220 + PyObject *dict; 1221 + #if PY_MAJOR_VERSION < 3 1222 + PyObject *module = Py_InitModule("perf", perf__methods); 1223 + #else 1224 + static struct PyModuleDef moduledef = { 1225 + PyModuleDef_HEAD_INIT, 1226 + "perf", /* m_name */ 1227 + "", /* m_doc */ 1228 + -1, /* m_size */ 1229 + perf__methods, /* m_methods */ 1230 + NULL, /* m_reload */ 1231 + NULL, /* m_traverse */ 1232 + NULL, /* m_clear */ 1233 + NULL, /* m_free */ 1234 + }; 1235 + PyObject *module = PyModule_Create(&moduledef); 1236 + #endif 1249 1237 1250 1238 if (module == NULL || 1251 1239 pyrf_event__setup_types() < 0 || ··· 1273 1221 pyrf_evsel__setup_types() < 0 || 1274 1222 pyrf_thread_map__setup_types() < 0 || 1275 1223 pyrf_cpu_map__setup_types() < 0) 1224 + #if PY_MAJOR_VERSION < 3 1276 1225 return; 1226 + #else 1227 + return module; 1228 + #endif 1277 1229 1278 1230 /* The page_size is placed in util object. */ 1279 1231 page_size = sysconf(_SC_PAGE_SIZE); ··· 1326 1270 goto error; 1327 1271 1328 1272 for (i = 0; perf__constants[i].name != NULL; i++) { 1329 - obj = PyInt_FromLong(perf__constants[i].value); 1273 + obj = _PyLong_FromLong(perf__constants[i].value); 1330 1274 if (obj == NULL) 1331 1275 goto error; 1332 1276 PyDict_SetItemString(dict, perf__constants[i].name, obj); ··· 1336 1280 error: 1337 1281 if (PyErr_Occurred()) 1338 1282 PyErr_SetString(PyExc_ImportError, "perf: Init failed!"); 1283 + #if PY_MAJOR_VERSION >= 3 1284 + return module; 1285 + #endif 1339 1286 } 1340 1287 1341 1288 /*
+104 -43
tools/perf/util/scripting-engines/trace-event-python.c
··· 49 49 #include "print_binary.h" 50 50 #include "stat.h" 51 51 52 + #if PY_MAJOR_VERSION < 3 53 + #define _PyUnicode_FromString(arg) \ 54 + PyString_FromString(arg) 55 + #define _PyUnicode_FromStringAndSize(arg1, arg2) \ 56 + PyString_FromStringAndSize((arg1), (arg2)) 57 + #define _PyBytes_FromStringAndSize(arg1, arg2) \ 58 + PyString_FromStringAndSize((arg1), (arg2)) 59 + #define _PyLong_FromLong(arg) \ 60 + PyInt_FromLong(arg) 61 + #define _PyLong_AsLong(arg) \ 62 + PyInt_AsLong(arg) 63 + #define _PyCapsule_New(arg1, arg2, arg3) \ 64 + PyCObject_FromVoidPtr((arg1), (arg2)) 65 + 52 66 PyMODINIT_FUNC initperf_trace_context(void); 67 + #else 68 + #define _PyUnicode_FromString(arg) \ 69 + PyUnicode_FromString(arg) 70 + #define _PyUnicode_FromStringAndSize(arg1, arg2) \ 71 + PyUnicode_FromStringAndSize((arg1), (arg2)) 72 + #define _PyBytes_FromStringAndSize(arg1, arg2) \ 73 + PyBytes_FromStringAndSize((arg1), (arg2)) 74 + #define _PyLong_FromLong(arg) \ 75 + PyLong_FromLong(arg) 76 + #define _PyLong_AsLong(arg) \ 77 + PyLong_AsLong(arg) 78 + #define _PyCapsule_New(arg1, arg2, arg3) \ 79 + PyCapsule_New((arg1), (arg2), (arg3)) 80 + 81 + PyMODINIT_FUNC PyInit_perf_trace_context(void); 82 + #endif 53 83 54 84 #define TRACE_EVENT_TYPE_MAX \ 55 85 ((1 << (sizeof(unsigned short) * 8)) - 1) ··· 165 135 PyObject *arg_count_obj = PyObject_GetAttrString(code_obj, 166 136 "co_argcount"); 167 137 if (arg_count_obj) { 168 - arg_count = (int) PyInt_AsLong(arg_count_obj); 138 + arg_count = (int) _PyLong_AsLong(arg_count_obj); 169 139 Py_DECREF(arg_count_obj); 170 140 } 171 141 Py_DECREF(code_obj); ··· 212 182 213 183 value = eval_flag(field_value); 214 184 215 - PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); 216 - PyTuple_SetItem(t, n++, PyString_FromString(field_name)); 217 - PyTuple_SetItem(t, n++, PyInt_FromLong(value)); 218 - PyTuple_SetItem(t, n++, PyString_FromString(field_str)); 185 + PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); 186 + PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); 187 + PyTuple_SetItem(t, n++, _PyLong_FromLong(value)); 188 + PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_str)); 219 189 220 190 try_call_object(handler_name, t); 221 191 ··· 253 223 if (!t) 254 224 Py_FatalError("couldn't create Python tuple"); 255 225 256 - PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); 257 - PyTuple_SetItem(t, n++, PyString_FromString(field_name)); 226 + PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); 227 + PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); 258 228 if (field_type == PRINT_FLAGS) 259 - PyTuple_SetItem(t, n++, PyString_FromString(delim)); 229 + PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim)); 260 230 261 231 try_call_object(handler_name, t); 262 232 ··· 355 325 if (field->flags & FIELD_IS_SIGNED) { 356 326 if ((long long)val >= LONG_MIN && 357 327 (long long)val <= LONG_MAX) 358 - obj = PyInt_FromLong(val); 328 + obj = _PyLong_FromLong(val); 359 329 else 360 330 obj = PyLong_FromLongLong(val); 361 331 } else { 362 332 if (val <= LONG_MAX) 363 - obj = PyInt_FromLong(val); 333 + obj = _PyLong_FromLong(val); 364 334 else 365 335 obj = PyLong_FromUnsignedLongLong(val); 366 336 } ··· 419 389 pydict_set_item_string_decref(pysym, "end", 420 390 PyLong_FromUnsignedLongLong(node->sym->end)); 421 391 pydict_set_item_string_decref(pysym, "binding", 422 - PyInt_FromLong(node->sym->binding)); 392 + _PyLong_FromLong(node->sym->binding)); 423 393 pydict_set_item_string_decref(pysym, "name", 424 - PyString_FromStringAndSize(node->sym->name, 394 + _PyUnicode_FromStringAndSize(node->sym->name, 425 395 node->sym->namelen)); 426 396 pydict_set_item_string_decref(pyelem, "sym", pysym); 427 397 } ··· 436 406 dsoname = map->dso->name; 437 407 } 438 408 pydict_set_item_string_decref(pyelem, "dso", 439 - PyString_FromString(dsoname)); 409 + _PyUnicode_FromString(dsoname)); 440 410 } 441 411 442 412 callchain_cursor_advance(&callchain_cursor); ··· 513 483 if (!dict_sample) 514 484 Py_FatalError("couldn't create Python dictionary"); 515 485 516 - pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 517 - pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( 486 + pydict_set_item_string_decref(dict, "ev_name", _PyUnicode_FromString(perf_evsel__name(evsel))); 487 + pydict_set_item_string_decref(dict, "attr", _PyUnicode_FromStringAndSize( 518 488 (const char *)&evsel->attr, sizeof(evsel->attr))); 519 489 520 490 pydict_set_item_string_decref(dict_sample, "pid", 521 - PyInt_FromLong(sample->pid)); 491 + _PyLong_FromLong(sample->pid)); 522 492 pydict_set_item_string_decref(dict_sample, "tid", 523 - PyInt_FromLong(sample->tid)); 493 + _PyLong_FromLong(sample->tid)); 524 494 pydict_set_item_string_decref(dict_sample, "cpu", 525 - PyInt_FromLong(sample->cpu)); 495 + _PyLong_FromLong(sample->cpu)); 526 496 pydict_set_item_string_decref(dict_sample, "ip", 527 497 PyLong_FromUnsignedLongLong(sample->ip)); 528 498 pydict_set_item_string_decref(dict_sample, "time", ··· 534 504 set_sample_read_in_dict(dict_sample, sample, evsel); 535 505 pydict_set_item_string_decref(dict, "sample", dict_sample); 536 506 537 - pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( 507 + pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize( 538 508 (const char *)sample->raw_data, sample->raw_size)); 539 509 pydict_set_item_string_decref(dict, "comm", 540 - PyString_FromString(thread__comm_str(al->thread))); 510 + _PyUnicode_FromString(thread__comm_str(al->thread))); 541 511 if (al->map) { 542 512 pydict_set_item_string_decref(dict, "dso", 543 - PyString_FromString(al->map->dso->name)); 513 + _PyUnicode_FromString(al->map->dso->name)); 544 514 } 545 515 if (al->sym) { 546 516 pydict_set_item_string_decref(dict, "symbol", 547 - PyString_FromString(al->sym->name)); 517 + _PyUnicode_FromString(al->sym->name)); 548 518 } 549 519 550 520 pydict_set_item_string_decref(dict, "callchain", callchain); ··· 604 574 scripting_context->event_data = data; 605 575 scripting_context->pevent = evsel->tp_format->pevent; 606 576 607 - context = PyCObject_FromVoidPtr(scripting_context, NULL); 577 + context = _PyCapsule_New(scripting_context, NULL, NULL); 608 578 609 - PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); 579 + PyTuple_SetItem(t, n++, _PyUnicode_FromString(handler_name)); 610 580 PyTuple_SetItem(t, n++, context); 611 581 612 582 /* ip unwinding */ ··· 615 585 Py_INCREF(callchain); 616 586 617 587 if (!dict) { 618 - PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 619 - PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 620 - PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 621 - PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); 622 - PyTuple_SetItem(t, n++, PyString_FromString(comm)); 588 + PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu)); 589 + PyTuple_SetItem(t, n++, _PyLong_FromLong(s)); 590 + PyTuple_SetItem(t, n++, _PyLong_FromLong(ns)); 591 + PyTuple_SetItem(t, n++, _PyLong_FromLong(pid)); 592 + PyTuple_SetItem(t, n++, _PyUnicode_FromString(comm)); 623 593 PyTuple_SetItem(t, n++, callchain); 624 594 } else { 625 - pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); 626 - pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); 627 - pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); 628 - pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); 629 - pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); 595 + pydict_set_item_string_decref(dict, "common_cpu", _PyLong_FromLong(cpu)); 596 + pydict_set_item_string_decref(dict, "common_s", _PyLong_FromLong(s)); 597 + pydict_set_item_string_decref(dict, "common_ns", _PyLong_FromLong(ns)); 598 + pydict_set_item_string_decref(dict, "common_pid", _PyLong_FromLong(pid)); 599 + pydict_set_item_string_decref(dict, "common_comm", _PyUnicode_FromString(comm)); 630 600 pydict_set_item_string_decref(dict, "common_callchain", callchain); 631 601 } 632 602 for (field = event->format.fields; field; field = field->next) { ··· 645 615 } 646 616 if (field->flags & FIELD_IS_STRING && 647 617 is_printable_array(data + offset, len)) { 648 - obj = PyString_FromString((char *) data + offset); 618 + obj = _PyUnicode_FromString((char *) data + offset); 649 619 } else { 650 620 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); 651 621 field->flags &= ~FIELD_IS_STRING; ··· 698 668 static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) 699 669 { 700 670 #if BITS_PER_LONG == 64 701 - return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); 671 + return PyTuple_SetItem(t, pos, _PyLong_FromLong(val)); 702 672 #endif 703 673 #if BITS_PER_LONG == 32 704 674 return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); ··· 707 677 708 678 static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) 709 679 { 710 - return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); 680 + return PyTuple_SetItem(t, pos, _PyLong_FromLong(val)); 711 681 } 712 682 713 683 static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) 714 684 { 715 - return PyTuple_SetItem(t, pos, PyString_FromString(s)); 685 + return PyTuple_SetItem(t, pos, _PyUnicode_FromString(s)); 716 686 } 717 687 718 688 static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) ··· 1059 1029 return; 1060 1030 } 1061 1031 1062 - PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 1063 - PyTuple_SetItem(t, n++, PyInt_FromLong(thread)); 1032 + PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu)); 1033 + PyTuple_SetItem(t, n++, _PyLong_FromLong(thread)); 1064 1034 1065 1035 tuple_set_u64(t, n++, tstamp); 1066 1036 tuple_set_u64(t, n++, count->val); ··· 1242 1212 SET_TABLE_HANDLER(call_return); 1243 1213 } 1244 1214 1215 + #if PY_MAJOR_VERSION < 3 1216 + static void _free_command_line(const char **command_line, int num) 1217 + { 1218 + free(command_line); 1219 + } 1220 + #else 1221 + static void _free_command_line(wchar_t **command_line, int num) 1222 + { 1223 + int i; 1224 + for (i = 0; i < num; i++) 1225 + PyMem_RawFree(command_line[i]); 1226 + free(command_line); 1227 + } 1228 + #endif 1229 + 1230 + 1245 1231 /* 1246 1232 * Start trace script 1247 1233 */ 1248 1234 static int python_start_script(const char *script, int argc, const char **argv) 1249 1235 { 1250 1236 struct tables *tables = &tables_global; 1237 + #if PY_MAJOR_VERSION < 3 1251 1238 const char **command_line; 1239 + #else 1240 + wchar_t **command_line; 1241 + #endif 1252 1242 char buf[PATH_MAX]; 1253 1243 int i, err = 0; 1254 1244 FILE *fp; 1255 1245 1246 + #if PY_MAJOR_VERSION < 3 1256 1247 command_line = malloc((argc + 1) * sizeof(const char *)); 1257 1248 command_line[0] = script; 1258 1249 for (i = 1; i < argc + 1; i++) 1259 1250 command_line[i] = argv[i - 1]; 1251 + #else 1252 + command_line = malloc((argc + 1) * sizeof(wchar_t *)); 1253 + command_line[0] = Py_DecodeLocale(script, NULL); 1254 + for (i = 1; i < argc + 1; i++) 1255 + command_line[i] = Py_DecodeLocale(argv[i - 1], NULL); 1256 + #endif 1260 1257 1261 1258 Py_Initialize(); 1262 1259 1260 + #if PY_MAJOR_VERSION < 3 1263 1261 initperf_trace_context(); 1264 - 1265 1262 PySys_SetArgv(argc + 1, (char **)command_line); 1263 + #else 1264 + PyInit_perf_trace_context(); 1265 + PySys_SetArgv(argc + 1, command_line); 1266 + #endif 1266 1267 1267 1268 fp = fopen(script, "r"); 1268 1269 if (!fp) { ··· 1323 1262 goto error; 1324 1263 } 1325 1264 1326 - free(command_line); 1265 + _free_command_line(command_line, argc + 1); 1327 1266 1328 1267 return err; 1329 1268 error: 1330 1269 Py_Finalize(); 1331 - free(command_line); 1270 + _free_command_line(command_line, argc + 1); 1332 1271 1333 1272 return err; 1334 1273 }
+3 -3
tools/perf/util/setup.py
··· 1 - #!/usr/bin/python2 1 + #!/usr/bin/python 2 2 3 3 from os import getenv 4 4 ··· 35 35 libtraceevent = getenv('LIBTRACEEVENT') 36 36 libapikfs = getenv('LIBAPI') 37 37 38 - ext_sources = [f.strip() for f in file('util/python-ext-sources') 38 + ext_sources = [f.strip() for f in open('util/python-ext-sources') 39 39 if len(f.strip()) > 0 and f[0] != '#'] 40 40 41 41 # use full paths with source files 42 - ext_sources = map(lambda x: '%s/%s' % (src_perf, x) , ext_sources) 42 + ext_sources = list(map(lambda x: '%s/%s' % (src_perf, x) , ext_sources)) 43 43 44 44 perf = Extension('perf', 45 45 sources = ext_sources,