[PATCH v6 54/59] perf: Remove libpython support and legacy Python scripts

Ian Rogers
2026-04-25T17:50:50Z

This commit removes embedded Python interpreter support from perf, as
all legacy Python scripts have been ported to standalone Python
scripts or are no longer needed.

Changes include:
- Removal of libpython detection and flags from Makefile.config.
- Removal of Python script installation rules from Makefile.perf.
- Deletion of tools/perf/util/scripting-engines/trace-event-python.c.
- Removal of Python scripting operations and setup from
trace-event-scripting.c.
- Removal of setup_python_scripting() call from builtin-script.c and
declaration from trace-event.h.
- Removal of Python checks in the script browser (scripts.c).
- Removal of libpython from the supported features list in builtin-check.c
and Documentation/perf-check.txt.
- Deletion of the legacy Python scripts in tools/perf/scripts/python.

Assisted-by: Gemini:gemini-3.1-pro-preview
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/Documentation/perf-check.txt | 1 -
tools/perf/Makefile.config | 4 -
tools/perf/Makefile.perf | 7 +-
tools/perf/builtin-check.c | 1 -
tools/perf/scripts/Build | 2 -
.../perf/scripts/python/Perf-Trace-Util/Build | 4 -
.../scripts/python/Perf-Trace-Util/Context.c | 225 --
.../Perf-Trace-Util/lib/Perf/Trace/Core.py | 116 -
.../lib/Perf/Trace/EventClass.py | 97 -
.../lib/Perf/Trace/SchedGui.py | 184 --
.../Perf-Trace-Util/lib/Perf/Trace/Util.py | 92 -
.../scripts/python/arm-cs-trace-disasm.py | 355 ---
.../python/bin/compaction-times-record | 2 -
.../python/bin/compaction-times-report | 4 -
.../python/bin/event_analyzing_sample-record | 8 -
.../python/bin/event_analyzing_sample-report | 3 -
.../python/bin/export-to-postgresql-record | 8 -
.../python/bin/export-to-postgresql-report | 29 -
.../python/bin/export-to-sqlite-record | 8 -
.../python/bin/export-to-sqlite-report | 29 -
.../python/bin/failed-syscalls-by-pid-record | 3 -
.../python/bin/failed-syscalls-by-pid-report | 10 -
.../perf/scripts/python/bin/flamegraph-record | 2 -
.../perf/scripts/python/bin/flamegraph-report | 3 -
.../python/bin/futex-contention-record | 2 -
.../python/bin/futex-contention-report | 4 -
tools/perf/scripts/python/bin/gecko-record | 2 -
tools/perf/scripts/python/bin/gecko-report | 7 -
.../scripts/python/bin/intel-pt-events-record | 13 -
.../scripts/python/bin/intel-pt-events-report | 3 -
.../scripts/python/bin/mem-phys-addr-record | 19 -
.../scripts/python/bin/mem-phys-addr-report | 3 -
.../scripts/python/bin/net_dropmonitor-record | 2 -
.../scripts/python/bin/net_dropmonitor-report | 4 -
.../scripts/python/bin/netdev-times-record | 8 -
.../scripts/python/bin/netdev-times-report | 5 -
.../scripts/python/bin/powerpc-hcalls-record | 2 -
.../scripts/python/bin/powerpc-hcalls-report | 2 -
.../scripts/python/bin/sched-migration-record | 2 -
.../scripts/python/bin/sched-migration-report | 3 -
tools/perf/scripts/python/bin/sctop-record | 3 -
tools/perf/scripts/python/bin/sctop-report | 24 -
.../scripts/python/bin/stackcollapse-record | 8 -
.../scripts/python/bin/stackcollapse-report | 3 -
.../python/bin/syscall-counts-by-pid-record | 3 -
.../python/bin/syscall-counts-by-pid-report | 10 -
.../scripts/python/bin/syscall-counts-record | 3 -
.../scripts/python/bin/syscall-counts-report | 10 -
.../scripts/python/bin/task-analyzer-record | 2 -
.../scripts/python/bin/task-analyzer-report | 3 -
tools/perf/scripts/python/check-perf-trace.py | 84 -
tools/perf/scripts/python/compaction-times.py | 311 ---
.../scripts/python/event_analyzing_sample.py | 192 --
.../scripts/python/export-to-postgresql.py | 1114 ---------
tools/perf/scripts/python/export-to-sqlite.py | 799 ------
.../scripts/python/failed-syscalls-by-pid.py | 79 -
tools/perf/scripts/python/flamegraph.py | 267 --
tools/perf/scripts/python/futex-contention.py | 57 -
tools/perf/scripts/python/gecko.py | 395 ---
tools/perf/scripts/python/intel-pt-events.py | 494 ----
tools/perf/scripts/python/libxed.py | 107 -
tools/perf/scripts/python/mem-phys-addr.py | 127 -
tools/perf/scripts/python/net_dropmonitor.py | 78 -
tools/perf/scripts/python/netdev-times.py | 473 ----
tools/perf/scripts/python/powerpc-hcalls.py | 202 --
tools/perf/scripts/python/sched-migration.py | 462 ----
tools/perf/scripts/python/sctop.py | 89 -
tools/perf/scripts/python/stackcollapse.py | 127 -
tools/perf/scripts/python/stat-cpi.py | 79 -
.../scripts/python/syscall-counts-by-pid.py | 75 -
tools/perf/scripts/python/syscall-counts.py | 65 -
tools/perf/scripts/python/task-analyzer.py | 934 -------
tools/perf/tests/shell/script_python.sh | 113 -
tools/perf/util/scripting-engines/Build | 8 +-
.../scripting-engines/trace-event-python.c | 2209 -----------------
tools/perf/util/trace-event-scripting.c | 14 +-
76 files changed, 4 insertions(+), 10297 deletions(-)
delete mode 100644 tools/perf/scripts/python/Perf-Trace-Util/Build
delete mode 100644 tools/perf/scripts/python/Perf-Trace-Util/Context.c
delete mode 100644 tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
delete mode 100755 tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py
delete mode 100644 tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
delete mode 100644 tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
delete mode 100755 tools/perf/scripts/python/arm-cs-trace-disasm.py
delete mode 100644 tools/perf/scripts/python/bin/compaction-times-record
delete mode 100644 tools/perf/scripts/python/bin/compaction-times-report
delete mode 100644 tools/perf/scripts/python/bin/event_analyzing_sample-record
delete mode 100644 tools/perf/scripts/python/bin/event_analyzing_sample-report
delete mode 100644 tools/perf/scripts/python/bin/export-to-postgresql-record
delete mode 100644 tools/perf/scripts/python/bin/export-to-postgresql-report
delete mode 100644 tools/perf/scripts/python/bin/export-to-sqlite-record
delete mode 100644 tools/perf/scripts/python/bin/export-to-sqlite-report
delete mode 100644 tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
delete mode 100644 tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
delete mode 100755 tools/perf/scripts/python/bin/flamegraph-record
delete mode 100755 tools/perf/scripts/python/bin/flamegraph-report
delete mode 100644 tools/perf/scripts/python/bin/futex-contention-record
delete mode 100644 tools/perf/scripts/python/bin/futex-contention-report
delete mode 100644 tools/perf/scripts/python/bin/gecko-record
delete mode 100755 tools/perf/scripts/python/bin/gecko-report
delete mode 100644 tools/perf/scripts/python/bin/intel-pt-events-record
delete mode 100644 tools/perf/scripts/python/bin/intel-pt-events-report
delete mode 100644 tools/perf/scripts/python/bin/mem-phys-addr-record
delete mode 100644 tools/perf/scripts/python/bin/mem-phys-addr-report
delete mode 100755 tools/perf/scripts/python/bin/net_dropmonitor-record
delete mode 100755 tools/perf/scripts/python/bin/net_dropmonitor-report
delete mode 100644 tools/perf/scripts/python/bin/netdev-times-record
delete mode 100644 tools/perf/scripts/python/bin/netdev-times-report
delete mode 100644 tools/perf/scripts/python/bin/powerpc-hcalls-record
delete mode 100644 tools/perf/scripts/python/bin/powerpc-hcalls-report
delete mode 100644 tools/perf/scripts/python/bin/sched-migration-record
delete mode 100644 tools/perf/scripts/python/bin/sched-migration-report
delete mode 100644 tools/perf/scripts/python/bin/sctop-record
delete mode 100644 tools/perf/scripts/python/bin/sctop-report
delete mode 100755 tools/perf/scripts/python/bin/stackcollapse-record
delete mode 100755 tools/perf/scripts/python/bin/stackcollapse-report
delete mode 100644 tools/perf/scripts/python/bin/syscall-counts-by-pid-record
delete mode 100644 tools/perf/scripts/python/bin/syscall-counts-by-pid-report
delete mode 100644 tools/perf/scripts/python/bin/syscall-counts-record
delete mode 100644 tools/perf/scripts/python/bin/syscall-counts-report
delete mode 100755 tools/perf/scripts/python/bin/task-analyzer-record
delete mode 100755 tools/perf/scripts/python/bin/task-analyzer-report
delete mode 100644 tools/perf/scripts/python/check-perf-trace.py
delete mode 100644 tools/perf/scripts/python/compaction-times.py
delete mode 100644 tools/perf/scripts/python/event_analyzing_sample.py
delete mode 100644 tools/perf/scripts/python/export-to-postgresql.py
delete mode 100644 tools/perf/scripts/python/export-to-sqlite.py
delete mode 100644 tools/perf/scripts/python/failed-syscalls-by-pid.py
delete mode 100755 tools/perf/scripts/python/flamegraph.py
delete mode 100644 tools/perf/scripts/python/futex-contention.py
delete mode 100644 tools/perf/scripts/python/gecko.py
delete mode 100644 tools/perf/scripts/python/intel-pt-events.py
delete mode 100644 tools/perf/scripts/python/libxed.py
delete mode 100644 tools/perf/scripts/python/mem-phys-addr.py
delete mode 100755 tools/perf/scripts/python/net_dropmonitor.py
delete mode 100644 tools/perf/scripts/python/netdev-times.py
delete mode 100644 tools/perf/scripts/python/powerpc-hcalls.py
delete mode 100644 tools/perf/scripts/python/sched-migration.py
delete mode 100644 tools/perf/scripts/python/sctop.py
delete mode 100755 tools/perf/scripts/python/stackcollapse.py
delete mode 100644 tools/perf/scripts/python/stat-cpi.py
delete mode 100644 tools/perf/scripts/python/syscall-counts-by-pid.py
delete mode 100644 tools/perf/scripts/python/syscall-counts.py
delete mode 100755 tools/perf/scripts/python/task-analyzer.py
delete mode 100755 tools/perf/tests/shell/script_python.sh
delete mode 100644 tools/perf/util/scripting-engines/trace-event-python.c

diff --git a/tools/perf/Documentation/perf-check.txt b/tools/perf/Documentation/perf-check.txt
index 60fa9ea43a58..32d6200e7b20 100644
--- a/tools/perf/Documentation/perf-check.txt
+++ b/tools/perf/Documentation/perf-check.txt
@@ -59,7 +59,6 @@ feature::
libnuma / HAVE_LIBNUMA_SUPPORT
libopencsd / HAVE_CSTRACE_SUPPORT
libpfm4 / HAVE_LIBPFM
- libpython / HAVE_LIBPYTHON_SUPPORT
libslang / HAVE_SLANG_SUPPORT
libtraceevent / HAVE_LIBTRACEEVENT
libunwind / HAVE_LIBUNWIND_SUPPORT
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index db30e73c5efc..ecddd91229c8 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -852,8 +852,6 @@ else
ifneq ($(feature-libpython), 1)
$(call disable-python,No 'Python.h' was found: disables Python support - please install python-devel/python-dev)
else
- LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
- EXTLIBS += $(PYTHON_EMBED_LIBADD)
PYTHON_SETUPTOOLS_INSTALLED := $(shell $(PYTHON) -c 'import setuptools;' 2> /dev/null && echo "yes" || echo "no")
ifeq ($(PYTHON_SETUPTOOLS_INSTALLED), yes)
PYTHON_EXTENSION_SUFFIX := $(shell $(PYTHON) -c 'from importlib import machinery; print(machinery.EXTENSION_SUFFIXES[0])')
@@ -864,8 +862,6 @@ else
else
$(warning Missing python setuptools, the python binding won't be built, please install python3-setuptools or equivalent)
endif
- CFLAGS += -DHAVE_LIBPYTHON_SUPPORT
- $(call detected,CONFIG_LIBPYTHON)
ifeq ($(filter -fPIC,$(CFLAGS)),)
# Building a shared library requires position independent code.
CFLAGS += -fPIC
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 7bf349198622..2020532bab9c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -1101,11 +1101,8 @@ endif

ifndef NO_LIBPYTHON
$(call QUIET_INSTALL, python-scripts) \
- $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
- $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'; \
- $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -m 644 -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
- $(INSTALL) scripts/python/*.py -m 644 -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
- $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
+ $(INSTALL) python/*.py -m 644 -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
endif
$(call QUIET_INSTALL, dlfilters) \
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/dlfilters'; \
diff --git a/tools/perf/builtin-check.c b/tools/perf/builtin-check.c
index 944038814d62..73391d182039 100644
--- a/tools/perf/builtin-check.c
+++ b/tools/perf/builtin-check.c
@@ -53,7 +53,6 @@ struct feature_status supported_features[] = {
FEATURE_STATUS("libopencsd", HAVE_CSTRACE_SUPPORT),

FEATURE_STATUS("libpfm4", HAVE_LIBPFM),
- FEATURE_STATUS("libpython", HAVE_LIBPYTHON_SUPPORT),
FEATURE_STATUS("libslang", HAVE_SLANG_SUPPORT),
FEATURE_STATUS("libtraceevent", HAVE_LIBTRACEEVENT),
FEATURE_STATUS_TIP("libunwind", HAVE_LIBUNWIND_SUPPORT, "Deprecated, use LIBUNWIND=1 and install libunwind-dev[el] to build with it"),
diff --git a/tools/perf/scripts/Build b/tools/perf/scripts/Build
index d72cf9ad45fe..d066864369ed 100644
--- a/tools/perf/scripts/Build
+++ b/tools/perf/scripts/Build
@@ -1,6 +1,4 @@

-perf-util-$(CONFIG_LIBPYTHON) += python/Perf-Trace-Util/
-
ifdef MYPY
PY_TESTS := $(shell find python -type f -name '*.py')
MYPY_TEST_LOGS := $(PY_TESTS:python/%=python/%.mypy_log)
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Build b/tools/perf/scripts/python/Perf-Trace-Util/Build
deleted file mode 100644
index be3710c61320..000000000000
--- a/tools/perf/scripts/python/Perf-Trace-Util/Build
+++ /dev/null
@@ -1,4 +0,0 @@
-perf-util-y += Context.o
-
-# -Wno-declaration-after-statement: The python headers have mixed code with declarations (decls after asserts, for instance)
-CFLAGS_Context.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-declaration-after-statement
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
deleted file mode 100644
index c19f44610983..000000000000
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ /dev/null
@@ -1,225 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Context.c. Python interfaces for perf script.
- *
- * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com>
- */
-
-/*
- * Use Py_ssize_t for '#' formats to avoid DeprecationWarning: PY_SSIZE_T_CLEAN
- * will be required for '#' formats.
- */
-#define PY_SSIZE_T_CLEAN
-
-#include <Python.h>
-#include "../../../util/config.h"
-#include "../../../util/trace-event.h"
-#include "../../../util/event.h"
-#include "../../../util/symbol.h"
-#include "../../../util/thread.h"
-#include "../../../util/map.h"
-#include "../../../util/maps.h"
-#include "../../../util/auxtrace.h"
-#include "../../../util/session.h"
-#include "../../../util/srcline.h"
-#include "../../../util/srccode.h"
-
-#define _PyCapsule_GetPointer(arg1, arg2) \
- PyCapsule_GetPointer((arg1), (arg2))
-#define _PyBytes_FromStringAndSize(arg1, arg2) \
- PyBytes_FromStringAndSize((arg1), (arg2))
-#define _PyUnicode_AsUTF8(arg) \
- PyUnicode_AsUTF8(arg)
-
-PyMODINIT_FUNC PyInit_perf_trace_context(void);
-
-static struct scripting_context *get_args(PyObject *args, const char *name, PyObject **arg2)
-{
- int cnt = 1 + !!arg2;
- PyObject *context;
-
- if (!PyArg_UnpackTuple(args, name, 1, cnt, &context, arg2))
- return NULL;
-
- return _PyCapsule_GetPointer(context, NULL);
-}
-
-static struct scripting_context *get_scripting_context(PyObject *args)
-{
- return get_args(args, "context", NULL);
-}
-
-#ifdef HAVE_LIBTRACEEVENT
-static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
-{
- struct scripting_context *c = get_scripting_context(args);
-
- if (!c)
- return NULL;
-
- return Py_BuildValue("i", common_pc(c));
-}
-
-static PyObject *perf_trace_context_common_flags(PyObject *obj,
- PyObject *args)
-{
- struct scripting_context *c = get_scripting_context(args);
-
- if (!c)
- return NULL;
-
- return Py_BuildValue("i", common_flags(c));
-}
-
-static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
- PyObject *args)
-{
- struct scripting_context *c = get_scripting_context(args);
-
- if (!c)
- return NULL;
-
- return Py_BuildValue("i", common_lock_depth(c));
-}
-#endif
-
-static PyObject *perf_sample_insn(PyObject *obj, PyObject *args)
-{
- struct scripting_context *c = get_scripting_context(args);
-
- if (!c)
- return NULL;
-
- if (c->sample->ip && !c->sample->insn_len && thread__maps(c->al->thread)) {
- struct machine *machine = maps__machine(thread__maps(c->al->thread));
-
- perf_sample__fetch_insn(c->sample, c->al->thread, machine);
- }
- if (!c->sample->insn_len)
- Py_RETURN_NONE; /* N.B. This is a return statement */
-
- return _PyBytes_FromStringAndSize(c->sample->insn, c->sample->insn_len);
-}
-
-static PyObject *perf_set_itrace_options(PyObject *obj, PyObject *args)
-{
- struct scripting_context *c;
- const char *itrace_options;
- int retval = -1;
- PyObject *str;
-
- c = get_args(args, "itrace_options", &str);
- if (!c)
- return NULL;
-
- if (!c->session || !c->session->itrace_synth_opts)
- goto out;
-
- if (c->session->itrace_synth_opts->set) {
- retval = 1;
- goto out;
- }
-
- itrace_options = _PyUnicode_AsUTF8(str);
-
- retval = itrace_do_parse_synth_opts(c->session->itrace_synth_opts, itrace_options, 0);
-out:
- return Py_BuildValue("i", retval);
-}
-
-static PyObject *perf_sample_src(PyObject *obj, PyObject *args, bool get_srccode)
-{
- struct scripting_context *c = get_scripting_context(args);
- unsigned int line = 0;
- char *srcfile = NULL;
- char *srccode = NULL;
- PyObject *result;
- struct map *map;
- struct dso *dso;
- int len = 0;
- u64 addr;
-
- if (!c)
- return NULL;
-
- map = c->al->map;
- addr = c->al->addr;
- dso = map ? map__dso(map) : NULL;
-
- if (dso)
- srcfile = get_srcline_split(dso, map__rip_2objdump(map, addr), &line);
-
- if (get_srccode) {
- if (srcfile)
- srccode = find_sourceline(srcfile, line, &len);
- result = Py_BuildValue("(sIs#)", srcfile, line, srccode, (Py_ssize_t)len);
- } else {
- result = Py_BuildValue("(sI)", srcfile, line);
- }
-
- free(srcfile);
-
- return result;
-}
-
-static PyObject *perf_sample_srcline(PyObject *obj, PyObject *args)
-{
- return perf_sample_src(obj, args, false);
-}
-
-static PyObject *perf_sample_srccode(PyObject *obj, PyObject *args)
-{
- return perf_sample_src(obj, args, true);
-}
-
-static PyObject *__perf_config_get(PyObject *obj, PyObject *args)
-{
- const char *config_name;
-
- if (!PyArg_ParseTuple(args, "s", &config_name))
- return NULL;
- return Py_BuildValue("s", perf_config_get(config_name));
-}
-
-static PyMethodDef ContextMethods[] = {
-#ifdef HAVE_LIBTRACEEVENT
- { "common_pc", perf_trace_context_common_pc, METH_VARARGS,
- "Get the common preempt count event field value."},
- { "common_flags", perf_trace_context_common_flags, METH_VARARGS,
- "Get the common flags event field value."},
- { "common_lock_depth", perf_trace_context_common_lock_depth,
- METH_VARARGS, "Get the common lock depth event field value."},
-#endif
- { "perf_sample_insn", perf_sample_insn,
- METH_VARARGS, "Get the machine code instruction."},
- { "perf_set_itrace_options", perf_set_itrace_options,
- METH_VARARGS, "Set --itrace options."},
- { "perf_sample_srcline", perf_sample_srcline,
- METH_VARARGS, "Get source file name and line number."},
- { "perf_sample_srccode", perf_sample_srccode,
- METH_VARARGS, "Get source file name, line number and line."},
- { "perf_config_get", __perf_config_get, METH_VARARGS, "Get perf config entry"},
- { NULL, NULL, 0, NULL}
-};
-
-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 */
- };
- PyObject *mod;
-
- mod = PyModule_Create(&moduledef);
- /* Add perf_script_context to the module so it can be imported */
- PyObject_SetAttrString(mod, "perf_script_context", Py_None);
-
- return mod;
-}
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
deleted file mode 100644
index 54ace2f6bc36..000000000000
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Core.py - Python extension for perf script, core functions
-#
-# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com>
-#
-# This software may be distributed under the terms of the GNU General
-# Public License ("GPL") version 2 as published by the Free Software
-# Foundation.
-
-from collections import defaultdict
-
-def autodict():
- return defaultdict(autodict)
-
-flag_fields = autodict()
-symbolic_fields = autodict()
-
-def define_flag_field(event_name, field_name, delim):
- flag_fields[event_name][field_name]['delim'] = delim
-
-def define_flag_value(event_name, field_name, value, field_str):
- flag_fields[event_name][field_name]['values'][value] = field_str
-
-def define_symbolic_field(event_name, field_name):
- # nothing to do, really
- pass
-
-def define_symbolic_value(event_name, field_name, value, field_str):
- symbolic_fields[event_name][field_name]['values'][value] = field_str
-
-def flag_str(event_name, field_name, value):
- string = ""
-
- if flag_fields[event_name][field_name]:
- print_delim = 0
- for idx in sorted(flag_fields[event_name][field_name]['values']):
- if not value and not idx:
- string += flag_fields[event_name][field_name]['values'][idx]
- break
- if idx and (value & idx) == idx:
- if print_delim and flag_fields[event_name][field_name]['delim']:
- string += " " + flag_fields[event_name][field_name]['delim'] + " "
- string += flag_fields[event_name][field_name]['values'][idx]
- print_delim = 1
- value &= ~idx
-
- return string
-
-def symbol_str(event_name, field_name, value):
- string = ""
-
- if symbolic_fields[event_name][field_name]:
- for idx in sorted(symbolic_fields[event_name][field_name]['values']):
- if not value and not idx:
- string = symbolic_fields[event_name][field_name]['values'][idx]
- break
- if (value == idx):
- string = symbolic_fields[event_name][field_name]['values'][idx]
- break
-
- return string
-
-trace_flags = { 0x00: "NONE", \
- 0x01: "IRQS_OFF", \
- 0x02: "IRQS_NOSUPPORT", \
- 0x04: "NEED_RESCHED", \
- 0x08: "HARDIRQ", \
- 0x10: "SOFTIRQ" }
-
-def trace_flag_str(value):
- string = ""
- print_delim = 0
-
- for idx in trace_flags:
- if not value and not idx:
- string += "NONE"
- break
-
- if idx and (value & idx) == idx:
- if print_delim:
- string += " | ";
- string += trace_flags[idx]
- print_delim = 1
- value &= ~idx
-
- return string
-
-
-def taskState(state):
- states = {
- 0 : "R",
- 1 : "S",
- 2 : "D",
- 64: "DEAD"
- }
-
- if state not in states:
- return "Unknown"
-
- return states[state]
-
-
-class EventHeaders:
- def __init__(self, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm, common_callchain):
- self.cpu = common_cpu
- self.secs = common_secs
- self.nsecs = common_nsecs
- self.pid = common_pid
- self.comm = common_comm
- self.callchain = common_callchain
-
- def ts(self):
- return (self.secs * (10 ** 9)) + self.nsecs
-
- def ts_format(self):
- return "%d.%d" % (self.secs, int(self.nsecs / 1000))
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py
deleted file mode 100755
index 21a7a1298094..000000000000
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py
+++ /dev/null
@@ -1,97 +0,0 @@
-# EventClass.py
-# SPDX-License-Identifier: GPL-2.0
-#
-# This is a library defining some events types classes, which could
-# be used by other scripts to analyzing the perf samples.
-#
-# Currently there are just a few classes defined for examples,
-# PerfEvent is the base class for all perf event sample, PebsEvent
-# is a HW base Intel x86 PEBS event, and user could add more SW/HW
-# event classes based on requirements.
-from __future__ import print_function
-
-import struct
-
-# Event types, user could add more here
-EVTYPE_GENERIC = 0
-EVTYPE_PEBS = 1 # Basic PEBS event
-EVTYPE_PEBS_LL = 2 # PEBS event with load latency info
-EVTYPE_IBS = 3
-
-#
-# Currently we don't have good way to tell the event type, but by
-# the size of raw buffer, raw PEBS event with load latency data's
-# size is 176 bytes, while the pure PEBS event's size is 144 bytes.
-#
-def create_event(name, comm, dso, symbol, raw_buf):
- if (len(raw_buf) == 144):
- event = PebsEvent(name, comm, dso, symbol, raw_buf)
- elif (len(raw_buf) == 176):
- event = PebsNHM(name, comm, dso, symbol, raw_buf)
- else:
- event = PerfEvent(name, comm, dso, symbol, raw_buf)
-
- return event
-
-class PerfEvent(object):
- event_num = 0
- def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_GENERIC):
- self.name = name
- self.comm = comm
- self.dso = dso
- self.symbol = symbol
- self.raw_buf = raw_buf
- self.ev_type = ev_type
- PerfEvent.event_num += 1
-
- def show(self):
- print("PMU event: name=%12s, symbol=%24s, comm=%8s, dso=%12s" %
- (self.name, self.symbol, self.comm, self.dso))
-
-#
-# Basic Intel PEBS (Precise Event-based Sampling) event, whose raw buffer
-# contains the context info when that event happened: the EFLAGS and
-# linear IP info, as well as all the registers.
-#
-class PebsEvent(PerfEvent):
- pebs_num = 0
- def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_PEBS):
- tmp_buf=raw_buf[0:80]
- flags, ip, ax, bx, cx, dx, si, di, bp, sp = struct.unpack('QQQQQQQQQQ', tmp_buf)
- self.flags = flags
- self.ip = ip
- self.ax = ax
- self.bx = bx
- self.cx = cx
- self.dx = dx
- self.si = si
- self.di = di
- self.bp = bp
- self.sp = sp
-
- PerfEvent.__init__(self, name, comm, dso, symbol, raw_buf, ev_type)
- PebsEvent.pebs_num += 1
- del tmp_buf
-
-#
-# Intel Nehalem and Westmere support PEBS plus Load Latency info which lie
-# in the four 64 bit words write after the PEBS data:
-# Status: records the IA32_PERF_GLOBAL_STATUS register value
-# DLA: Data Linear Address (EIP)
-# DSE: Data Source Encoding, where the latency happens, hit or miss
-# in L1/L2/L3 or IO operations
-# LAT: the actual latency in cycles
-#
-class PebsNHM(PebsEvent):
- pebs_nhm_num = 0
- def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_PEBS_LL):
- tmp_buf=raw_buf[144:176]
- status, dla, dse, lat = struct.unpack('QQQQ', tmp_buf)
- self.status = status
- self.dla = dla
- self.dse = dse
- self.lat = lat
-
- PebsEvent.__init__(self, name, comm, dso, symbol, raw_buf, ev_type)
- PebsNHM.pebs_nhm_num += 1
- del tmp_buf
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
deleted file mode 100644
index cac7b2542ee8..000000000000
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
+++ /dev/null
@@ -1,184 +0,0 @@
-# SchedGui.py - Python extension for perf script, basic GUI code for
-# traces drawing and overview.
-#
-# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com>
-#
-# This software is distributed under the terms of the GNU General
-# Public License ("GPL") version 2 as published by the Free Software
-# Foundation.
-
-
-try:
- import wx
-except ImportError:
- raise ImportError("You need to install the wxpython lib for this script")
-
-
-class RootFrame(wx.Frame):
- Y_OFFSET = 100
- RECT_HEIGHT = 100
- RECT_SPACE = 50
- EVENT_MARKING_WIDTH = 5
-
- def __init__(self, sched_tracer, title, parent = None, id = -1):
- wx.Frame.__init__(self, parent, id, title)
-
- (self.screen_width, self.screen_height) = wx.GetDisplaySize()
- self.screen_width -= 10
- self.screen_height -= 10
- self.zoom = 0.5
- self.scroll_scale = 20
- self.sched_tracer = sched_tracer
- self.sched_tracer.set_root_win(self)
- (self.ts_start, self.ts_end) = sched_tracer.interval()
- self.update_width_virtual()
- self.nr_rects = sched_tracer.nr_rectangles() + 1
- self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
-
- # whole window panel
- self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height))
-
- # scrollable container
- self.scroll = wx.ScrolledWindow(self.panel)
- self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale)
- self.scroll.EnableScrolling(True, True)
- self.scroll.SetFocus()
-
- # scrollable drawing area
- self.scroll_panel = wx.Panel(self.scroll, size=(self.screen_width - 15, self.screen_height / 2))
- self.scroll_panel.Bind(wx.EVT_PAINT, self.on_paint)
- self.scroll_panel.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
- self.scroll_panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
- self.scroll.Bind(wx.EVT_PAINT, self.on_paint)
- self.scroll.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
- self.scroll.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
-
- self.scroll.Fit()
- self.Fit()
-
- self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, self.height_virtual, wx.SIZE_USE_EXISTING)
-
- self.txt = None
-
- self.Show(True)
-
- def us_to_px(self, val):
- return val / (10 ** 3) * self.zoom
-
- def px_to_us(self, val):
- return (val / self.zoom) * (10 ** 3)
-
- def scroll_start(self):
- (x, y) = self.scroll.GetViewStart()
- return (x * self.scroll_scale, y * self.scroll_scale)
-
- def scroll_start_us(self):
- (x, y) = self.scroll_start()
- return self.px_to_us(x)
-
- def paint_rectangle_zone(self, nr, color, top_color, start, end):
- offset_px = self.us_to_px(start - self.ts_start)
- width_px = self.us_to_px(end - self.ts_start)
-
- offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
- width_py = RootFrame.RECT_HEIGHT
-
- dc = self.dc
-
- if top_color is not None:
- (r, g, b) = top_color
- top_color = wx.Colour(r, g, b)
- brush = wx.Brush(top_color, wx.SOLID)
- dc.SetBrush(brush)
- dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH)
- width_py -= RootFrame.EVENT_MARKING_WIDTH
- offset_py += RootFrame.EVENT_MARKING_WIDTH
-
- (r ,g, b) = color
- color = wx.Colour(r, g, b)
- brush = wx.Brush(color, wx.SOLID)
- dc.SetBrush(brush)
- dc.DrawRectangle(offset_px, offset_py, width_px, width_py)
-
- def update_rectangles(self, dc, start, end):
- start += self.ts_start
- end += self.ts_start
- self.sched_tracer.fill_zone(start, end)
-
- def on_paint(self, event):
- dc = wx.PaintDC(self.scroll_panel)
- self.dc = dc
-
- width = min(self.width_virtual, self.screen_width)
- (x, y) = self.scroll_start()
- start = self.px_to_us(x)
- end = self.px_to_us(x + width)
- self.update_rectangles(dc, start, end)
-
- def rect_from_ypixel(self, y):
- y -= RootFrame.Y_OFFSET
- rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
- height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
-
- if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT:
- return -1
-
- return rect
-
- def update_summary(self, txt):
- if self.txt:
- self.txt.Destroy()
- self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50))
-
-
- def on_mouse_down(self, event):
- (x, y) = event.GetPositionTuple()
- rect = self.rect_from_ypixel(y)
- if rect == -1:
- return
-
- t = self.px_to_us(x) + self.ts_start
-
- self.sched_tracer.mouse_down(rect, t)
-
-
- def update_width_virtual(self):
- self.width_virtual = self.us_to_px(self.ts_end - self.ts_start)
-
- def __zoom(self, x):
- self.update_width_virtual()
- (xpos, ypos) = self.scroll.GetViewStart()
- xpos = self.us_to_px(x) / self.scroll_scale
- self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale, xpos, ypos)
- self.Refresh()
-
- def zoom_in(self):
- x = self.scroll_start_us()
- self.zoom *= 2
- self.__zoom(x)
-
- def zoom_out(self):
- x = self.scroll_start_us()
- self.zoom /= 2
- self.__zoom(x)
-
-
- def on_key_press(self, event):
- key = event.GetRawKeyCode()
- if key == ord("+"):
- self.zoom_in()
- return
- if key == ord("-"):
- self.zoom_out()
- return
-
- key = event.GetKeyCode()
- (x, y) = self.scroll.GetViewStart()
- if key == wx.WXK_RIGHT:
- self.scroll.Scroll(x + 1, y)
- elif key == wx.WXK_LEFT:
- self.scroll.Scroll(x - 1, y)
- elif key == wx.WXK_DOWN:
- self.scroll.Scroll(x, y + 1)
- elif key == wx.WXK_UP:
- self.scroll.Scroll(x, y - 1)
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
deleted file mode 100644
index b75d31858e54..000000000000
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Util.py - Python extension for perf script, miscellaneous utility code
-#
-# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com>
-#
-# This software may be distributed under the terms of the GNU General
-# Public License ("GPL") version 2 as published by the Free Software
-# Foundation.
-from __future__ import print_function
-
-import errno, os
-
-FUTEX_WAIT = 0
-FUTEX_WAKE = 1
-FUTEX_PRIVATE_FLAG = 128
-FUTEX_CLOCK_REALTIME = 256
-FUTEX_CMD_MASK = ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
-
-NSECS_PER_SEC = 1000000000
-
-def avg(total, n):
- return total / n
-
-def nsecs(secs, nsecs):
- return secs * NSECS_PER_SEC + nsecs
-
-def nsecs_secs(nsecs):
- return nsecs / NSECS_PER_SEC
-
-def nsecs_nsecs(nsecs):
- return nsecs % NSECS_PER_SEC
-
-def nsecs_str(nsecs):
- str = "%5u.%09u" % (nsecs_secs(nsecs), nsecs_nsecs(nsecs)),
- return str
-
-def add_stats(dict, key, value):
- if key not in dict:
- dict[key] = (value, value, value, 1)
- else:
- min, max, avg, count = dict[key]
- if value < min:
- min = value
- if value > max:
- max = value
- avg = (avg + value) / 2
- dict[key] = (min, max, avg, count + 1)
-
-def clear_term():
- print("\x1b[H\x1b[2J")
-
-audit_package_warned = False
-
-try:
- import audit
- machine_to_id = {
- 'x86_64': audit.MACH_86_64,
- 'aarch64': audit.MACH_AARCH64,
- 'alpha' : audit.MACH_ALPHA,
- 'ia64' : audit.MACH_IA64,
- 'ppc' : audit.MACH_PPC,
- 'ppc64' : audit.MACH_PPC64,
- 'ppc64le' : audit.MACH_PPC64LE,
- 's390' : audit.MACH_S390,
- 's390x' : audit.MACH_S390X,
- 'i386' : audit.MACH_X86,
- 'i586' : audit.MACH_X86,
- 'i686' : audit.MACH_X86,
- }
- try:
- machine_to_id['armeb'] = audit.MACH_ARMEB
- except:
- pass
- machine_id = machine_to_id[os.uname()[4]]
-except:
- if not audit_package_warned:
- audit_package_warned = True
- print("Install the python-audit package to get syscall names.\n"
- "For example:\n # apt-get install python3-audit (Ubuntu)"
- "\n # yum install python3-audit (Fedora)"
- "\n etc.\n")
-
-def syscall_name(id):
- try:
- return audit.audit_syscall_to_name(id, machine_id)
- except:
- return str(id)
-
-def strerror(nr):
- try:
- return errno.errorcode[abs(nr)]
- except:
- return "Unknown %d errno" % nr
diff --git a/tools/perf/scripts/python/arm-cs-trace-disasm.py b/tools/perf/scripts/python/arm-cs-trace-disasm.py
deleted file mode 100755
index ba208c90d631..000000000000
--- a/tools/perf/scripts/python/arm-cs-trace-disasm.py
+++ /dev/null
@@ -1,355 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# arm-cs-trace-disasm.py: ARM CoreSight Trace Dump With Disassember
-#
-# Author: Tor Jeremiassen <tor@ti.com>
-# Mathieu Poirier <mathieu.poirier@linaro.org>
-# Leo Yan <leo.yan@linaro.org>
-# Al Grant <Al.Grant@arm.com>
-
-from __future__ import print_function
-import os
-from os import path
-import re
-from subprocess import *
-import argparse
-import platform
-
-from perf_trace_context import perf_sample_srccode, perf_config_get
-
-# Below are some example commands for using this script.
-# Note a --kcore recording is required for accurate decode
-# due to the alternatives patching mechanism. However this
-# script only supports reading vmlinux for disassembly dump,
-# meaning that any patched instructions will appear
-# as unpatched, but the instruction ranges themselves will
-# be correct. In addition to this, source line info comes
-# from Perf, and when using kcore there is no debug info. The
-# following lists the supported features in each mode:
-#
-# +-----------+-----------------+------------------+------------------+
-# | Recording | Accurate decode | Source line dump | Disassembly dump |
-# +-----------+-----------------+------------------+------------------+
-# | --kcore | yes | no | yes |
-# | normal | no | yes | yes |
-# +-----------+-----------------+------------------+------------------+
-#
-# Output disassembly with objdump and auto detect vmlinux
-# (when running on same machine.)
-# perf script -s scripts/python/arm-cs-trace-disasm.py -d
-#
-# Output disassembly with llvm-objdump:
-# perf script -s scripts/python/arm-cs-trace-disasm.py \
-# -- -d llvm-objdump-11 -k path/to/vmlinux
-#
-# Output only source line and symbols:
-# perf script -s scripts/python/arm-cs-trace-disasm.py
-
-def default_objdump():
- config = perf_config_get("annotate.objdump")
- return config if config else "objdump"
-
-# Command line parsing.
-def int_arg(v):
- v = int(v)
- if v < 0:
- raise argparse.ArgumentTypeError("Argument must be a positive integer")
- return v
-
-args = argparse.ArgumentParser()
-args.add_argument("-k", "--vmlinux",
- help="Set path to vmlinux file. Omit to autodetect if running on same machine")
-args.add_argument("-d", "--objdump", nargs="?", const=default_objdump(),
- help="Show disassembly. Can also be used to change the objdump path"),
-args.add_argument("-v", "--verbose", action="store_true", help="Enable debugging log")
-args.add_argument("--start-time", type=int_arg, help="Monotonic clock time of sample to start from. "
- "See 'time' field on samples in -v mode.")
-args.add_argument("--stop-time", type=int_arg, help="Monotonic clock time of sample to stop at. "
- "See 'time' field on samples in -v mode.")
-args.add_argument("--start-sample", type=int_arg, help="Index of sample to start from. "
- "See 'index' field on samples in -v mode.")
-args.add_argument("--stop-sample", type=int_arg, help="Index of sample to stop at. "
- "See 'index' field on samples in -v mode.")
-
-options = args.parse_args()
-if (options.start_time and options.stop_time and
- options.start_time >= options.stop_time):
- print("--start-time must less than --stop-time")
- exit(2)
-if (options.start_sample and options.stop_sample and
- options.start_sample >= options.stop_sample):
- print("--start-sample must less than --stop-sample")
- exit(2)
-
-# Initialize global dicts and regular expression
-disasm_cache = dict()
-cpu_data = dict()
-disasm_re = re.compile(r"^\s*([0-9a-fA-F]+):")
-disasm_func_re = re.compile(r"^\s*([0-9a-fA-F]+)\s.*:")
-cache_size = 64*1024
-sample_idx = -1
-
-glb_source_file_name = None
-glb_line_number = None
-glb_dso = None
-
-kver = platform.release()
-vmlinux_paths = [
- f"/usr/lib/debug/boot/vmlinux-{kver}.debug",
- f"/usr/lib/debug/lib/modules/{kver}/vmlinux",
- f"/lib/modules/{kver}/build/vmlinux",
- f"/usr/lib/debug/boot/vmlinux-{kver}",
- f"/boot/vmlinux-{kver}",
- f"/boot/vmlinux",
- f"vmlinux"
-]
-
-def get_optional(perf_dict, field):
- if field in perf_dict:
- return perf_dict[field]
- return "[unknown]"
-
-def get_offset(perf_dict, field):
- if field in perf_dict:
- return "+%#x" % perf_dict[field]
- return ""
-
-def find_vmlinux():
- if hasattr(find_vmlinux, "path"):
- return find_vmlinux.path
-
- for v in vmlinux_paths:
- if os.access(v, os.R_OK):
- find_vmlinux.path = v
- break
- else:
- find_vmlinux.path = None
-
- return find_vmlinux.path
-
-def get_dso_file_path(dso_name, dso_build_id):
- if (dso_name == "[kernel.kallsyms]" or dso_name == "vmlinux"):
- if (options.vmlinux):
- return options.vmlinux;
- else:
- return find_vmlinux() if find_vmlinux() else dso_name
-
- if (dso_name == "[vdso]") :
- append = "/vdso"
- else:
- append = "/elf"
-
- dso_path = os.environ['PERF_BUILDID_DIR'] + "/" + dso_name + "/" + dso_build_id + append;
- # Replace duplicate slash chars to single slash char
- dso_path = dso_path.replace('//', '/', 1)
- return dso_path
-
-def read_disam(dso_fname, dso_start, start_addr, stop_addr):
- addr_range = str(start_addr) + ":" + str(stop_addr) + ":" + dso_fname
-
- # Don't let the cache get too big, clear it when it hits max size
- if (len(disasm_cache) > cache_size):
- disasm_cache.clear();
-
- if addr_range in disasm_cache:
- disasm_output = disasm_cache[addr_range];
- else:
- start_addr = start_addr - dso_start;
- stop_addr = stop_addr - dso_start;
- disasm = [ options.objdump, "-d", "-z",
- "--start-address="+format(start_addr,"#x"),
- "--stop-address="+format(stop_addr,"#x") ]
- disasm += [ dso_fname ]
- disasm_output = check_output(disasm).decode('utf-8').split('\n')
- disasm_cache[addr_range] = disasm_output
-
- return disasm_output
-
-def print_disam(dso_fname, dso_start, start_addr, stop_addr):
- for line in read_disam(dso_fname, dso_start, start_addr, stop_addr):
- m = disasm_func_re.search(line)
- if m is None:
- m = disasm_re.search(line)
- if m is None:
- continue
- print("\t" + line)
-
-def print_sample(sample):
- print("Sample = { cpu: %04d addr: 0x%016x phys_addr: 0x%016x ip: 0x%016x " \
- "pid: %d tid: %d period: %d time: %d index: %d}" % \
- (sample['cpu'], sample['addr'], sample['phys_addr'], \
- sample['ip'], sample['pid'], sample['tid'], \
- sample['period'], sample['time'], sample_idx))
-
-def trace_begin():
- print('ARM CoreSight Trace Data Assembler Dump')
-
-def trace_end():
- print('End')
-
-def trace_unhandled(event_name, context, event_fields_dict):
- print(' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]))
-
-def common_start_str(comm, sample):
- sec = int(sample["time"] / 1000000000)
- ns = sample["time"] % 1000000000
- cpu = sample["cpu"]
- pid = sample["pid"]
- tid = sample["tid"]
- return "%16s %5u/%-5u [%04u] %9u.%09u " % (comm, pid, tid, cpu, sec, ns)
-
-# This code is copied from intel-pt-events.py for printing source code
-# line and symbols.
-def print_srccode(comm, param_dict, sample, symbol, dso):
- ip = sample["ip"]
- if symbol == "[unknown]":
- start_str = common_start_str(comm, sample) + ("%x" % ip).rjust(16).ljust(40)
- else:
- offs = get_offset(param_dict, "symoff")
- start_str = common_start_str(comm, sample) + (symbol + offs).ljust(40)
-
- global glb_source_file_name
- global glb_line_number
- global glb_dso
-
- source_file_name, line_number, source_line = perf_sample_srccode(perf_script_context)
- if source_file_name:
- if glb_line_number == line_number and glb_source_file_name == source_file_name:
- src_str = ""
- else:
- if len(source_file_name) > 40:
- src_file = ("..." + source_file_name[-37:]) + " "
- else:
- src_file = source_file_name.ljust(41)
-
- if source_line is None:
- src_str = src_file + str(line_number).rjust(4) + " "
- else:
- src_str = src_file + str(line_number).rjust(4) + " " + source_line
- glb_dso = None
- elif dso == glb_dso:
- src_str = ""
- else:
- src_str = dso
- glb_dso = dso
-
- glb_line_number = line_number
- glb_source_file_name = source_file_name
-
- print(start_str, src_str)
-
-def process_event(param_dict):
- global cache_size
- global options
- global sample_idx
-
- sample = param_dict["sample"]
- comm = param_dict["comm"]
-
- name = param_dict["ev_name"]
- dso = get_optional(param_dict, "dso")
- dso_bid = get_optional(param_dict, "dso_bid")
- dso_start = get_optional(param_dict, "dso_map_start")
- dso_end = get_optional(param_dict, "dso_map_end")
- symbol = get_optional(param_dict, "symbol")
- map_pgoff = get_optional(param_dict, "map_pgoff")
- # check for valid map offset
- if (str(map_pgoff) == '[unknown]'):
- map_pgoff = 0
-
- cpu = sample["cpu"]
- ip = sample["ip"]
- addr = sample["addr"]
-
- sample_idx += 1
-
- if (options.start_time and sample["time"] < options.start_time):
- return
- if (options.stop_time and sample["time"] > options.stop_time):
- exit(0)
- if (options.start_sample and sample_idx < options.start_sample):
- return
- if (options.stop_sample and sample_idx > options.stop_sample):
- exit(0)
-
- if (options.verbose == True):
- print("Event type: %s" % name)
- print_sample(sample)
-
- # Initialize CPU data if it's empty, and directly return back
- # if this is the first tracing event for this CPU.
- if (cpu_data.get(str(cpu) + 'addr') == None):
- cpu_data[str(cpu) + 'addr'] = addr
- return
-
- # If cannot find dso so cannot dump assembler, bail out
- if (dso == '[unknown]'):
- return
-
- # Validate dso start and end addresses
- if ((dso_start == '[unknown]') or (dso_end == '[unknown]')):
- print("Failed to find valid dso map for dso %s" % dso)
- return
-
- if (name[0:12] == "instructions"):
- print_srccode(comm, param_dict, sample, symbol, dso)
- return
-
- # Don't proceed if this event is not a branch sample, .
- if (name[0:8] != "branches"):
- return
-
- # The format for packet is:
- #
- # +------------+------------+------------+
- # sample_prev: | addr | ip | cpu |
- # +------------+------------+------------+
- # sample_next: | addr | ip | cpu |
- # +------------+------------+------------+
- #
- # We need to combine the two continuous packets to get the instruction
- # range for sample_prev::cpu:
- #
- # [ sample_prev::addr .. sample_next::ip ]
- #
- # For this purose, sample_prev::addr is stored into cpu_data structure
- # and read back for 'start_addr' when the new packet comes, and we need
- # to use sample_next::ip to calculate 'stop_addr', plusing extra 4 for
- # 'stop_addr' is for the sake of objdump so the final assembler dump can
- # include last instruction for sample_next::ip.
- start_addr = cpu_data[str(cpu) + 'addr']
- stop_addr = ip + 4
-
- # Record for previous sample packet
- cpu_data[str(cpu) + 'addr'] = addr
-
- # Filter out zero start_address. Optionally identify CS_ETM_TRACE_ON packet
- if (start_addr == 0):
- if ((stop_addr == 4) and (options.verbose == True)):
- print("CPU%d: CS_ETM_TRACE_ON packet is inserted" % cpu)
- return
-
- if (start_addr < int(dso_start) or start_addr > int(dso_end)):
- print("Start address 0x%x is out of range [ 0x%x .. 0x%x ] for dso %s" % (start_addr, int(dso_start), int(dso_end), dso))
- return
-
- if (stop_addr < int(dso_start) or stop_addr > int(dso_end)):
- print("Stop address 0x%x is out of range [ 0x%x .. 0x%x ] for dso %s" % (stop_addr, int(dso_start), int(dso_end), dso))
- return
-
- if (options.objdump != None):
- # It doesn't need to decrease virtual memory offset for disassembly
- # for kernel dso and executable file dso, so in this case we set
- # vm_start to zero.
- if (dso == "[kernel.kallsyms]" or dso_start == 0x400000):
- dso_vm_start = 0
- map_pgoff = 0
- else:
- dso_vm_start = int(dso_start)
-
- dso_fname = get_dso_file_path(dso, dso_bid)
- if path.exists(dso_fname):
- print_disam(dso_fname, dso_vm_start, start_addr + map_pgoff, stop_addr + map_pgoff)
- else:
- print("Failed to find dso %s for address range [ 0x%x .. 0x%x ]" % (dso, start_addr + map_pgoff, stop_addr + map_pgoff))
-
- print_srccode(comm, param_dict, sample, symbol, dso)
diff --git a/tools/perf/scripts/python/bin/compaction-times-record b/tools/perf/scripts/python/bin/compaction-times-record
deleted file mode 100644
index 6edcd40e14e8..000000000000
--- a/tools/perf/scripts/python/bin/compaction-times-record
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-perf record -e compaction:mm_compaction_begin -e compaction:mm_compaction_end -e compaction:mm_compaction_migratepages -e compaction:mm_compaction_isolate_migratepages -e compaction:mm_compaction_isolate_freepages $@
diff --git a/tools/perf/scripts/python/bin/compaction-times-report b/tools/perf/scripts/python/bin/compaction-times-report
deleted file mode 100644
index 3dc13897cfde..000000000000
--- a/tools/perf/scripts/python/bin/compaction-times-report
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-#description: display time taken by mm compaction
-#args: [-h] [-u] [-p|-pv] [-t | [-m] [-fs] [-ms]] [pid|pid-range|comm-regex]
-perf script -s "$PERF_EXEC_PATH"/scripts/python/compaction-times.py $@
diff --git a/tools/perf/scripts/python/bin/event_analyzing_sample-record b/tools/perf/scripts/python/bin/event_analyzing_sample-record
deleted file mode 100644
index 5ce652dabd02..000000000000
--- a/tools/perf/scripts/python/bin/event_analyzing_sample-record
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-#
-# event_analyzing_sample.py can cover all type of perf samples including
-# the tracepoints, so no special record requirements, just record what
-# you want to analyze.
-#
-perf record $@
diff --git a/tools/perf/scripts/python/bin/event_analyzing_sample-report b/tools/perf/scripts/python/bin/event_analyzing_sample-report
deleted file mode 100644
index 0941fc94e158..000000000000
--- a/tools/perf/scripts/python/bin/event_analyzing_sample-report
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-# description: analyze all perf samples
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/event_analyzing_sample.py
diff --git a/tools/perf/scripts/python/bin/export-to-postgresql-record b/tools/perf/scripts/python/bin/export-to-postgresql-record
deleted file mode 100644
index 221d66e05713..000000000000
--- a/tools/perf/scripts/python/bin/export-to-postgresql-record
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-#
-# export perf data to a postgresql database. Can cover
-# perf ip samples (excluding the tracepoints). No special
-# record requirements, just record what you want to export.
-#
-perf record $@
diff --git a/tools/perf/scripts/python/bin/export-to-postgresql-report b/tools/perf/scripts/python/bin/export-to-postgresql-report
deleted file mode 100644
index cd335b6e2a01..000000000000
--- a/tools/perf/scripts/python/bin/export-to-postgresql-report
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-# description: export perf data to a postgresql database
-# args: [database name] [columns] [calls]
-n_args=0
-for i in "$@"
-do
- if expr match "$i" "-" > /dev/null ; then
- break
- fi
- n_args=$(( $n_args + 1 ))
-done
-if [ "$n_args" -gt 3 ] ; then
- echo "usage: export-to-postgresql-report [database name] [columns] [calls]"
- exit
-fi
-if [ "$n_args" -gt 2 ] ; then
- dbname=$1
- columns=$2
- calls=$3
- shift 3
-elif [ "$n_args" -gt 1 ] ; then
- dbname=$1
- columns=$2
- shift 2
-elif [ "$n_args" -gt 0 ] ; then
- dbname=$1
- shift
-fi
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/export-to-postgresql.py $dbname $columns $calls
diff --git a/tools/perf/scripts/python/bin/export-to-sqlite-record b/tools/perf/scripts/python/bin/export-to-sqlite-record
deleted file mode 100644
index 070204fd6d00..000000000000
--- a/tools/perf/scripts/python/bin/export-to-sqlite-record
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-#
-# export perf data to a sqlite3 database. Can cover
-# perf ip samples (excluding the tracepoints). No special
-# record requirements, just record what you want to export.
-#
-perf record $@
diff --git a/tools/perf/scripts/python/bin/export-to-sqlite-report b/tools/perf/scripts/python/bin/export-to-sqlite-report
deleted file mode 100644
index 5ff6033e70ba..000000000000
--- a/tools/perf/scripts/python/bin/export-to-sqlite-report
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-# description: export perf data to a sqlite3 database
-# args: [database name] [columns] [calls]
-n_args=0
-for i in "$@"
-do
- if expr match "$i" "-" > /dev/null ; then
- break
- fi
- n_args=$(( $n_args + 1 ))
-done
-if [ "$n_args" -gt 3 ] ; then
- echo "usage: export-to-sqlite-report [database name] [columns] [calls]"
- exit
-fi
-if [ "$n_args" -gt 2 ] ; then
- dbname=$1
- columns=$2
- calls=$3
- shift 3
-elif [ "$n_args" -gt 1 ] ; then
- dbname=$1
- columns=$2
- shift 2
-elif [ "$n_args" -gt 0 ] ; then
- dbname=$1
- shift
-fi
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/export-to-sqlite.py $dbname $columns $calls
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
deleted file mode 100644
index 74685f318379..000000000000
--- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-(perf record -e raw_syscalls:sys_exit $@ || \
- perf record -e syscalls:sys_exit $@) 2> /dev/null
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
deleted file mode 100644
index fda5096d0cbf..000000000000
--- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-# description: system-wide failed syscalls, by pid
-# args: [comm]
-if [ $# -gt 0 ] ; then
- if ! expr match "$1" "-" > /dev/null ; then
- comm=$1
- shift
- fi
-fi
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/failed-syscalls-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/flamegraph-record b/tools/perf/scripts/python/bin/flamegraph-record
deleted file mode 100755
index 7df5a19c0163..000000000000
--- a/tools/perf/scripts/python/bin/flamegraph-record
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-perf record -g "$@"
diff --git a/tools/perf/scripts/python/bin/flamegraph-report b/tools/perf/scripts/python/bin/flamegraph-report
deleted file mode 100755
index 453a6918afbe..000000000000
--- a/tools/perf/scripts/python/bin/flamegraph-report
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-# description: create flame graphs
-perf script -s "$PERF_EXEC_PATH"/scripts/python/flamegraph.py "$@"
diff --git a/tools/perf/scripts/python/bin/futex-contention-record b/tools/perf/scripts/python/bin/futex-contention-record
deleted file mode 100644
index b1495c9a9b20..000000000000
--- a/tools/perf/scripts/python/bin/futex-contention-record
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-perf record -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@
diff --git a/tools/perf/scripts/python/bin/futex-contention-report b/tools/perf/scripts/python/bin/futex-contention-report
deleted file mode 100644
index 6c44271091ab..000000000000
--- a/tools/perf/scripts/python/bin/futex-contention-report
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-# description: futext contention measurement
-
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/futex-contention.py
diff --git a/tools/perf/scripts/python/bin/gecko-record b/tools/perf/scripts/python/bin/gecko-record
deleted file mode 100644
index f0d1aa55f171..000000000000
--- a/tools/perf/scripts/python/bin/gecko-record
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-perf record -F 99 -g "$@"
diff --git a/tools/perf/scripts/python/bin/gecko-report b/tools/perf/scripts/python/bin/gecko-report
deleted file mode 100755
index 1867ec8d9757..000000000000
--- a/tools/perf/scripts/python/bin/gecko-report
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-# description: create firefox gecko profile json format from perf.data
-if [ "$*" = "-i -" ]; then
-perf script -s "$PERF_EXEC_PATH"/scripts/python/gecko.py
-else
-perf script -s "$PERF_EXEC_PATH"/scripts/python/gecko.py -- "$@"
-fi
diff --git a/tools/perf/scripts/python/bin/intel-pt-events-record b/tools/perf/scripts/python/bin/intel-pt-events-record
deleted file mode 100644
index 6b9877cfe23e..000000000000
--- a/tools/perf/scripts/python/bin/intel-pt-events-record
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-#
-# print Intel PT Events including Power Events and PTWRITE. The intel_pt PMU
-# event needs to be specified with appropriate config terms.
-#
-if ! echo "$@" | grep -q intel_pt ; then
- echo "Options must include the Intel PT event e.g. -e intel_pt/pwr_evt,ptw/"
- echo "and for power events it probably needs to be system wide i.e. -a option"
- echo "For example: -a -e intel_pt/pwr_evt,branch=0/ sleep 1"
- exit 1
-fi
-perf record $@
diff --git a/tools/perf/scripts/python/bin/intel-pt-events-report b/tools/perf/scripts/python/bin/intel-pt-events-report
deleted file mode 100644
index beeac3fde9db..000000000000
--- a/tools/perf/scripts/python/bin/intel-pt-events-report
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-# description: print Intel PT Events including Power Events and PTWRITE
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/intel-pt-events.py
diff --git a/tools/perf/scripts/python/bin/mem-phys-addr-record b/tools/perf/scripts/python/bin/mem-phys-addr-record
deleted file mode 100644
index 5a875122a904..000000000000
--- a/tools/perf/scripts/python/bin/mem-phys-addr-record
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-#
-# Profiling physical memory by all retired load instructions/uops event
-# MEM_INST_RETIRED.ALL_LOADS or MEM_UOPS_RETIRED.ALL_LOADS
-#
-
-load=`perf list | grep mem_inst_retired.all_loads`
-if [ -z "$load" ]; then
- load=`perf list | grep mem_uops_retired.all_loads`
-fi
-if [ -z "$load" ]; then
- echo "There is no event to count all retired load instructions/uops."
- exit 1
-fi
-
-arg=$(echo $load | tr -d ' ')
-arg="$arg:P"
-perf record --phys-data -e $arg $@
diff --git a/tools/perf/scripts/python/bin/mem-phys-addr-report b/tools/perf/scripts/python/bin/mem-phys-addr-report
deleted file mode 100644
index 3f2b847e2eab..000000000000
--- a/tools/perf/scripts/python/bin/mem-phys-addr-report
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-# description: resolve physical address samples
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/mem-phys-addr.py
diff --git a/tools/perf/scripts/python/bin/net_dropmonitor-record b/tools/perf/scripts/python/bin/net_dropmonitor-record
deleted file mode 100755
index 423fb81dadae..000000000000
--- a/tools/perf/scripts/python/bin/net_dropmonitor-record
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-perf record -e skb:kfree_skb $@
diff --git a/tools/perf/scripts/python/bin/net_dropmonitor-report b/tools/perf/scripts/python/bin/net_dropmonitor-report
deleted file mode 100755
index 8d698f5a06aa..000000000000
--- a/tools/perf/scripts/python/bin/net_dropmonitor-report
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-# description: display a table of dropped frames
-
-perf script -s "$PERF_EXEC_PATH"/scripts/python/net_dropmonitor.py $@
diff --git a/tools/perf/scripts/python/bin/netdev-times-record b/tools/perf/scripts/python/bin/netdev-times-record
deleted file mode 100644
index 558754b840a9..000000000000
--- a/tools/perf/scripts/python/bin/netdev-times-record
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-perf record -e net:net_dev_xmit -e net:net_dev_queue \
- -e net:netif_receive_skb -e net:netif_rx \
- -e skb:consume_skb -e skb:kfree_skb \
- -e skb:skb_copy_datagram_iovec -e napi:napi_poll \
- -e irq:irq_handler_entry -e irq:irq_handler_exit \
- -e irq:softirq_entry -e irq:softirq_exit \
- -e irq:softirq_raise $@
diff --git a/tools/perf/scripts/python/bin/netdev-times-report b/tools/perf/scripts/python/bin/netdev-times-report
deleted file mode 100644
index 8f759291da86..000000000000
--- a/tools/perf/scripts/python/bin/netdev-times-report
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-# description: display a process of packet and processing time
-# args: [tx] [rx] [dev=] [debug]
-
-perf script -s "$PERF_EXEC_PATH"/scripts/python/netdev-times.py $@
diff --git a/tools/perf/scripts/python/bin/powerpc-hcalls-record b/tools/perf/scripts/python/bin/powerpc-hcalls-record
deleted file mode 100644
index b7402aa9147d..000000000000
--- a/tools/perf/scripts/python/bin/powerpc-hcalls-record
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-perf record -e "{powerpc:hcall_entry,powerpc:hcall_exit}" $@
diff --git a/tools/perf/scripts/python/bin/powerpc-hcalls-report b/tools/perf/scripts/python/bin/powerpc-hcalls-report
deleted file mode 100644
index dd32ad7465f6..000000000000
--- a/tools/perf/scripts/python/bin/powerpc-hcalls-report
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/powerpc-hcalls.py
diff --git a/tools/perf/scripts/python/bin/sched-migration-record b/tools/perf/scripts/python/bin/sched-migration-record
deleted file mode 100644
index 7493fddbe995..000000000000
--- a/tools/perf/scripts/python/bin/sched-migration-record
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-perf record -m 16384 -e sched:sched_wakeup -e sched:sched_wakeup_new -e sched:sched_switch -e sched:sched_migrate_task $@
diff --git a/tools/perf/scripts/python/bin/sched-migration-report b/tools/perf/scripts/python/bin/sched-migration-report
deleted file mode 100644
index 68b037a1849b..000000000000
--- a/tools/perf/scripts/python/bin/sched-migration-report
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-# description: sched migration overview
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/sched-migration.py
diff --git a/tools/perf/scripts/python/bin/sctop-record b/tools/perf/scripts/python/bin/sctop-record
deleted file mode 100644
index d6940841e54f..000000000000
--- a/tools/perf/scripts/python/bin/sctop-record
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-(perf record -e raw_syscalls:sys_enter $@ || \
- perf record -e syscalls:sys_enter $@) 2> /dev/null
diff --git a/tools/perf/scripts/python/bin/sctop-report b/tools/perf/scripts/python/bin/sctop-report
deleted file mode 100644
index c32db294124d..000000000000
--- a/tools/perf/scripts/python/bin/sctop-report
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-# description: syscall top
-# args: [comm] [interval]
-n_args=0
-for i in "$@"
-do
- if expr match "$i" "-" > /dev/null ; then
- break
- fi
- n_args=$(( $n_args + 1 ))
-done
-if [ "$n_args" -gt 2 ] ; then
- echo "usage: sctop-report [comm] [interval]"
- exit
-fi
-if [ "$n_args" -gt 1 ] ; then
- comm=$1
- interval=$2
- shift 2
-elif [ "$n_args" -gt 0 ] ; then
- interval=$1
- shift
-fi
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/sctop.py $comm $interval
diff --git a/tools/perf/scripts/python/bin/stackcollapse-record b/tools/perf/scripts/python/bin/stackcollapse-record
deleted file mode 100755
index 9d8f9f0f3a17..000000000000
--- a/tools/perf/scripts/python/bin/stackcollapse-record
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-#
-# stackcollapse.py can cover all type of perf samples including
-# the tracepoints, so no special record requirements, just record what
-# you want to analyze.
-#
-perf record "$@"
diff --git a/tools/perf/scripts/python/bin/stackcollapse-report b/tools/perf/scripts/python/bin/stackcollapse-report
deleted file mode 100755
index 21a356bd27f6..000000000000
--- a/tools/perf/scripts/python/bin/stackcollapse-report
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# description: produce callgraphs in short form for scripting use
-perf script -s "$PERF_EXEC_PATH"/scripts/python/stackcollapse.py "$@"
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
deleted file mode 100644
index d6940841e54f..000000000000
--- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-(perf record -e raw_syscalls:sys_enter $@ || \
- perf record -e syscalls:sys_enter $@) 2> /dev/null
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
deleted file mode 100644
index 16eb8d65c543..000000000000
--- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-# description: system-wide syscall counts, by pid
-# args: [comm]
-if [ $# -gt 0 ] ; then
- if ! expr match "$1" "-" > /dev/null ; then
- comm=$1
- shift
- fi
-fi
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/syscall-counts-record b/tools/perf/scripts/python/bin/syscall-counts-record
deleted file mode 100644
index d6940841e54f..000000000000
--- a/tools/perf/scripts/python/bin/syscall-counts-record
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-(perf record -e raw_syscalls:sys_enter $@ || \
- perf record -e syscalls:sys_enter $@) 2> /dev/null
diff --git a/tools/perf/scripts/python/bin/syscall-counts-report b/tools/perf/scripts/python/bin/syscall-counts-report
deleted file mode 100644
index 0f0e9d453bb4..000000000000
--- a/tools/perf/scripts/python/bin/syscall-counts-report
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-# description: system-wide syscall counts
-# args: [comm]
-if [ $# -gt 0 ] ; then
- if ! expr match "$1" "-" > /dev/null ; then
- comm=$1
- shift
- fi
-fi
-perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts.py $comm
diff --git a/tools/perf/scripts/python/bin/task-analyzer-record b/tools/perf/scripts/python/bin/task-analyzer-record
deleted file mode 100755
index 0f6b51bb2767..000000000000
--- a/tools/perf/scripts/python/bin/task-analyzer-record
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-perf record -e sched:sched_switch -e sched:sched_migrate_task "$@"
diff --git a/tools/perf/scripts/python/bin/task-analyzer-report b/tools/perf/scripts/python/bin/task-analyzer-report
deleted file mode 100755
index 4b16a8cc40a0..000000000000
--- a/tools/perf/scripts/python/bin/task-analyzer-report
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-# description: analyze timings of tasks
-perf script -s "$PERF_EXEC_PATH"/scripts/python/task-analyzer.py -- "$@"
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
deleted file mode 100644
index d2c22954800d..000000000000
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# perf script event handlers, generated by perf script -g python
-# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
-# Licensed under the terms of the GNU GPL License version 2
-#
-# This script tests basic functionality such as flag and symbol
-# strings, common_xxx() calls back into perf, begin, end, unhandled
-# events, etc. Basically, if this script runs successfully and
-# displays expected results, Python scripting support should be ok.
-
-from __future__ import print_function
-
-import os
-import sys
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from Core import *
-from perf_trace_context import *
-
-unhandled = autodict()
-
-def trace_begin():
- print("trace_begin")
- pass
-
-def trace_end():
- print_unhandled()
-
-def irq__softirq_entry(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, vec):
- print_header(event_name, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
-
- print_uncommon(context)
-
- print("vec=%s" % (symbol_str("irq__softirq_entry", "vec", vec)))
-
-def kmem__kmalloc(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, call_site, ptr, bytes_req, bytes_alloc,
- gfp_flags):
- print_header(event_name, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
-
- print_uncommon(context)
-
- print("call_site=%u, ptr=%u, bytes_req=%u, "
- "bytes_alloc=%u, gfp_flags=%s" %
- (call_site, ptr, bytes_req, bytes_alloc,
- flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)))
-
-def trace_unhandled(event_name, context, event_fields_dict):
- try:
- unhandled[event_name] += 1
- except TypeError:
- unhandled[event_name] = 1
-
-def print_header(event_name, cpu, secs, nsecs, pid, comm):
- print("%-20s %5u %05u.%09u %8u %-20s " %
- (event_name, cpu, secs, nsecs, pid, comm),
- end=' ')
-
-# print trace fields not included in handler args
-def print_uncommon(context):
- print("common_preempt_count=%d, common_flags=%s, "
- "common_lock_depth=%d, " %
- (common_pc(context), trace_flag_str(common_flags(context)),
- common_lock_depth(context)))
-
-def print_unhandled():
- keys = unhandled.keys()
- if not keys:
- return
-
- print("\nunhandled events:\n")
-
- print("%-40s %10s" % ("event", "count"))
- print("%-40s %10s" % ("----------------------------------------",
- "-----------"))
-
- for event_name in keys:
- print("%-40s %10d\n" % (event_name, unhandled[event_name]))
diff --git a/tools/perf/scripts/python/compaction-times.py b/tools/perf/scripts/python/compaction-times.py
deleted file mode 100644
index 9401f7c14747..000000000000
--- a/tools/perf/scripts/python/compaction-times.py
+++ /dev/null
@@ -1,311 +0,0 @@
-# report time spent in compaction
-# Licensed under the terms of the GNU GPL License version 2
-
-# testing:
-# 'echo 1 > /proc/sys/vm/compact_memory' to force compaction of all zones
-
-import os
-import sys
-import re
-
-import signal
-signal.signal(signal.SIGPIPE, signal.SIG_DFL)
-
-usage = "usage: perf script report compaction-times.py -- [-h] [-u] [-p|-pv] [-t | [-m] [-fs] [-ms]] [pid|pid-range|comm-regex]\n"
-
-class popt:
- DISP_DFL = 0
- DISP_PROC = 1
- DISP_PROC_VERBOSE=2
-
-class topt:
- DISP_TIME = 0
- DISP_MIG = 1
- DISP_ISOLFREE = 2
- DISP_ISOLMIG = 4
- DISP_ALL = 7
-
-class comm_filter:
- def __init__(self, re):
- self.re = re
-
- def filter(self, pid, comm):
- m = self.re.search(comm)
- return m == None or m.group() == ""
-
-class pid_filter:
- def __init__(self, low, high):
- self.low = (0 if low == "" else int(low))
- self.high = (0 if high == "" else int(high))
-
- def filter(self, pid, comm):
- return not (pid >= self.low and (self.high == 0 or pid <= self.high))
-
-def set_type(t):
- global opt_disp
- opt_disp = (t if opt_disp == topt.DISP_ALL else opt_disp|t)
-
-def ns(sec, nsec):
- return (sec * 1000000000) + nsec
-
-def time(ns):
- return "%dns" % ns if opt_ns else "%dus" % (round(ns, -3) / 1000)
-
-class pair:
- def __init__(self, aval, bval, alabel = None, blabel = None):
- self.alabel = alabel
- self.blabel = blabel
- self.aval = aval
- self.bval = bval
-
- def __add__(self, rhs):
- self.aval += rhs.aval
- self.bval += rhs.bval
- return self
-
- def __str__(self):
- return "%s=%d %s=%d" % (self.alabel, self.aval, self.blabel, self.bval)
-
-class cnode:
- def __init__(self, ns):
- self.ns = ns
- self.migrated = pair(0, 0, "moved", "failed")
- self.fscan = pair(0,0, "scanned", "isolated")
- self.mscan = pair(0,0, "scanned", "isolated")
-
- def __add__(self, rhs):
- self.ns += rhs.ns
- self.migrated += rhs.migrated
- self.fscan += rhs.fscan
- self.mscan += rhs.mscan
- return self
-
- def __str__(self):
- prev = 0
- s = "%s " % time(self.ns)
- if (opt_disp & topt.DISP_MIG):
- s += "migration: %s" % self.migrated
- prev = 1
- if (opt_disp & topt.DISP_ISOLFREE):
- s += "%sfree_scanner: %s" % (" " if prev else "", self.fscan)
- prev = 1
- if (opt_disp & topt.DISP_ISOLMIG):
- s += "%smigration_scanner: %s" % (" " if prev else "", self.mscan)
- return s
-
- def complete(self, secs, nsecs):
- self.ns = ns(secs, nsecs) - self.ns
-
- def increment(self, migrated, fscan, mscan):
- if (migrated != None):
- self.migrated += migrated
- if (fscan != None):
- self.fscan += fscan
- if (mscan != None):
- self.mscan += mscan
-
-
-class chead:
- heads = {}
- val = cnode(0);
- fobj = None
-
- @classmethod
- def add_filter(cls, filter):
- cls.fobj = filter
-
- @classmethod
- def create_pending(cls, pid, comm, start_secs, start_nsecs):
- filtered = 0
- try:
- head = cls.heads[pid]
- filtered = head.is_filtered()
- except KeyError:
- if cls.fobj != None:
- filtered = cls.fobj.filter(pid, comm)
- head = cls.heads[pid] = chead(comm, pid, filtered)
-
- if not filtered:
- head.mark_pending(start_secs, start_nsecs)
-
- @classmethod
- def increment_pending(cls, pid, migrated, fscan, mscan):
- head = cls.heads[pid]
- if not head.is_filtered():
- if head.is_pending():
- head.do_increment(migrated, fscan, mscan)
- else:
- sys.stderr.write("missing start compaction event for pid %d\n" % pid)
-
- @classmethod
- def complete_pending(cls, pid, secs, nsecs):
- head = cls.heads[pid]
- if not head.is_filtered():
- if head.is_pending():
- head.make_complete(secs, nsecs)
- else:
- sys.stderr.write("missing start compaction event for pid %d\n" % pid)
-
- @classmethod
- def gen(cls):
- if opt_proc != popt.DISP_DFL:
- for i in cls.heads:
- yield cls.heads[i]
-
- @classmethod
- def str(cls):
- return cls.val
-
- def __init__(self, comm, pid, filtered):
- self.comm = comm
- self.pid = pid
- self.val = cnode(0)
- self.pending = None
- self.filtered = filtered
- self.list = []
-
- def __add__(self, rhs):
- self.ns += rhs.ns
- self.val += rhs.val
- return self
-
- def mark_pending(self, secs, nsecs):
- self.pending = cnode(ns(secs, nsecs))
-
- def do_increment(self, migrated, fscan, mscan):
- self.pending.increment(migrated, fscan, mscan)
-
- def make_complete(self, secs, nsecs):
- self.pending.complete(secs, nsecs)
- chead.val += self.pending
-
- if opt_proc != popt.DISP_DFL:
- self.val += self.pending
-
- if opt_proc == popt.DISP_PROC_VERBOSE:
- self.list.append(self.pending)
- self.pending = None
-
- def enumerate(self):
- if opt_proc == popt.DISP_PROC_VERBOSE and not self.is_filtered():
- for i, pelem in enumerate(self.list):
- sys.stdout.write("%d[%s].%d: %s\n" % (self.pid, self.comm, i+1, pelem))
-
- def is_pending(self):
- return self.pending != None
-
- def is_filtered(self):
- return self.filtered
-
- def display(self):
- if not self.is_filtered():
- sys.stdout.write("%d[%s]: %s\n" % (self.pid, self.comm, self.val))
-
-
-def trace_end():
- sys.stdout.write("total: %s\n" % chead.str())
- for i in chead.gen():
- i.display(),
- i.enumerate()
-
-def compaction__mm_compaction_migratepages(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, nr_migrated, nr_failed):
-
- chead.increment_pending(common_pid,
- pair(nr_migrated, nr_failed), None, None)
-
-def compaction__mm_compaction_isolate_freepages(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken):
-
- chead.increment_pending(common_pid,
- None, pair(nr_scanned, nr_taken), None)
-
-def compaction__mm_compaction_isolate_migratepages(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, start_pfn, end_pfn, nr_scanned, nr_taken):
-
- chead.increment_pending(common_pid,
- None, None, pair(nr_scanned, nr_taken))
-
-def compaction__mm_compaction_end(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, zone_start, migrate_start, free_start, zone_end,
- sync, status):
-
- chead.complete_pending(common_pid, common_secs, common_nsecs)
-
-def compaction__mm_compaction_begin(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, zone_start, migrate_start, free_start, zone_end,
- sync):
-
- chead.create_pending(common_pid, common_comm, common_secs, common_nsecs)
-
-def pr_help():
- global usage
-
- sys.stdout.write(usage)
- sys.stdout.write("\n")
- sys.stdout.write("-h display this help\n")
- sys.stdout.write("-p display by process\n")
- sys.stdout.write("-pv display by process (verbose)\n")
- sys.stdout.write("-t display stall times only\n")
- sys.stdout.write("-m display stats for migration\n")
- sys.stdout.write("-fs display stats for free scanner\n")
- sys.stdout.write("-ms display stats for migration scanner\n")
- sys.stdout.write("-u display results in microseconds (default nanoseconds)\n")
-
-
-comm_re = None
-pid_re = None
-pid_regex = r"^(\d*)-(\d*)$|^(\d*)$"
-
-opt_proc = popt.DISP_DFL
-opt_disp = topt.DISP_ALL
-
-opt_ns = True
-
-argc = len(sys.argv) - 1
-if argc >= 1:
- pid_re = re.compile(pid_regex)
-
- for i, opt in enumerate(sys.argv[1:]):
- if opt[0] == "-":
- if opt == "-h":
- pr_help()
- exit(0);
- elif opt == "-p":
- opt_proc = popt.DISP_PROC
- elif opt == "-pv":
- opt_proc = popt.DISP_PROC_VERBOSE
- elif opt == '-u':
- opt_ns = False
- elif opt == "-t":
- set_type(topt.DISP_TIME)
- elif opt == "-m":
- set_type(topt.DISP_MIG)
- elif opt == "-fs":
- set_type(topt.DISP_ISOLFREE)
- elif opt == "-ms":
- set_type(topt.DISP_ISOLMIG)
- else:
- sys.exit(usage)
-
- elif i == argc - 1:
- m = pid_re.search(opt)
- if m != None and m.group() != "":
- if m.group(3) != None:
- f = pid_filter(m.group(3), m.group(3))
- else:
- f = pid_filter(m.group(1), m.group(2))
- else:
- try:
- comm_re=re.compile(opt)
- except:
- sys.stderr.write("invalid regex '%s'" % opt)
- sys.exit(usage)
- f = comm_filter(comm_re)
-
- chead.add_filter(f)
diff --git a/tools/perf/scripts/python/event_analyzing_sample.py b/tools/perf/scripts/python/event_analyzing_sample.py
deleted file mode 100644
index aa1e2cfa26a6..000000000000
--- a/tools/perf/scripts/python/event_analyzing_sample.py
+++ /dev/null
@@ -1,192 +0,0 @@
-# event_analyzing_sample.py: general event handler in python
-# SPDX-License-Identifier: GPL-2.0
-#
-# Current perf report is already very powerful with the annotation integrated,
-# and this script is not trying to be as powerful as perf report, but
-# providing end user/developer a flexible way to analyze the events other
-# than trace points.
-#
-# The 2 database related functions in this script just show how to gather
-# the basic information, and users can modify and write their own functions
-# according to their specific requirement.
-#
-# The first function "show_general_events" just does a basic grouping for all
-# generic events with the help of sqlite, and the 2nd one "show_pebs_ll" is
-# for a x86 HW PMU event: PEBS with load latency data.
-#
-
-from __future__ import print_function
-
-import os
-import sys
-import math
-import struct
-import sqlite3
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from EventClass import *
-
-#
-# If the perf.data has a big number of samples, then the insert operation
-# will be very time consuming (about 10+ minutes for 10000 samples) if the
-# .db database is on disk. Move the .db file to RAM based FS to speedup
-# the handling, which will cut the time down to several seconds.
-#
-con = sqlite3.connect("/dev/shm/perf.db")
-con.isolation_level = None
-
-def trace_begin():
- print("In trace_begin:\n")
-
- #
- # Will create several tables at the start, pebs_ll is for PEBS data with
- # load latency info, while gen_events is for general event.
- #
- con.execute("""
- create table if not exists gen_events (
- name text,
- symbol text,
- comm text,
- dso text
- );""")
- con.execute("""
- create table if not exists pebs_ll (
- name text,
- symbol text,
- comm text,
- dso text,
- flags integer,
- ip integer,
- status integer,
- dse integer,
- dla integer,
- lat integer
- );""")
-
-#
-# Create and insert event object to a database so that user could
-# do more analysis with simple database commands.
-#
-def process_event(param_dict):
- event_attr = param_dict["attr"]
- sample = param_dict["sample"]
- raw_buf = param_dict["raw_buf"]
- comm = param_dict["comm"]
- name = param_dict["ev_name"]
-
- # Symbol and dso info are not always resolved
- if ("dso" in param_dict):
- dso = param_dict["dso"]
- else:
- dso = "Unknown_dso"
-
- if ("symbol" in param_dict):
- symbol = param_dict["symbol"]
- else:
- symbol = "Unknown_symbol"
-
- # Create the event object and insert it to the right table in database
- event = create_event(name, comm, dso, symbol, raw_buf)
- insert_db(event)
-
-def insert_db(event):
- if event.ev_type == EVTYPE_GENERIC:
- con.execute("insert into gen_events values(?, ?, ?, ?)",
- (event.name, event.symbol, event.comm, event.dso))
- elif event.ev_type == EVTYPE_PEBS_LL:
- event.ip &= 0x7fffffffffffffff
- event.dla &= 0x7fffffffffffffff
- con.execute("insert into pebs_ll values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- (event.name, event.symbol, event.comm, event.dso, event.flags,
- event.ip, event.status, event.dse, event.dla, event.lat))
-
-def trace_end():
- print("In trace_end:\n")
- # We show the basic info for the 2 type of event classes
- show_general_events()
- show_pebs_ll()
- con.close()
-
-#
-# As the event number may be very big, so we can't use linear way
-# to show the histogram in real number, but use a log2 algorithm.
-#
-
-def num2sym(num):
- # Each number will have at least one '#'
- snum = '#' * (int)(math.log(num, 2) + 1)
- return snum
-
-def show_general_events():
-
- # Check the total record number in the table
- count = con.execute("select count(*) from gen_events")
- for t in count:
- print("There is %d records in gen_events table" % t[0])
- if t[0] == 0:
- return
-
- print("Statistics about the general events grouped by thread/symbol/dso: \n")
-
- # Group by thread
- commq = con.execute("select comm, count(comm) from gen_events group by comm order by -count(comm)")
- print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42))
- for row in commq:
- print("%16s %8d %s" % (row[0], row[1], num2sym(row[1])))
-
- # Group by symbol
- print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58))
- symbolq = con.execute("select symbol, count(symbol) from gen_events group by symbol order by -count(symbol)")
- for row in symbolq:
- print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
-
- # Group by dso
- print("\n%40s %8s %16s\n%s" % ("dso", "number", "histogram", "="*74))
- dsoq = con.execute("select dso, count(dso) from gen_events group by dso order by -count(dso)")
- for row in dsoq:
- print("%40s %8d %s" % (row[0], row[1], num2sym(row[1])))
-
-#
-# This function just shows the basic info, and we could do more with the
-# data in the tables, like checking the function parameters when some
-# big latency events happen.
-#
-def show_pebs_ll():
-
- count = con.execute("select count(*) from pebs_ll")
- for t in count:
- print("There is %d records in pebs_ll table" % t[0])
- if t[0] == 0:
- return
-
- print("Statistics about the PEBS Load Latency events grouped by thread/symbol/dse/latency: \n")
-
- # Group by thread
- commq = con.execute("select comm, count(comm) from pebs_ll group by comm order by -count(comm)")
- print("\n%16s %8s %16s\n%s" % ("comm", "number", "histogram", "="*42))
- for row in commq:
- print("%16s %8d %s" % (row[0], row[1], num2sym(row[1])))
-
- # Group by symbol
- print("\n%32s %8s %16s\n%s" % ("symbol", "number", "histogram", "="*58))
- symbolq = con.execute("select symbol, count(symbol) from pebs_ll group by symbol order by -count(symbol)")
- for row in symbolq:
- print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
-
- # Group by dse
- dseq = con.execute("select dse, count(dse) from pebs_ll group by dse order by -count(dse)")
- print("\n%32s %8s %16s\n%s" % ("dse", "number", "histogram", "="*58))
- for row in dseq:
- print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
-
- # Group by latency
- latq = con.execute("select lat, count(lat) from pebs_ll group by lat order by lat")
- print("\n%32s %8s %16s\n%s" % ("latency", "number", "histogram", "="*58))
- for row in latq:
- print("%32s %8d %s" % (row[0], row[1], num2sym(row[1])))
-
-def trace_unhandled(event_name, context, event_fields_dict):
- print (' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]))
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
deleted file mode 100644
index 3a6bdcd74e60..000000000000
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ /dev/null
@@ -1,1114 +0,0 @@
-# export-to-postgresql.py: export perf data to a postgresql database
-# Copyright (c) 2014, Intel Corporation.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-
-from __future__ import print_function
-
-import os
-import sys
-import struct
-import datetime
-
-# To use this script you will need to have installed package python-pyside which
-# provides LGPL-licensed Python bindings for Qt. You will also need the package
-# libqt4-sql-psql for Qt postgresql support.
-#
-# The script assumes postgresql is running on the local machine and that the
-# user has postgresql permissions to create databases. Examples of installing
-# postgresql and adding such a user are:
-#
-# fedora:
-#
-# $ sudo yum install postgresql postgresql-server qt-postgresql
-# $ sudo su - postgres -c initdb
-# $ sudo service postgresql start
-# $ sudo su - postgres
-# $ createuser -s <your user id here> # Older versions may not support -s, in which case answer the prompt below:
-# Shall the new role be a superuser? (y/n) y
-# $ sudo yum install python-pyside
-#
-# Alternately, to use Python3 and/or pyside 2, one of the following:
-# $ sudo yum install python3-pyside
-# $ pip install --user PySide2
-# $ pip3 install --user PySide2
-#
-# ubuntu:
-#
-# $ sudo apt-get install postgresql
-# $ sudo su - postgres
-# $ createuser -s <your user id here>
-# $ sudo apt-get install python-pyside.qtsql libqt4-sql-psql
-#
-# Alternately, to use Python3 and/or pyside 2, one of the following:
-#
-# $ sudo apt-get install python3-pyside.qtsql libqt4-sql-psql
-# $ sudo apt-get install python-pyside2.qtsql libqt5sql5-psql
-# $ sudo apt-get install python3-pyside2.qtsql libqt5sql5-psql
-#
-# An example of using this script with Intel PT:
-#
-# $ perf record -e intel_pt//u ls
-# $ perf script -s ~/libexec/perf-core/scripts/python/export-to-postgresql.py pt_example branches calls
-# 2015-05-29 12:49:23.464364 Creating database...
-# 2015-05-29 12:49:26.281717 Writing to intermediate files...
-# 2015-05-29 12:49:27.190383 Copying to database...
-# 2015-05-29 12:49:28.140451 Removing intermediate files...
-# 2015-05-29 12:49:28.147451 Adding primary keys
-# 2015-05-29 12:49:28.655683 Adding foreign keys
-# 2015-05-29 12:49:29.365350 Done
-#
-# To browse the database, psql can be used e.g.
-#
-# $ psql pt_example
-# pt_example=# select * from samples_view where id < 100;
-# pt_example=# \d+
-# pt_example=# \d+ samples_view
-# pt_example=# \q
-#
-# An example of using the database is provided by the script
-# exported-sql-viewer.py. Refer to that script for details.
-#
-# Tables:
-#
-# The tables largely correspond to perf tools' data structures. They are largely self-explanatory.
-#
-# samples
-#
-# 'samples' is the main table. It represents what instruction was executing at a point in time
-# when something (a selected event) happened. The memory address is the instruction pointer or 'ip'.
-#
-# calls
-#
-# 'calls' represents function calls and is related to 'samples' by 'call_id' and 'return_id'.
-# 'calls' is only created when the 'calls' option to this script is specified.
-#
-# call_paths
-#
-# 'call_paths' represents all the call stacks. Each 'call' has an associated record in 'call_paths'.
-# 'calls_paths' is only created when the 'calls' option to this script is specified.
-#
-# branch_types
-#
-# 'branch_types' provides descriptions for each type of branch.
-#
-# comm_threads
-#
-# 'comm_threads' shows how 'comms' relates to 'threads'.
-#
-# comms
-#
-# 'comms' contains a record for each 'comm' - the name given to the executable that is running.
-#
-# dsos
-#
-# 'dsos' contains a record for each executable file or library.
-#
-# machines
-#
-# 'machines' can be used to distinguish virtual machines if virtualization is supported.
-#
-# selected_events
-#
-# 'selected_events' contains a record for each kind of event that has been sampled.
-#
-# symbols
-#
-# 'symbols' contains a record for each symbol. Only symbols that have samples are present.
-#
-# threads
-#
-# 'threads' contains a record for each thread.
-#
-# Views:
-#
-# Most of the tables have views for more friendly display. The views are:
-#
-# calls_view
-# call_paths_view
-# comm_threads_view
-# dsos_view
-# machines_view
-# samples_view
-# symbols_view
-# threads_view
-#
-# More examples of browsing the database with psql:
-# Note that some of the examples are not the most optimal SQL query.
-# Note that call information is only available if the script's 'calls' option has been used.
-#
-# Top 10 function calls (not aggregated by symbol):
-#
-# SELECT * FROM calls_view ORDER BY elapsed_time DESC LIMIT 10;
-#
-# Top 10 function calls (aggregated by symbol):
-#
-# SELECT symbol_id,(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,
-# SUM(elapsed_time) AS tot_elapsed_time,SUM(branch_count) AS tot_branch_count
-# FROM calls_view GROUP BY symbol_id ORDER BY tot_elapsed_time DESC LIMIT 10;
-#
-# Note that the branch count gives a rough estimation of cpu usage, so functions
-# that took a long time but have a relatively low branch count must have spent time
-# waiting.
-#
-# Find symbols by pattern matching on part of the name (e.g. names containing 'alloc'):
-#
-# SELECT * FROM symbols_view WHERE name LIKE '%alloc%';
-#
-# Top 10 function calls for a specific symbol (e.g. whose symbol_id is 187):
-#
-# SELECT * FROM calls_view WHERE symbol_id = 187 ORDER BY elapsed_time DESC LIMIT 10;
-#
-# Show function calls made by function in the same context (i.e. same call path) (e.g. one with call_path_id 254):
-#
-# SELECT * FROM calls_view WHERE parent_call_path_id = 254;
-#
-# Show branches made during a function call (e.g. where call_id is 29357 and return_id is 29370 and tid is 29670)
-#
-# SELECT * FROM samples_view WHERE id >= 29357 AND id <= 29370 AND tid = 29670 AND event LIKE 'branches%';
-#
-# Show transactions:
-#
-# SELECT * FROM samples_view WHERE event = 'transactions';
-#
-# Note transaction start has 'in_tx' true whereas, transaction end has 'in_tx' false.
-# Transaction aborts have branch_type_name 'transaction abort'
-#
-# Show transaction aborts:
-#
-# SELECT * FROM samples_view WHERE event = 'transactions' AND branch_type_name = 'transaction abort';
-#
-# To print a call stack requires walking the call_paths table. For example this python script:
-# #!/usr/bin/python2
-#
-# import sys
-# from PySide.QtSql import *
-#
-# if __name__ == '__main__':
-# if (len(sys.argv) < 3):
-# print >> sys.stderr, "Usage is: printcallstack.py <database name> <call_path_id>"
-# raise Exception("Too few arguments")
-# dbname = sys.argv[1]
-# call_path_id = sys.argv[2]
-# db = QSqlDatabase.addDatabase('QPSQL')
-# db.setDatabaseName(dbname)
-# if not db.open():
-# raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text())
-# query = QSqlQuery(db)
-# print " id ip symbol_id symbol dso_id dso_short_name"
-# while call_path_id != 0 and call_path_id != 1:
-# ret = query.exec_('SELECT * FROM call_paths_view WHERE id = ' + str(call_path_id))
-# if not ret:
-# raise Exception("Query failed: " + query.lastError().text())
-# if not query.next():
-# raise Exception("Query failed")
-# print "{0:>6} {1:>10} {2:>9} {3:<30} {4:>6} {5:<30}".format(query.value(0), query.value(1), query.value(2), query.value(3), query.value(4), query.value(5))
-# call_path_id = query.value(6)
-
-pyside_version_1 = True
-if not "pyside-version-1" in sys.argv:
- try:
- from PySide2.QtSql import *
- pyside_version_1 = False
- except:
- pass
-
-if pyside_version_1:
- from PySide.QtSql import *
-
-if sys.version_info < (3, 0):
- def toserverstr(str):
- return str
- def toclientstr(str):
- return str
-else:
- # Assume UTF-8 server_encoding and client_encoding
- def toserverstr(str):
- return bytes(str, "UTF_8")
- def toclientstr(str):
- return bytes(str, "UTF_8")
-
-# Need to access PostgreSQL C library directly to use COPY FROM STDIN
-from ctypes import *
-libpq = CDLL("libpq.so.5")
-PQconnectdb = libpq.PQconnectdb
-PQconnectdb.restype = c_void_p
-PQconnectdb.argtypes = [ c_char_p ]
-PQfinish = libpq.PQfinish
-PQfinish.argtypes = [ c_void_p ]
-PQstatus = libpq.PQstatus
-PQstatus.restype = c_int
-PQstatus.argtypes = [ c_void_p ]
-PQexec = libpq.PQexec
-PQexec.restype = c_void_p
-PQexec.argtypes = [ c_void_p, c_char_p ]
-PQresultStatus = libpq.PQresultStatus
-PQresultStatus.restype = c_int
-PQresultStatus.argtypes = [ c_void_p ]
-PQputCopyData = libpq.PQputCopyData
-PQputCopyData.restype = c_int
-PQputCopyData.argtypes = [ c_void_p, c_void_p, c_int ]
-PQputCopyEnd = libpq.PQputCopyEnd
-PQputCopyEnd.restype = c_int
-PQputCopyEnd.argtypes = [ c_void_p, c_void_p ]
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-# These perf imports are not used at present
-#from perf_trace_context import *
-#from Core import *
-
-perf_db_export_mode = True
-perf_db_export_calls = False
-perf_db_export_callchains = False
-
-def printerr(*args, **kw_args):
- print(*args, file=sys.stderr, **kw_args)
-
-def printdate(*args, **kw_args):
- print(datetime.datetime.today(), *args, sep=' ', **kw_args)
-
-def usage():
- printerr("Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>] [<pyside-version-1>]");
- printerr("where: columns 'all' or 'branches'");
- printerr(" calls 'calls' => create calls and call_paths table");
- printerr(" callchains 'callchains' => create call_paths table");
- printerr(" pyside-version-1 'pyside-version-1' => use pyside version 1");
- raise Exception("Too few or bad arguments")
-
-if (len(sys.argv) < 2):
- usage()
-
-dbname = sys.argv[1]
-
-if (len(sys.argv) >= 3):
- columns = sys.argv[2]
-else:
- columns = "all"
-
-if columns not in ("all", "branches"):
- usage()
-
-branches = (columns == "branches")
-
-for i in range(3,len(sys.argv)):
- if (sys.argv[i] == "calls"):
- perf_db_export_calls = True
- elif (sys.argv[i] == "callchains"):
- perf_db_export_callchains = True
- elif (sys.argv[i] == "pyside-version-1"):
- pass
- else:
- usage()
-
-output_dir_name = os.getcwd() + "/" + dbname + "-perf-data"
-os.mkdir(output_dir_name)
-
-def do_query(q, s):
- if (q.exec_(s)):
- return
- raise Exception("Query failed: " + q.lastError().text())
-
-printdate("Creating database...")
-
-db = QSqlDatabase.addDatabase('QPSQL')
-query = QSqlQuery(db)
-db.setDatabaseName('postgres')
-db.open()
-try:
- do_query(query, 'CREATE DATABASE ' + dbname)
-except:
- os.rmdir(output_dir_name)
- raise
-query.finish()
-query.clear()
-db.close()
-
-db.setDatabaseName(dbname)
-db.open()
-
-query = QSqlQuery(db)
-do_query(query, 'SET client_min_messages TO WARNING')
-
-do_query(query, 'CREATE TABLE selected_events ('
- 'id bigint NOT NULL,'
- 'name varchar(80))')
-do_query(query, 'CREATE TABLE machines ('
- 'id bigint NOT NULL,'
- 'pid integer,'
- 'root_dir varchar(4096))')
-do_query(query, 'CREATE TABLE threads ('
- 'id bigint NOT NULL,'
- 'machine_id bigint,'
- 'process_id bigint,'
- 'pid integer,'
- 'tid integer)')
-do_query(query, 'CREATE TABLE comms ('
- 'id bigint NOT NULL,'
- 'comm varchar(16),'
- 'c_thread_id bigint,'
- 'c_time bigint,'
- 'exec_flag boolean)')
-do_query(query, 'CREATE TABLE comm_threads ('
- 'id bigint NOT NULL,'
- 'comm_id bigint,'
- 'thread_id bigint)')
-do_query(query, 'CREATE TABLE dsos ('
- 'id bigint NOT NULL,'
- 'machine_id bigint,'
- 'short_name varchar(256),'
- 'long_name varchar(4096),'
- 'build_id varchar(64))')
-do_query(query, 'CREATE TABLE symbols ('
- 'id bigint NOT NULL,'
- 'dso_id bigint,'
- 'sym_start bigint,'
- 'sym_end bigint,'
- 'binding integer,'
- 'name varchar(2048))')
-do_query(query, 'CREATE TABLE branch_types ('
- 'id integer NOT NULL,'
- 'name varchar(80))')
-
-if branches:
- do_query(query, 'CREATE TABLE samples ('
- 'id bigint NOT NULL,'
- 'evsel_id bigint,'
- 'machine_id bigint,'
- 'thread_id bigint,'
- 'comm_id bigint,'
- 'dso_id bigint,'
- 'symbol_id bigint,'
- 'sym_offset bigint,'
- 'ip bigint,'
- 'time bigint,'
- 'cpu integer,'
- 'to_dso_id bigint,'
- 'to_symbol_id bigint,'
- 'to_sym_offset bigint,'
- 'to_ip bigint,'
- 'branch_type integer,'
- 'in_tx boolean,'
- 'call_path_id bigint,'
- 'insn_count bigint,'
- 'cyc_count bigint,'
- 'flags integer)')
-else:
- do_query(query, 'CREATE TABLE samples ('
- 'id bigint NOT NULL,'
- 'evsel_id bigint,'
- 'machine_id bigint,'
- 'thread_id bigint,'
- 'comm_id bigint,'
- 'dso_id bigint,'
- 'symbol_id bigint,'
- 'sym_offset bigint,'
- 'ip bigint,'
- 'time bigint,'
- 'cpu integer,'
- 'to_dso_id bigint,'
- 'to_symbol_id bigint,'
- 'to_sym_offset bigint,'
- 'to_ip bigint,'
- 'period bigint,'
- 'weight bigint,'
- 'transaction bigint,'
- 'data_src bigint,'
- 'branch_type integer,'
- 'in_tx boolean,'
- 'call_path_id bigint,'
- 'insn_count bigint,'
- 'cyc_count bigint,'
- 'flags integer)')
-
-if perf_db_export_calls or perf_db_export_callchains:
- do_query(query, 'CREATE TABLE call_paths ('
- 'id bigint NOT NULL,'
- 'parent_id bigint,'
- 'symbol_id bigint,'
- 'ip bigint)')
-if perf_db_export_calls:
- do_query(query, 'CREATE TABLE calls ('
- 'id bigint NOT NULL,'
- 'thread_id bigint,'
- 'comm_id bigint,'
- 'call_path_id bigint,'
- 'call_time bigint,'
- 'return_time bigint,'
- 'branch_count bigint,'
- 'call_id bigint,'
- 'return_id bigint,'
- 'parent_call_path_id bigint,'
- 'flags integer,'
- 'parent_id bigint,'
- 'insn_count bigint,'
- 'cyc_count bigint)')
-
-do_query(query, 'CREATE TABLE ptwrite ('
- 'id bigint NOT NULL,'
- 'payload bigint,'
- 'exact_ip boolean)')
-
-do_query(query, 'CREATE TABLE cbr ('
- 'id bigint NOT NULL,'
- 'cbr integer,'
- 'mhz integer,'
- 'percent integer)')
-
-do_query(query, 'CREATE TABLE mwait ('
- 'id bigint NOT NULL,'
- 'hints integer,'
- 'extensions integer)')
-
-do_query(query, 'CREATE TABLE pwre ('
- 'id bigint NOT NULL,'
- 'cstate integer,'
- 'subcstate integer,'
- 'hw boolean)')
-
-do_query(query, 'CREATE TABLE exstop ('
- 'id bigint NOT NULL,'
- 'exact_ip boolean)')
-
-do_query(query, 'CREATE TABLE pwrx ('
- 'id bigint NOT NULL,'
- 'deepest_cstate integer,'
- 'last_cstate integer,'
- 'wake_reason integer)')
-
-do_query(query, 'CREATE TABLE context_switches ('
- 'id bigint NOT NULL,'
- 'machine_id bigint,'
- 'time bigint,'
- 'cpu integer,'
- 'thread_out_id bigint,'
- 'comm_out_id bigint,'
- 'thread_in_id bigint,'
- 'comm_in_id bigint,'
- 'flags integer)')
-
-do_query(query, 'CREATE VIEW machines_view AS '
- 'SELECT '
- 'id,'
- 'pid,'
- 'root_dir,'
- 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
- ' FROM machines')
-
-do_query(query, 'CREATE VIEW dsos_view AS '
- 'SELECT '
- 'id,'
- 'machine_id,'
- '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
- 'short_name,'
- 'long_name,'
- 'build_id'
- ' FROM dsos')
-
-do_query(query, 'CREATE VIEW symbols_view AS '
- 'SELECT '
- 'id,'
- 'name,'
- '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
- 'dso_id,'
- 'sym_start,'
- 'sym_end,'
- 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
- ' FROM symbols')
-
-do_query(query, 'CREATE VIEW threads_view AS '
- 'SELECT '
- 'id,'
- 'machine_id,'
- '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
- 'process_id,'
- 'pid,'
- 'tid'
- ' FROM threads')
-
-do_query(query, 'CREATE VIEW comm_threads_view AS '
- 'SELECT '
- 'comm_id,'
- '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
- 'thread_id,'
- '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
- '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
- ' FROM comm_threads')
-
-if perf_db_export_calls or perf_db_export_callchains:
- do_query(query, 'CREATE VIEW call_paths_view AS '
- 'SELECT '
- 'c.id,'
- 'to_hex(c.ip) AS ip,'
- 'c.symbol_id,'
- '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
- '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
- '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,'
- 'c.parent_id,'
- 'to_hex(p.ip) AS parent_ip,'
- 'p.symbol_id AS parent_symbol_id,'
- '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
- '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
- '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
- ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
-if perf_db_export_calls:
- do_query(query, 'CREATE VIEW calls_view AS '
- 'SELECT '
- 'calls.id,'
- 'thread_id,'
- '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
- '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
- '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
- 'call_path_id,'
- 'to_hex(ip) AS ip,'
- 'symbol_id,'
- '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
- 'call_time,'
- 'return_time,'
- 'return_time - call_time AS elapsed_time,'
- 'branch_count,'
- 'insn_count,'
- 'cyc_count,'
- 'CASE WHEN cyc_count=0 THEN CAST(0 AS NUMERIC(20, 2)) ELSE CAST((CAST(insn_count AS FLOAT) / cyc_count) AS NUMERIC(20, 2)) END AS IPC,'
- 'call_id,'
- 'return_id,'
- 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE CAST ( flags AS VARCHAR(6) ) END AS flags,'
- 'parent_call_path_id,'
- 'calls.parent_id'
- ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
-
-do_query(query, 'CREATE VIEW samples_view AS '
- 'SELECT '
- 'id,'
- 'time,'
- 'cpu,'
- '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
- '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
- '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
- '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,'
- 'to_hex(ip) AS ip_hex,'
- '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
- 'sym_offset,'
- '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,'
- 'to_hex(to_ip) AS to_ip_hex,'
- '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,'
- 'to_sym_offset,'
- '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'
- '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,'
- 'in_tx,'
- 'insn_count,'
- 'cyc_count,'
- 'CASE WHEN cyc_count=0 THEN CAST(0 AS NUMERIC(20, 2)) ELSE CAST((CAST(insn_count AS FLOAT) / cyc_count) AS NUMERIC(20, 2)) END AS IPC,'
- 'flags'
- ' FROM samples')
-
-do_query(query, 'CREATE VIEW ptwrite_view AS '
- 'SELECT '
- 'ptwrite.id,'
- 'time,'
- 'cpu,'
- 'to_hex(payload) AS payload_hex,'
- 'CASE WHEN exact_ip=FALSE THEN \'False\' ELSE \'True\' END AS exact_ip'
- ' FROM ptwrite'
- ' INNER JOIN samples ON samples.id = ptwrite.id')
-
-do_query(query, 'CREATE VIEW cbr_view AS '
- 'SELECT '
- 'cbr.id,'
- 'time,'
- 'cpu,'
- 'cbr,'
- 'mhz,'
- 'percent'
- ' FROM cbr'
- ' INNER JOIN samples ON samples.id = cbr.id')
-
-do_query(query, 'CREATE VIEW mwait_view AS '
- 'SELECT '
- 'mwait.id,'
- 'time,'
- 'cpu,'
- 'to_hex(hints) AS hints_hex,'
- 'to_hex(extensions) AS extensions_hex'
- ' FROM mwait'
- ' INNER JOIN samples ON samples.id = mwait.id')
-
-do_query(query, 'CREATE VIEW pwre_view AS '
- 'SELECT '
- 'pwre.id,'
- 'time,'
- 'cpu,'
- 'cstate,'
- 'subcstate,'
- 'CASE WHEN hw=FALSE THEN \'False\' ELSE \'True\' END AS hw'
- ' FROM pwre'
- ' INNER JOIN samples ON samples.id = pwre.id')
-
-do_query(query, 'CREATE VIEW exstop_view AS '
- 'SELECT '
- 'exstop.id,'
- 'time,'
- 'cpu,'
- 'CASE WHEN exact_ip=FALSE THEN \'False\' ELSE \'True\' END AS exact_ip'
- ' FROM exstop'
- ' INNER JOIN samples ON samples.id = exstop.id')
-
-do_query(query, 'CREATE VIEW pwrx_view AS '
- 'SELECT '
- 'pwrx.id,'
- 'time,'
- 'cpu,'
- 'deepest_cstate,'
- 'last_cstate,'
- 'CASE WHEN wake_reason=1 THEN \'Interrupt\''
- ' WHEN wake_reason=2 THEN \'Timer Deadline\''
- ' WHEN wake_reason=4 THEN \'Monitored Address\''
- ' WHEN wake_reason=8 THEN \'HW\''
- ' ELSE CAST ( wake_reason AS VARCHAR(2) )'
- 'END AS wake_reason'
- ' FROM pwrx'
- ' INNER JOIN samples ON samples.id = pwrx.id')
-
-do_query(query, 'CREATE VIEW power_events_view AS '
- 'SELECT '
- 'samples.id,'
- 'samples.time,'
- 'samples.cpu,'
- 'selected_events.name AS event,'
- 'FORMAT(\'%6s\', cbr.cbr) AS cbr,'
- 'FORMAT(\'%6s\', cbr.mhz) AS MHz,'
- 'FORMAT(\'%5s\', cbr.percent) AS percent,'
- 'to_hex(mwait.hints) AS hints_hex,'
- 'to_hex(mwait.extensions) AS extensions_hex,'
- 'FORMAT(\'%3s\', pwre.cstate) AS cstate,'
- 'FORMAT(\'%3s\', pwre.subcstate) AS subcstate,'
- 'CASE WHEN pwre.hw=FALSE THEN \'False\' WHEN pwre.hw=TRUE THEN \'True\' ELSE NULL END AS hw,'
- 'CASE WHEN exstop.exact_ip=FALSE THEN \'False\' WHEN exstop.exact_ip=TRUE THEN \'True\' ELSE NULL END AS exact_ip,'
- 'FORMAT(\'%3s\', pwrx.deepest_cstate) AS deepest_cstate,'
- 'FORMAT(\'%3s\', pwrx.last_cstate) AS last_cstate,'
- 'CASE WHEN pwrx.wake_reason=1 THEN \'Interrupt\''
- ' WHEN pwrx.wake_reason=2 THEN \'Timer Deadline\''
- ' WHEN pwrx.wake_reason=4 THEN \'Monitored Address\''
- ' WHEN pwrx.wake_reason=8 THEN \'HW\''
- ' ELSE FORMAT(\'%2s\', pwrx.wake_reason)'
- 'END AS wake_reason'
- ' FROM cbr'
- ' FULL JOIN mwait ON mwait.id = cbr.id'
- ' FULL JOIN pwre ON pwre.id = cbr.id'
- ' FULL JOIN exstop ON exstop.id = cbr.id'
- ' FULL JOIN pwrx ON pwrx.id = cbr.id'
- ' INNER JOIN samples ON samples.id = coalesce(cbr.id, mwait.id, pwre.id, exstop.id, pwrx.id)'
- ' INNER JOIN selected_events ON selected_events.id = samples.evsel_id'
- ' ORDER BY samples.id')
-
-do_query(query, 'CREATE VIEW context_switches_view AS '
- 'SELECT '
- 'context_switches.id,'
- 'context_switches.machine_id,'
- 'context_switches.time,'
- 'context_switches.cpu,'
- 'th_out.pid AS pid_out,'
- 'th_out.tid AS tid_out,'
- 'comm_out.comm AS comm_out,'
- 'th_in.pid AS pid_in,'
- 'th_in.tid AS tid_in,'
- 'comm_in.comm AS comm_in,'
- 'CASE WHEN context_switches.flags = 0 THEN \'in\''
- ' WHEN context_switches.flags = 1 THEN \'out\''
- ' WHEN context_switches.flags = 3 THEN \'out preempt\''
- ' ELSE CAST ( context_switches.flags AS VARCHAR(11) )'
- 'END AS flags'
- ' FROM context_switches'
- ' INNER JOIN threads AS th_out ON th_out.id = context_switches.thread_out_id'
- ' INNER JOIN threads AS th_in ON th_in.id = context_switches.thread_in_id'
- ' INNER JOIN comms AS comm_out ON comm_out.id = context_switches.comm_out_id'
- ' INNER JOIN comms AS comm_in ON comm_in.id = context_switches.comm_in_id')
-
-file_header = struct.pack("!11sii", b"PGCOPY\n\377\r\n\0", 0, 0)
-file_trailer = b"\377\377"
-
-def open_output_file(file_name):
- path_name = output_dir_name + "/" + file_name
- file = open(path_name, "wb+")
- file.write(file_header)
- return file
-
-def close_output_file(file):
- file.write(file_trailer)
- file.close()
-
-def copy_output_file_direct(file, table_name):
- close_output_file(file)
- sql = "COPY " + table_name + " FROM '" + file.name + "' (FORMAT 'binary')"
- do_query(query, sql)
-
-# Use COPY FROM STDIN because security may prevent postgres from accessing the files directly
-def copy_output_file(file, table_name):
- conn = PQconnectdb(toclientstr("dbname = " + dbname))
- if (PQstatus(conn)):
- raise Exception("COPY FROM STDIN PQconnectdb failed")
- file.write(file_trailer)
- file.seek(0)
- sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')"
- res = PQexec(conn, toclientstr(sql))
- if (PQresultStatus(res) != 4):
- raise Exception("COPY FROM STDIN PQexec failed")
- data = file.read(65536)
- while (len(data)):
- ret = PQputCopyData(conn, data, len(data))
- if (ret != 1):
- raise Exception("COPY FROM STDIN PQputCopyData failed, error " + str(ret))
- data = file.read(65536)
- ret = PQputCopyEnd(conn, None)
- if (ret != 1):
- raise Exception("COPY FROM STDIN PQputCopyEnd failed, error " + str(ret))
- PQfinish(conn)
-
-def remove_output_file(file):
- name = file.name
- file.close()
- os.unlink(name)
-
-evsel_file = open_output_file("evsel_table.bin")
-machine_file = open_output_file("machine_table.bin")
-thread_file = open_output_file("thread_table.bin")
-comm_file = open_output_file("comm_table.bin")
-comm_thread_file = open_output_file("comm_thread_table.bin")
-dso_file = open_output_file("dso_table.bin")
-symbol_file = open_output_file("symbol_table.bin")
-branch_type_file = open_output_file("branch_type_table.bin")
-sample_file = open_output_file("sample_table.bin")
-if perf_db_export_calls or perf_db_export_callchains:
- call_path_file = open_output_file("call_path_table.bin")
-if perf_db_export_calls:
- call_file = open_output_file("call_table.bin")
-ptwrite_file = open_output_file("ptwrite_table.bin")
-cbr_file = open_output_file("cbr_table.bin")
-mwait_file = open_output_file("mwait_table.bin")
-pwre_file = open_output_file("pwre_table.bin")
-exstop_file = open_output_file("exstop_table.bin")
-pwrx_file = open_output_file("pwrx_table.bin")
-context_switches_file = open_output_file("context_switches_table.bin")
-
-def trace_begin():
- printdate("Writing to intermediate files...")
- # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs
- evsel_table(0, "unknown")
- machine_table(0, 0, "unknown")
- thread_table(0, 0, 0, -1, -1)
- comm_table(0, "unknown", 0, 0, 0)
- dso_table(0, 0, "unknown", "unknown", "")
- symbol_table(0, 0, 0, 0, 0, "unknown")
- sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
- if perf_db_export_calls or perf_db_export_callchains:
- call_path_table(0, 0, 0, 0)
- call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
-
-unhandled_count = 0
-
-def is_table_empty(table_name):
- do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1');
- if query.next():
- return False
- return True
-
-def drop(table_name):
- do_query(query, 'DROP VIEW ' + table_name + '_view');
- do_query(query, 'DROP TABLE ' + table_name);
-
-def trace_end():
- printdate("Copying to database...")
- copy_output_file(evsel_file, "selected_events")
- copy_output_file(machine_file, "machines")
- copy_output_file(thread_file, "threads")
- copy_output_file(comm_file, "comms")
- copy_output_file(comm_thread_file, "comm_threads")
- copy_output_file(dso_file, "dsos")
- copy_output_file(symbol_file, "symbols")
- copy_output_file(branch_type_file, "branch_types")
- copy_output_file(sample_file, "samples")
- if perf_db_export_calls or perf_db_export_callchains:
- copy_output_file(call_path_file, "call_paths")
- if perf_db_export_calls:
- copy_output_file(call_file, "calls")
- copy_output_file(ptwrite_file, "ptwrite")
- copy_output_file(cbr_file, "cbr")
- copy_output_file(mwait_file, "mwait")
- copy_output_file(pwre_file, "pwre")
- copy_output_file(exstop_file, "exstop")
- copy_output_file(pwrx_file, "pwrx")
- copy_output_file(context_switches_file, "context_switches")
-
- printdate("Removing intermediate files...")
- remove_output_file(evsel_file)
- remove_output_file(machine_file)
- remove_output_file(thread_file)
- remove_output_file(comm_file)
- remove_output_file(comm_thread_file)
- remove_output_file(dso_file)
- remove_output_file(symbol_file)
- remove_output_file(branch_type_file)
- remove_output_file(sample_file)
- if perf_db_export_calls or perf_db_export_callchains:
- remove_output_file(call_path_file)
- if perf_db_export_calls:
- remove_output_file(call_file)
- remove_output_file(ptwrite_file)
- remove_output_file(cbr_file)
- remove_output_file(mwait_file)
- remove_output_file(pwre_file)
- remove_output_file(exstop_file)
- remove_output_file(pwrx_file)
- remove_output_file(context_switches_file)
- os.rmdir(output_dir_name)
- printdate("Adding primary keys")
- do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE machines ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE threads ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE comms ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE comm_threads ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE dsos ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE symbols ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE branch_types ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE samples ADD PRIMARY KEY (id)')
- if perf_db_export_calls or perf_db_export_callchains:
- do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)')
- if perf_db_export_calls:
- do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE ptwrite ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE cbr ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE mwait ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE pwre ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE exstop ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE pwrx ADD PRIMARY KEY (id)')
- do_query(query, 'ALTER TABLE context_switches ADD PRIMARY KEY (id)')
-
- printdate("Adding foreign keys")
- do_query(query, 'ALTER TABLE threads '
- 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),'
- 'ADD CONSTRAINT processfk FOREIGN KEY (process_id) REFERENCES threads (id)')
- do_query(query, 'ALTER TABLE comms '
- 'ADD CONSTRAINT threadfk FOREIGN KEY (c_thread_id) REFERENCES threads (id)')
- do_query(query, 'ALTER TABLE comm_threads '
- 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
- 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id)')
- do_query(query, 'ALTER TABLE dsos '
- 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id)')
- do_query(query, 'ALTER TABLE symbols '
- 'ADD CONSTRAINT dsofk FOREIGN KEY (dso_id) REFERENCES dsos (id)')
- do_query(query, 'ALTER TABLE samples '
- 'ADD CONSTRAINT evselfk FOREIGN KEY (evsel_id) REFERENCES selected_events (id),'
- 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),'
- 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),'
- 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
- 'ADD CONSTRAINT dsofk FOREIGN KEY (dso_id) REFERENCES dsos (id),'
- 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id),'
- 'ADD CONSTRAINT todsofk FOREIGN KEY (to_dso_id) REFERENCES dsos (id),'
- 'ADD CONSTRAINT tosymbolfk FOREIGN KEY (to_symbol_id) REFERENCES symbols (id)')
- if perf_db_export_calls or perf_db_export_callchains:
- do_query(query, 'ALTER TABLE call_paths '
- 'ADD CONSTRAINT parentfk FOREIGN KEY (parent_id) REFERENCES call_paths (id),'
- 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id)')
- if perf_db_export_calls:
- do_query(query, 'ALTER TABLE calls '
- 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),'
- 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
- 'ADD CONSTRAINT call_pathfk FOREIGN KEY (call_path_id) REFERENCES call_paths (id),'
- 'ADD CONSTRAINT callfk FOREIGN KEY (call_id) REFERENCES samples (id),'
- 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),'
- 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)')
- do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
- do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
- do_query(query, 'ALTER TABLE comms ADD has_calls boolean')
- do_query(query, 'UPDATE comms SET has_calls = TRUE WHERE comms.id IN (SELECT DISTINCT comm_id FROM calls)')
- do_query(query, 'ALTER TABLE ptwrite '
- 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)')
- do_query(query, 'ALTER TABLE cbr '
- 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)')
- do_query(query, 'ALTER TABLE mwait '
- 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)')
- do_query(query, 'ALTER TABLE pwre '
- 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)')
- do_query(query, 'ALTER TABLE exstop '
- 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)')
- do_query(query, 'ALTER TABLE pwrx '
- 'ADD CONSTRAINT idfk FOREIGN KEY (id) REFERENCES samples (id)')
- do_query(query, 'ALTER TABLE context_switches '
- 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),'
- 'ADD CONSTRAINT toutfk FOREIGN KEY (thread_out_id) REFERENCES threads (id),'
- 'ADD CONSTRAINT tinfk FOREIGN KEY (thread_in_id) REFERENCES threads (id),'
- 'ADD CONSTRAINT coutfk FOREIGN KEY (comm_out_id) REFERENCES comms (id),'
- 'ADD CONSTRAINT cinfk FOREIGN KEY (comm_in_id) REFERENCES comms (id)')
-
- printdate("Dropping unused tables")
- if is_table_empty("ptwrite"):
- drop("ptwrite")
- if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"):
- do_query(query, 'DROP VIEW power_events_view');
- drop("mwait")
- drop("pwre")
- drop("exstop")
- drop("pwrx")
- if is_table_empty("cbr"):
- drop("cbr")
- if is_table_empty("context_switches"):
- drop("context_switches")
-
- if (unhandled_count):
- printdate("Warning: ", unhandled_count, " unhandled events")
- printdate("Done")
-
-def trace_unhandled(event_name, context, event_fields_dict):
- global unhandled_count
- unhandled_count += 1
-
-def sched__sched_switch(*x):
- pass
-
-def evsel_table(evsel_id, evsel_name, *x):
- evsel_name = toserverstr(evsel_name)
- n = len(evsel_name)
- fmt = "!hiqi" + str(n) + "s"
- value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name)
- evsel_file.write(value)
-
-def machine_table(machine_id, pid, root_dir, *x):
- root_dir = toserverstr(root_dir)
- n = len(root_dir)
- fmt = "!hiqiii" + str(n) + "s"
- value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir)
- machine_file.write(value)
-
-def thread_table(thread_id, machine_id, process_id, pid, tid, *x):
- value = struct.pack("!hiqiqiqiiii", 5, 8, thread_id, 8, machine_id, 8, process_id, 4, pid, 4, tid)
- thread_file.write(value)
-
-def comm_table(comm_id, comm_str, thread_id, time, exec_flag, *x):
- comm_str = toserverstr(comm_str)
- n = len(comm_str)
- fmt = "!hiqi" + str(n) + "s" + "iqiqiB"
- value = struct.pack(fmt, 5, 8, comm_id, n, comm_str, 8, thread_id, 8, time, 1, exec_flag)
- comm_file.write(value)
-
-def comm_thread_table(comm_thread_id, comm_id, thread_id, *x):
- fmt = "!hiqiqiq"
- value = struct.pack(fmt, 3, 8, comm_thread_id, 8, comm_id, 8, thread_id)
- comm_thread_file.write(value)
-
-def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x):
- short_name = toserverstr(short_name)
- long_name = toserverstr(long_name)
- build_id = toserverstr(build_id)
- n1 = len(short_name)
- n2 = len(long_name)
- n3 = len(build_id)
- fmt = "!hiqiqi" + str(n1) + "si" + str(n2) + "si" + str(n3) + "s"
- value = struct.pack(fmt, 5, 8, dso_id, 8, machine_id, n1, short_name, n2, long_name, n3, build_id)
- dso_file.write(value)
-
-def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x):
- symbol_name = toserverstr(symbol_name)
- n = len(symbol_name)
- fmt = "!hiqiqiqiqiii" + str(n) + "s"
- value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name)
- symbol_file.write(value)
-
-def branch_type_table(branch_type, name, *x):
- name = toserverstr(name)
- n = len(name)
- fmt = "!hiii" + str(n) + "s"
- value = struct.pack(fmt, 2, 4, branch_type, n, name)
- branch_type_file.write(value)
-
-def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, call_path_id, insn_cnt, cyc_cnt, flags, *x):
- if branches:
- value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiBiqiqiqii", 21, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx, 8, call_path_id, 8, insn_cnt, 8, cyc_cnt, 4, flags)
- else:
- value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiBiqiqiqii", 25, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx, 8, call_path_id, 8, insn_cnt, 8, cyc_cnt, 4, flags)
- sample_file.write(value)
-
-def call_path_table(cp_id, parent_id, symbol_id, ip, *x):
- fmt = "!hiqiqiqiq"
- value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip)
- call_path_file.write(value)
-
-def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, parent_id, insn_cnt, cyc_cnt, *x):
- fmt = "!hiqiqiqiqiqiqiqiqiqiqiiiqiqiq"
- value = struct.pack(fmt, 14, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags, 8, parent_id, 8, insn_cnt, 8, cyc_cnt)
- call_file.write(value)
-
-def ptwrite(id, raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- flags = data[0]
- payload = data[1]
- exact_ip = flags & 1
- value = struct.pack("!hiqiqiB", 3, 8, id, 8, payload, 1, exact_ip)
- ptwrite_file.write(value)
-
-def cbr(id, raw_buf):
- data = struct.unpack_from("<BBBBII", raw_buf)
- cbr = data[0]
- MHz = (data[4] + 500) / 1000
- percent = ((cbr * 1000 / data[2]) + 5) / 10
- value = struct.pack("!hiqiiiiii", 4, 8, id, 4, cbr, 4, int(MHz), 4, int(percent))
- cbr_file.write(value)
-
-def mwait(id, raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- payload = data[1]
- hints = payload & 0xff
- extensions = (payload >> 32) & 0x3
- value = struct.pack("!hiqiiii", 3, 8, id, 4, hints, 4, extensions)
- mwait_file.write(value)
-
-def pwre(id, raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- payload = data[1]
- hw = (payload >> 7) & 1
- cstate = (payload >> 12) & 0xf
- subcstate = (payload >> 8) & 0xf
- value = struct.pack("!hiqiiiiiB", 4, 8, id, 4, cstate, 4, subcstate, 1, hw)
- pwre_file.write(value)
-
-def exstop(id, raw_buf):
- data = struct.unpack_from("<I", raw_buf)
- flags = data[0]
- exact_ip = flags & 1
- value = struct.pack("!hiqiB", 2, 8, id, 1, exact_ip)
- exstop_file.write(value)
-
-def pwrx(id, raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- payload = data[1]
- deepest_cstate = payload & 0xf
- last_cstate = (payload >> 4) & 0xf
- wake_reason = (payload >> 8) & 0xf
- value = struct.pack("!hiqiiiiii", 4, 8, id, 4, deepest_cstate, 4, last_cstate, 4, wake_reason)
- pwrx_file.write(value)
-
-def synth_data(id, config, raw_buf, *x):
- if config == 0:
- ptwrite(id, raw_buf)
- elif config == 1:
- mwait(id, raw_buf)
- elif config == 2:
- pwre(id, raw_buf)
- elif config == 3:
- exstop(id, raw_buf)
- elif config == 4:
- pwrx(id, raw_buf)
- elif config == 5:
- cbr(id, raw_buf)
-
-def context_switch_table(id, machine_id, time, cpu, thread_out_id, comm_out_id, thread_in_id, comm_in_id, flags, *x):
- fmt = "!hiqiqiqiiiqiqiqiqii"
- value = struct.pack(fmt, 9, 8, id, 8, machine_id, 8, time, 4, cpu, 8, thread_out_id, 8, comm_out_id, 8, thread_in_id, 8, comm_in_id, 4, flags)
- context_switches_file.write(value)
diff --git a/tools/perf/scripts/python/export-to-sqlite.py b/tools/perf/scripts/python/export-to-sqlite.py
deleted file mode 100644
index 73c992feb1b9..000000000000
--- a/tools/perf/scripts/python/export-to-sqlite.py
+++ /dev/null
@@ -1,799 +0,0 @@
-# export-to-sqlite.py: export perf data to a sqlite3 database
-# Copyright (c) 2017, Intel Corporation.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-
-from __future__ import print_function
-
-import os
-import sys
-import struct
-import datetime
-
-# To use this script you will need to have installed package python-pyside which
-# provides LGPL-licensed Python bindings for Qt. You will also need the package
-# libqt4-sql-sqlite for Qt sqlite3 support.
-#
-# Examples of installing pyside:
-#
-# ubuntu:
-#
-# $ sudo apt-get install python-pyside.qtsql libqt4-sql-psql
-#
-# Alternately, to use Python3 and/or pyside 2, one of the following:
-#
-# $ sudo apt-get install python3-pyside.qtsql libqt4-sql-psql
-# $ sudo apt-get install python-pyside2.qtsql libqt5sql5-psql
-# $ sudo apt-get install python3-pyside2.qtsql libqt5sql5-psql
-# fedora:
-#
-# $ sudo yum install python-pyside
-#
-# Alternately, to use Python3 and/or pyside 2, one of the following:
-# $ sudo yum install python3-pyside
-# $ pip install --user PySide2
-# $ pip3 install --user PySide2
-#
-# An example of using this script with Intel PT:
-#
-# $ perf record -e intel_pt//u ls
-# $ perf script -s ~/libexec/perf-core/scripts/python/export-to-sqlite.py pt_example branches calls
-# 2017-07-31 14:26:07.326913 Creating database...
-# 2017-07-31 14:26:07.538097 Writing records...
-# 2017-07-31 14:26:09.889292 Adding indexes
-# 2017-07-31 14:26:09.958746 Done
-#
-# To browse the database, sqlite3 can be used e.g.
-#
-# $ sqlite3 pt_example
-# sqlite> .header on
-# sqlite> select * from samples_view where id < 10;
-# sqlite> .mode column
-# sqlite> select * from samples_view where id < 10;
-# sqlite> .tables
-# sqlite> .schema samples_view
-# sqlite> .quit
-#
-# An example of using the database is provided by the script
-# exported-sql-viewer.py. Refer to that script for details.
-#
-# The database structure is practically the same as created by the script
-# export-to-postgresql.py. Refer to that script for details. A notable
-# difference is the 'transaction' column of the 'samples' table which is
-# renamed 'transaction_' in sqlite because 'transaction' is a reserved word.
-
-pyside_version_1 = True
-if not "pyside-version-1" in sys.argv:
- try:
- from PySide2.QtSql import *
- pyside_version_1 = False
- except:
- pass
-
-if pyside_version_1:
- from PySide.QtSql import *
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-# These perf imports are not used at present
-#from perf_trace_context import *
-#from Core import *
-
-perf_db_export_mode = True
-perf_db_export_calls = False
-perf_db_export_callchains = False
-
-def printerr(*args, **keyword_args):
- print(*args, file=sys.stderr, **keyword_args)
-
-def printdate(*args, **kw_args):
- print(datetime.datetime.today(), *args, sep=' ', **kw_args)
-
-def usage():
- printerr("Usage is: export-to-sqlite.py <database name> [<columns>] [<calls>] [<callchains>] [<pyside-version-1>]");
- printerr("where: columns 'all' or 'branches'");
- printerr(" calls 'calls' => create calls and call_paths table");
- printerr(" callchains 'callchains' => create call_paths table");
- printerr(" pyside-version-1 'pyside-version-1' => use pyside version 1");
- raise Exception("Too few or bad arguments")
-
-if (len(sys.argv) < 2):
- usage()
-
-dbname = sys.argv[1]
-
-if (len(sys.argv) >= 3):
- columns = sys.argv[2]
-else:
- columns = "all"
-
-if columns not in ("all", "branches"):
- usage()
-
-branches = (columns == "branches")
-
-for i in range(3,len(sys.argv)):
- if (sys.argv[i] == "calls"):
- perf_db_export_calls = True
- elif (sys.argv[i] == "callchains"):
- perf_db_export_callchains = True
- elif (sys.argv[i] == "pyside-version-1"):
- pass
- else:
- usage()
-
-def do_query(q, s):
- if (q.exec_(s)):
- return
- raise Exception("Query failed: " + q.lastError().text())
-
-def do_query_(q):
- if (q.exec_()):
- return
- raise Exception("Query failed: " + q.lastError().text())
-
-printdate("Creating database ...")
-
-db_exists = False
-try:
- f = open(dbname)
- f.close()
- db_exists = True
-except:
- pass
-
-if db_exists:
- raise Exception(dbname + " already exists")
-
-db = QSqlDatabase.addDatabase('QSQLITE')
-db.setDatabaseName(dbname)
-db.open()
-
-query = QSqlQuery(db)
-
-do_query(query, 'PRAGMA journal_mode = OFF')
-do_query(query, 'BEGIN TRANSACTION')
-
-do_query(query, 'CREATE TABLE selected_events ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'name varchar(80))')
-do_query(query, 'CREATE TABLE machines ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'pid integer,'
- 'root_dir varchar(4096))')
-do_query(query, 'CREATE TABLE threads ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'machine_id bigint,'
- 'process_id bigint,'
- 'pid integer,'
- 'tid integer)')
-do_query(query, 'CREATE TABLE comms ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'comm varchar(16),'
- 'c_thread_id bigint,'
- 'c_time bigint,'
- 'exec_flag boolean)')
-do_query(query, 'CREATE TABLE comm_threads ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'comm_id bigint,'
- 'thread_id bigint)')
-do_query(query, 'CREATE TABLE dsos ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'machine_id bigint,'
- 'short_name varchar(256),'
- 'long_name varchar(4096),'
- 'build_id varchar(64))')
-do_query(query, 'CREATE TABLE symbols ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'dso_id bigint,'
- 'sym_start bigint,'
- 'sym_end bigint,'
- 'binding integer,'
- 'name varchar(2048))')
-do_query(query, 'CREATE TABLE branch_types ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'name varchar(80))')
-
-if branches:
- do_query(query, 'CREATE TABLE samples ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'evsel_id bigint,'
- 'machine_id bigint,'
- 'thread_id bigint,'
- 'comm_id bigint,'
- 'dso_id bigint,'
- 'symbol_id bigint,'
- 'sym_offset bigint,'
- 'ip bigint,'
- 'time bigint,'
- 'cpu integer,'
- 'to_dso_id bigint,'
- 'to_symbol_id bigint,'
- 'to_sym_offset bigint,'
- 'to_ip bigint,'
- 'branch_type integer,'
- 'in_tx boolean,'
- 'call_path_id bigint,'
- 'insn_count bigint,'
- 'cyc_count bigint,'
- 'flags integer)')
-else:
- do_query(query, 'CREATE TABLE samples ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'evsel_id bigint,'
- 'machine_id bigint,'
- 'thread_id bigint,'
- 'comm_id bigint,'
- 'dso_id bigint,'
- 'symbol_id bigint,'
- 'sym_offset bigint,'
- 'ip bigint,'
- 'time bigint,'
- 'cpu integer,'
- 'to_dso_id bigint,'
- 'to_symbol_id bigint,'
- 'to_sym_offset bigint,'
- 'to_ip bigint,'
- 'period bigint,'
- 'weight bigint,'
- 'transaction_ bigint,'
- 'data_src bigint,'
- 'branch_type integer,'
- 'in_tx boolean,'
- 'call_path_id bigint,'
- 'insn_count bigint,'
- 'cyc_count bigint,'
- 'flags integer)')
-
-if perf_db_export_calls or perf_db_export_callchains:
- do_query(query, 'CREATE TABLE call_paths ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'parent_id bigint,'
- 'symbol_id bigint,'
- 'ip bigint)')
-if perf_db_export_calls:
- do_query(query, 'CREATE TABLE calls ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'thread_id bigint,'
- 'comm_id bigint,'
- 'call_path_id bigint,'
- 'call_time bigint,'
- 'return_time bigint,'
- 'branch_count bigint,'
- 'call_id bigint,'
- 'return_id bigint,'
- 'parent_call_path_id bigint,'
- 'flags integer,'
- 'parent_id bigint,'
- 'insn_count bigint,'
- 'cyc_count bigint)')
-
-do_query(query, 'CREATE TABLE ptwrite ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'payload bigint,'
- 'exact_ip integer)')
-
-do_query(query, 'CREATE TABLE cbr ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'cbr integer,'
- 'mhz integer,'
- 'percent integer)')
-
-do_query(query, 'CREATE TABLE mwait ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'hints integer,'
- 'extensions integer)')
-
-do_query(query, 'CREATE TABLE pwre ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'cstate integer,'
- 'subcstate integer,'
- 'hw integer)')
-
-do_query(query, 'CREATE TABLE exstop ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'exact_ip integer)')
-
-do_query(query, 'CREATE TABLE pwrx ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'deepest_cstate integer,'
- 'last_cstate integer,'
- 'wake_reason integer)')
-
-do_query(query, 'CREATE TABLE context_switches ('
- 'id integer NOT NULL PRIMARY KEY,'
- 'machine_id bigint,'
- 'time bigint,'
- 'cpu integer,'
- 'thread_out_id bigint,'
- 'comm_out_id bigint,'
- 'thread_in_id bigint,'
- 'comm_in_id bigint,'
- 'flags integer)')
-
-# printf was added to sqlite in version 3.8.3
-sqlite_has_printf = False
-try:
- do_query(query, 'SELECT printf("") FROM machines')
- sqlite_has_printf = True
-except:
- pass
-
-def emit_to_hex(x):
- if sqlite_has_printf:
- return 'printf("%x", ' + x + ')'
- else:
- return x
-
-do_query(query, 'CREATE VIEW machines_view AS '
- 'SELECT '
- 'id,'
- 'pid,'
- 'root_dir,'
- 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest'
- ' FROM machines')
-
-do_query(query, 'CREATE VIEW dsos_view AS '
- 'SELECT '
- 'id,'
- 'machine_id,'
- '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
- 'short_name,'
- 'long_name,'
- 'build_id'
- ' FROM dsos')
-
-do_query(query, 'CREATE VIEW symbols_view AS '
- 'SELECT '
- 'id,'
- 'name,'
- '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,'
- 'dso_id,'
- 'sym_start,'
- 'sym_end,'
- 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding'
- ' FROM symbols')
-
-do_query(query, 'CREATE VIEW threads_view AS '
- 'SELECT '
- 'id,'
- 'machine_id,'
- '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,'
- 'process_id,'
- 'pid,'
- 'tid'
- ' FROM threads')
-
-do_query(query, 'CREATE VIEW comm_threads_view AS '
- 'SELECT '
- 'comm_id,'
- '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
- 'thread_id,'
- '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
- '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
- ' FROM comm_threads')
-
-if perf_db_export_calls or perf_db_export_callchains:
- do_query(query, 'CREATE VIEW call_paths_view AS '
- 'SELECT '
- 'c.id,'
- + emit_to_hex('c.ip') + ' AS ip,'
- 'c.symbol_id,'
- '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,'
- '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,'
- '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,'
- 'c.parent_id,'
- + emit_to_hex('p.ip') + ' AS parent_ip,'
- 'p.symbol_id AS parent_symbol_id,'
- '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,'
- '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
- '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
- ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
-if perf_db_export_calls:
- do_query(query, 'CREATE VIEW calls_view AS '
- 'SELECT '
- 'calls.id,'
- 'thread_id,'
- '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
- '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
- '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
- 'call_path_id,'
- + emit_to_hex('ip') + ' AS ip,'
- 'symbol_id,'
- '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
- 'call_time,'
- 'return_time,'
- 'return_time - call_time AS elapsed_time,'
- 'branch_count,'
- 'insn_count,'
- 'cyc_count,'
- 'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC,'
- 'call_id,'
- 'return_id,'
- 'CASE WHEN flags=0 THEN \'\' WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' WHEN flags=6 THEN \'jump\' ELSE flags END AS flags,'
- 'parent_call_path_id,'
- 'calls.parent_id'
- ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id')
-
-do_query(query, 'CREATE VIEW samples_view AS '
- 'SELECT '
- 'id,'
- 'time,'
- 'cpu,'
- '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
- '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
- '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
- '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,'
- + emit_to_hex('ip') + ' AS ip_hex,'
- '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
- 'sym_offset,'
- '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,'
- + emit_to_hex('to_ip') + ' AS to_ip_hex,'
- '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,'
- 'to_sym_offset,'
- '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'
- '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,'
- 'in_tx,'
- 'insn_count,'
- 'cyc_count,'
- 'CASE WHEN cyc_count=0 THEN CAST(0 AS FLOAT) ELSE ROUND(CAST(insn_count AS FLOAT) / cyc_count, 2) END AS IPC,'
- 'flags'
- ' FROM samples')
-
-do_query(query, 'CREATE VIEW ptwrite_view AS '
- 'SELECT '
- 'ptwrite.id,'
- 'time,'
- 'cpu,'
- + emit_to_hex('payload') + ' AS payload_hex,'
- 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip'
- ' FROM ptwrite'
- ' INNER JOIN samples ON samples.id = ptwrite.id')
-
-do_query(query, 'CREATE VIEW cbr_view AS '
- 'SELECT '
- 'cbr.id,'
- 'time,'
- 'cpu,'
- 'cbr,'
- 'mhz,'
- 'percent'
- ' FROM cbr'
- ' INNER JOIN samples ON samples.id = cbr.id')
-
-do_query(query, 'CREATE VIEW mwait_view AS '
- 'SELECT '
- 'mwait.id,'
- 'time,'
- 'cpu,'
- + emit_to_hex('hints') + ' AS hints_hex,'
- + emit_to_hex('extensions') + ' AS extensions_hex'
- ' FROM mwait'
- ' INNER JOIN samples ON samples.id = mwait.id')
-
-do_query(query, 'CREATE VIEW pwre_view AS '
- 'SELECT '
- 'pwre.id,'
- 'time,'
- 'cpu,'
- 'cstate,'
- 'subcstate,'
- 'CASE WHEN hw=0 THEN \'False\' ELSE \'True\' END AS hw'
- ' FROM pwre'
- ' INNER JOIN samples ON samples.id = pwre.id')
-
-do_query(query, 'CREATE VIEW exstop_view AS '
- 'SELECT '
- 'exstop.id,'
- 'time,'
- 'cpu,'
- 'CASE WHEN exact_ip=0 THEN \'False\' ELSE \'True\' END AS exact_ip'
- ' FROM exstop'
- ' INNER JOIN samples ON samples.id = exstop.id')
-
-do_query(query, 'CREATE VIEW pwrx_view AS '
- 'SELECT '
- 'pwrx.id,'
- 'time,'
- 'cpu,'
- 'deepest_cstate,'
- 'last_cstate,'
- 'CASE WHEN wake_reason=1 THEN \'Interrupt\''
- ' WHEN wake_reason=2 THEN \'Timer Deadline\''
- ' WHEN wake_reason=4 THEN \'Monitored Address\''
- ' WHEN wake_reason=8 THEN \'HW\''
- ' ELSE wake_reason '
- 'END AS wake_reason'
- ' FROM pwrx'
- ' INNER JOIN samples ON samples.id = pwrx.id')
-
-do_query(query, 'CREATE VIEW power_events_view AS '
- 'SELECT '
- 'samples.id,'
- 'time,'
- 'cpu,'
- 'selected_events.name AS event,'
- 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT cbr FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS cbr,'
- 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT mhz FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS mhz,'
- 'CASE WHEN selected_events.name=\'cbr\' THEN (SELECT percent FROM cbr WHERE cbr.id = samples.id) ELSE "" END AS percent,'
- 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('hints') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS hints_hex,'
- 'CASE WHEN selected_events.name=\'mwait\' THEN (SELECT ' + emit_to_hex('extensions') + ' FROM mwait WHERE mwait.id = samples.id) ELSE "" END AS extensions_hex,'
- 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT cstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS cstate,'
- 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT subcstate FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS subcstate,'
- 'CASE WHEN selected_events.name=\'pwre\' THEN (SELECT hw FROM pwre WHERE pwre.id = samples.id) ELSE "" END AS hw,'
- 'CASE WHEN selected_events.name=\'exstop\' THEN (SELECT exact_ip FROM exstop WHERE exstop.id = samples.id) ELSE "" END AS exact_ip,'
- 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT deepest_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS deepest_cstate,'
- 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT last_cstate FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS last_cstate,'
- 'CASE WHEN selected_events.name=\'pwrx\' THEN (SELECT '
- 'CASE WHEN wake_reason=1 THEN \'Interrupt\''
- ' WHEN wake_reason=2 THEN \'Timer Deadline\''
- ' WHEN wake_reason=4 THEN \'Monitored Address\''
- ' WHEN wake_reason=8 THEN \'HW\''
- ' ELSE wake_reason '
- 'END'
- ' FROM pwrx WHERE pwrx.id = samples.id) ELSE "" END AS wake_reason'
- ' FROM samples'
- ' INNER JOIN selected_events ON selected_events.id = evsel_id'
- ' WHERE selected_events.name IN (\'cbr\',\'mwait\',\'exstop\',\'pwre\',\'pwrx\')')
-
-do_query(query, 'CREATE VIEW context_switches_view AS '
- 'SELECT '
- 'context_switches.id,'
- 'context_switches.machine_id,'
- 'context_switches.time,'
- 'context_switches.cpu,'
- 'th_out.pid AS pid_out,'
- 'th_out.tid AS tid_out,'
- 'comm_out.comm AS comm_out,'
- 'th_in.pid AS pid_in,'
- 'th_in.tid AS tid_in,'
- 'comm_in.comm AS comm_in,'
- 'CASE WHEN context_switches.flags = 0 THEN \'in\''
- ' WHEN context_switches.flags = 1 THEN \'out\''
- ' WHEN context_switches.flags = 3 THEN \'out preempt\''
- ' ELSE context_switches.flags '
- 'END AS flags'
- ' FROM context_switches'
- ' INNER JOIN threads AS th_out ON th_out.id = context_switches.thread_out_id'
- ' INNER JOIN threads AS th_in ON th_in.id = context_switches.thread_in_id'
- ' INNER JOIN comms AS comm_out ON comm_out.id = context_switches.comm_out_id'
- ' INNER JOIN comms AS comm_in ON comm_in.id = context_switches.comm_in_id')
-
-do_query(query, 'END TRANSACTION')
-
-evsel_query = QSqlQuery(db)
-evsel_query.prepare("INSERT INTO selected_events VALUES (?, ?)")
-machine_query = QSqlQuery(db)
-machine_query.prepare("INSERT INTO machines VALUES (?, ?, ?)")
-thread_query = QSqlQuery(db)
-thread_query.prepare("INSERT INTO threads VALUES (?, ?, ?, ?, ?)")
-comm_query = QSqlQuery(db)
-comm_query.prepare("INSERT INTO comms VALUES (?, ?, ?, ?, ?)")
-comm_thread_query = QSqlQuery(db)
-comm_thread_query.prepare("INSERT INTO comm_threads VALUES (?, ?, ?)")
-dso_query = QSqlQuery(db)
-dso_query.prepare("INSERT INTO dsos VALUES (?, ?, ?, ?, ?)")
-symbol_query = QSqlQuery(db)
-symbol_query.prepare("INSERT INTO symbols VALUES (?, ?, ?, ?, ?, ?)")
-branch_type_query = QSqlQuery(db)
-branch_type_query.prepare("INSERT INTO branch_types VALUES (?, ?)")
-sample_query = QSqlQuery(db)
-if branches:
- sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
-else:
- sample_query.prepare("INSERT INTO samples VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
-if perf_db_export_calls or perf_db_export_callchains:
- call_path_query = QSqlQuery(db)
- call_path_query.prepare("INSERT INTO call_paths VALUES (?, ?, ?, ?)")
-if perf_db_export_calls:
- call_query = QSqlQuery(db)
- call_query.prepare("INSERT INTO calls VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
-ptwrite_query = QSqlQuery(db)
-ptwrite_query.prepare("INSERT INTO ptwrite VALUES (?, ?, ?)")
-cbr_query = QSqlQuery(db)
-cbr_query.prepare("INSERT INTO cbr VALUES (?, ?, ?, ?)")
-mwait_query = QSqlQuery(db)
-mwait_query.prepare("INSERT INTO mwait VALUES (?, ?, ?)")
-pwre_query = QSqlQuery(db)
-pwre_query.prepare("INSERT INTO pwre VALUES (?, ?, ?, ?)")
-exstop_query = QSqlQuery(db)
-exstop_query.prepare("INSERT INTO exstop VALUES (?, ?)")
-pwrx_query = QSqlQuery(db)
-pwrx_query.prepare("INSERT INTO pwrx VALUES (?, ?, ?, ?)")
-context_switch_query = QSqlQuery(db)
-context_switch_query.prepare("INSERT INTO context_switches VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")
-
-def trace_begin():
- printdate("Writing records...")
- do_query(query, 'BEGIN TRANSACTION')
- # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs
- evsel_table(0, "unknown")
- machine_table(0, 0, "unknown")
- thread_table(0, 0, 0, -1, -1)
- comm_table(0, "unknown", 0, 0, 0)
- dso_table(0, 0, "unknown", "unknown", "")
- symbol_table(0, 0, 0, 0, 0, "unknown")
- sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
- if perf_db_export_calls or perf_db_export_callchains:
- call_path_table(0, 0, 0, 0)
- call_return_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
-
-unhandled_count = 0
-
-def is_table_empty(table_name):
- do_query(query, 'SELECT * FROM ' + table_name + ' LIMIT 1');
- if query.next():
- return False
- return True
-
-def drop(table_name):
- do_query(query, 'DROP VIEW ' + table_name + '_view');
- do_query(query, 'DROP TABLE ' + table_name);
-
-def trace_end():
- do_query(query, 'END TRANSACTION')
-
- printdate("Adding indexes")
- if perf_db_export_calls:
- do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
- do_query(query, 'CREATE INDEX pid_idx ON calls (parent_id)')
- do_query(query, 'ALTER TABLE comms ADD has_calls boolean')
- do_query(query, 'UPDATE comms SET has_calls = 1 WHERE comms.id IN (SELECT DISTINCT comm_id FROM calls)')
-
- printdate("Dropping unused tables")
- if is_table_empty("ptwrite"):
- drop("ptwrite")
- if is_table_empty("mwait") and is_table_empty("pwre") and is_table_empty("exstop") and is_table_empty("pwrx"):
- do_query(query, 'DROP VIEW power_events_view');
- drop("mwait")
- drop("pwre")
- drop("exstop")
- drop("pwrx")
- if is_table_empty("cbr"):
- drop("cbr")
- if is_table_empty("context_switches"):
- drop("context_switches")
-
- if (unhandled_count):
- printdate("Warning: ", unhandled_count, " unhandled events")
- printdate("Done")
-
-def trace_unhandled(event_name, context, event_fields_dict):
- global unhandled_count
- unhandled_count += 1
-
-def sched__sched_switch(*x):
- pass
-
-def bind_exec(q, n, x):
- for xx in x[0:n]:
- q.addBindValue(str(xx))
- do_query_(q)
-
-def evsel_table(*x):
- bind_exec(evsel_query, 2, x)
-
-def machine_table(*x):
- bind_exec(machine_query, 3, x)
-
-def thread_table(*x):
- bind_exec(thread_query, 5, x)
-
-def comm_table(*x):
- bind_exec(comm_query, 5, x)
-
-def comm_thread_table(*x):
- bind_exec(comm_thread_query, 3, x)
-
-def dso_table(*x):
- bind_exec(dso_query, 5, x)
-
-def symbol_table(*x):
- bind_exec(symbol_query, 6, x)
-
-def branch_type_table(*x):
- bind_exec(branch_type_query, 2, x)
-
-def sample_table(*x):
- if branches:
- for xx in x[0:15]:
- sample_query.addBindValue(str(xx))
- for xx in x[19:25]:
- sample_query.addBindValue(str(xx))
- do_query_(sample_query)
- else:
- bind_exec(sample_query, 25, x)
-
-def call_path_table(*x):
- bind_exec(call_path_query, 4, x)
-
-def call_return_table(*x):
- bind_exec(call_query, 14, x)
-
-def ptwrite(id, raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- flags = data[0]
- payload = data[1]
- exact_ip = flags & 1
- ptwrite_query.addBindValue(str(id))
- ptwrite_query.addBindValue(str(payload))
- ptwrite_query.addBindValue(str(exact_ip))
- do_query_(ptwrite_query)
-
-def cbr(id, raw_buf):
- data = struct.unpack_from("<BBBBII", raw_buf)
- cbr = data[0]
- MHz = (data[4] + 500) / 1000
- percent = ((cbr * 1000 / data[2]) + 5) / 10
- cbr_query.addBindValue(str(id))
- cbr_query.addBindValue(str(cbr))
- cbr_query.addBindValue(str(MHz))
- cbr_query.addBindValue(str(percent))
- do_query_(cbr_query)
-
-def mwait(id, raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- payload = data[1]
- hints = payload & 0xff
- extensions = (payload >> 32) & 0x3
- mwait_query.addBindValue(str(id))
- mwait_query.addBindValue(str(hints))
- mwait_query.addBindValue(str(extensions))
- do_query_(mwait_query)
-
-def pwre(id, raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- payload = data[1]
- hw = (payload >> 7) & 1
- cstate = (payload >> 12) & 0xf
- subcstate = (payload >> 8) & 0xf
- pwre_query.addBindValue(str(id))
- pwre_query.addBindValue(str(cstate))
- pwre_query.addBindValue(str(subcstate))
- pwre_query.addBindValue(str(hw))
- do_query_(pwre_query)
-
-def exstop(id, raw_buf):
- data = struct.unpack_from("<I", raw_buf)
- flags = data[0]
- exact_ip = flags & 1
- exstop_query.addBindValue(str(id))
- exstop_query.addBindValue(str(exact_ip))
- do_query_(exstop_query)
-
-def pwrx(id, raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- payload = data[1]
- deepest_cstate = payload & 0xf
- last_cstate = (payload >> 4) & 0xf
- wake_reason = (payload >> 8) & 0xf
- pwrx_query.addBindValue(str(id))
- pwrx_query.addBindValue(str(deepest_cstate))
- pwrx_query.addBindValue(str(last_cstate))
- pwrx_query.addBindValue(str(wake_reason))
- do_query_(pwrx_query)
-
-def synth_data(id, config, raw_buf, *x):
- if config == 0:
- ptwrite(id, raw_buf)
- elif config == 1:
- mwait(id, raw_buf)
- elif config == 2:
- pwre(id, raw_buf)
- elif config == 3:
- exstop(id, raw_buf)
- elif config == 4:
- pwrx(id, raw_buf)
- elif config == 5:
- cbr(id, raw_buf)
-
-def context_switch_table(*x):
- bind_exec(context_switch_query, 9, x)
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
deleted file mode 100644
index 310efe5e7e23..000000000000
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# failed system call counts, by pid
-# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
-# Licensed under the terms of the GNU GPL License version 2
-#
-# Displays system-wide failed system call totals, broken down by pid.
-# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
-
-from __future__ import print_function
-
-import os
-import sys
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-from Util import *
-
-usage = "perf script -s syscall-counts-by-pid.py [comm|pid]\n";
-
-for_comm = None
-for_pid = None
-
-if len(sys.argv) > 2:
- sys.exit(usage)
-
-if len(sys.argv) > 1:
- try:
- for_pid = int(sys.argv[1])
- except:
- for_comm = sys.argv[1]
-
-syscalls = autodict()
-
-def trace_begin():
- print("Press control+C to stop and show the summary")
-
-def trace_end():
- print_error_totals()
-
-def raw_syscalls__sys_exit(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, id, ret):
- if (for_comm and common_comm != for_comm) or \
- (for_pid and common_pid != for_pid ):
- return
-
- if ret < 0:
- try:
- syscalls[common_comm][common_pid][id][ret] += 1
- except TypeError:
- syscalls[common_comm][common_pid][id][ret] = 1
-
-def syscalls__sys_exit(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- id, ret):
- raw_syscalls__sys_exit(**locals())
-
-def print_error_totals():
- if for_comm is not None:
- print("\nsyscall errors for %s:\n" % (for_comm))
- else:
- print("\nsyscall errors:\n")
-
- print("%-30s %10s" % ("comm [pid]", "count"))
- print("%-30s %10s" % ("------------------------------", "----------"))
-
- comm_keys = syscalls.keys()
- for comm in comm_keys:
- pid_keys = syscalls[comm].keys()
- for pid in pid_keys:
- print("\n%s [%d]" % (comm, pid))
- id_keys = syscalls[comm][pid].keys()
- for id in id_keys:
- print(" syscall: %-16s" % syscall_name(id))
- ret_keys = syscalls[comm][pid][id].keys()
- for ret, val in sorted(syscalls[comm][pid][id].items(), key = lambda kv: (kv[1], kv[0]), reverse = True):
- print(" err = %-20s %10d" % (strerror(ret), val))
diff --git a/tools/perf/scripts/python/flamegraph.py b/tools/perf/scripts/python/flamegraph.py
deleted file mode 100755
index ad735990c5be..000000000000
--- a/tools/perf/scripts/python/flamegraph.py
+++ /dev/null
@@ -1,267 +0,0 @@
-# flamegraph.py - create flame graphs from perf samples
-# SPDX-License-Identifier: GPL-2.0
-#
-# Usage:
-#
-# perf record -a -g -F 99 sleep 60
-# perf script report flamegraph
-#
-# Combined:
-#
-# perf script flamegraph -a -F 99 sleep 60
-#
-# Written by Andreas Gerstmayr <agerstmayr@redhat.com>
-# Flame Graphs invented by Brendan Gregg <bgregg@netflix.com>
-# Works in tandem with d3-flame-graph by Martin Spier <mspier@netflix.com>
-#
-# pylint: disable=missing-module-docstring
-# pylint: disable=missing-class-docstring
-# pylint: disable=missing-function-docstring
-
-import argparse
-import hashlib
-import io
-import json
-import os
-import subprocess
-import sys
-from typing import Dict, Optional, Union
-import urllib.request
-
-MINIMAL_HTML = """
-
-
-
-
-
-
-
- const stacks = [/** @flamegraph_json **/];
- // Note, options is unused.
- const options = [/** @options_json **/];
-
- var chart = flamegraph();
- d3.select("#chart")
- .datum(stacks[0])
- .call(chart);
-
-
-"""
-
-# pylint: disable=too-few-public-methods
-class Node:
- def __init__(self, name: str, libtype: str):
- self.name = name
- # "root" | "kernel" | ""
- # "" indicates user space
- self.libtype = libtype
- self.value: int = 0
- self.children: list[Node] = []
-
- def to_json(self) -> Dict[str, Union[str, int, list[Dict]]]:
- return {
- "n": self.name,
- "l": self.libtype,
- "v": self.value,
- "c": [x.to_json() for x in self.children]
- }
-
-
-class FlameGraphCLI:
- def __init__(self, args):
- self.args = args
- self.stack = Node("all", "root")
-
- @staticmethod
- def get_libtype_from_dso(dso: Optional[str]) -> str:
- """
- when kernel-debuginfo is installed,
- dso points to /usr/lib/debug/lib/modules/*/vmlinux
- """
- if dso and (dso == "[kernel.kallsyms]" or dso.endswith("/vmlinux")):
- return "kernel"
-
- return ""
-
- @staticmethod
- def find_or_create_node(node: Node, name: str, libtype: str) -> Node:
- for child in node.children:
- if child.name == name:
- return child
-
- child = Node(name, libtype)
- node.children.append(child)
- return child
-
- def process_event(self, event) -> None:
- # ignore events where the event name does not match
- # the one specified by the user
- if self.args.event_name and event.get("ev_name") != self.args.event_name:
- return
-
- pid = event.get("sample", {}).get("pid", 0)
- # event["dso"] sometimes contains /usr/lib/debug/lib/modules/*/vmlinux
- # for user-space processes; let's use pid for kernel or user-space distinction
- if pid == 0:
- comm = event["comm"]
- libtype = "kernel"
- else:
- comm = f"{event['comm']} ({pid})"
- libtype = ""
- node = self.find_or_create_node(self.stack, comm, libtype)
-
- if "callchain" in event:
- for entry in reversed(event["callchain"]):
- name = entry.get("sym", {}).get("name", "[unknown]")
- libtype = self.get_libtype_from_dso(entry.get("dso"))
- node = self.find_or_create_node(node, name, libtype)
- else:
- name = event.get("symbol", "[unknown]")
- libtype = self.get_libtype_from_dso(event.get("dso"))
- node = self.find_or_create_node(node, name, libtype)
- node.value += 1
-
- def get_report_header(self) -> str:
- if self.args.input == "-":
- # when this script is invoked with "perf script flamegraph",
- # no perf.data is created and we cannot read the header of it
- return ""
-
- try:
- # if the file name other than perf.data is given,
- # we read the header of that file
- if self.args.input:
- output = subprocess.check_output(["perf", "report", "--header-only",
- "-i", self.args.input])
- else:
- output = subprocess.check_output(["perf", "report", "--header-only"])
-
- result = output.decode("utf-8")
- if self.args.event_name:
- result += "\nFocused event: " + self.args.event_name
- return result
- except Exception as err: # pylint: disable=broad-except
- print(f"Error reading report header: {err}", file=sys.stderr)
- return ""
-
- def trace_end(self) -> None:
- stacks_json = json.dumps(self.stack, default=lambda x: x.to_json())
-
- if self.args.format == "html":
- report_header = self.get_report_header()
- options = {
- "colorscheme": self.args.colorscheme,
- "context": report_header
- }
- options_json = json.dumps(options)
-
- template_md5sum = None
- if self.args.format == "html":
- if os.path.isfile(self.args.template):
- template = f"file://{self.args.template}"
- else:
- if not self.args.allow_download:
- print(f"""Warning: Flame Graph template '{self.args.template}'
-does not exist. To avoid this please install a package such as the
-js-d3-flame-graph or libjs-d3-flame-graph, specify an existing flame
-graph template (--template PATH) or use another output format (--format
-FORMAT).""",
- file=sys.stderr)
- if self.args.input == "-":
- print(
-"""Not attempting to download Flame Graph template as script command line
-input is disabled due to using live mode. If you want to download the
-template retry without live mode. For example, use 'perf record -a -g
--F 99 sleep 60' and 'perf script report flamegraph'. Alternatively,
-download the template from:
-https://cdn.jsdelivr.net/npm/d3-flame-graph@4.1.3/dist/templates/d3-flamegraph-base.html
-and place it at:
-/usr/share/d3-flame-graph/d3-flamegraph-base.html""",
- file=sys.stderr)
- sys.exit(1)
- s = None
- while s not in ["y", "n"]:
- s = input("Do you wish to download a template from cdn.jsdelivr.net?" +
- "(this warning can be suppressed with --allow-download) [yn] "
- ).lower()
- if s == "n":
- sys.exit(1)
- template = ("https://cdn.jsdelivr.net/npm/d3-flame-graph@4.1.3/dist/templates/"
- "d3-flamegraph-base.html")
- template_md5sum = "143e0d06ba69b8370b9848dcd6ae3f36"
-
- try:
- with urllib.request.urlopen(template) as url_template:
- output_str = "".join([
- l.decode("utf-8") for l in url_template.readlines()
- ])
- except Exception as err:
- print(f"Error reading template {template}: {err}\n"
- "a minimal flame graph will be generated", file=sys.stderr)
- output_str = MINIMAL_HTML
- template_md5sum = None
-
- if template_md5sum:
- download_md5sum = hashlib.md5(output_str.encode("utf-8")).hexdigest()
- if download_md5sum != template_md5sum:
- s = None
- while s not in ["y", "n"]:
- s = input(f"""Unexpected template md5sum.
-{download_md5sum} != {template_md5sum}, for:
-{output_str}
-continue?[yn] """).lower()
- if s == "n":
- sys.exit(1)
-
- output_str = output_str.replace("/** @options_json **/", options_json)
- output_str = output_str.replace("/** @flamegraph_json **/", stacks_json)
-
- output_fn = self.args.output or "flamegraph.html"
- else:
- output_str = stacks_json
- output_fn = self.args.output or "stacks.json"
-
- if output_fn == "-":
- with io.open(sys.stdout.fileno(), "w", encoding="utf-8", closefd=False) as out:
- out.write(output_str)
- else:
- print(f"dumping data to {output_fn}")
- try:
- with io.open(output_fn, "w", encoding="utf-8") as out:
- out.write(output_str)
- except IOError as err:
- print(f"Error writing output file: {err}", file=sys.stderr)
- sys.exit(1)
-
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser(description="Create flame graphs.")
- parser.add_argument("-f", "--format",
- default="html", choices=["json", "html"],
- help="output file format")
- parser.add_argument("-o", "--output",
- help="output file name")
- parser.add_argument("--template",
- default="/usr/share/d3-flame-graph/d3-flamegraph-base.html",
- help="path to flame graph HTML template")
- parser.add_argument("--colorscheme",
- default="blue-green",
- help="flame graph color scheme",
- choices=["blue-green", "orange"])
- parser.add_argument("-i", "--input",
- help=argparse.SUPPRESS)
- parser.add_argument("--allow-download",
- default=False,
- action="store_true",
- help="allow unprompted downloading of HTML template")
- parser.add_argument("-e", "--event",
- default="",
- dest="event_name",
- type=str,
- help="specify the event to generate flamegraph for")
-
- cli_args = parser.parse_args()
- cli = FlameGraphCLI(cli_args)
-
- process_event = cli.process_event
- trace_end = cli.trace_end
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
deleted file mode 100644
index 7e884d46f920..000000000000
--- a/tools/perf/scripts/python/futex-contention.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# futex contention
-# (c) 2010, Arnaldo Carvalho de Melo <acme@redhat.com>
-# Licensed under the terms of the GNU GPL License version 2
-#
-# Translation of:
-#
-# http://sourceware.org/systemtap/wiki/WSFutexContention
-#
-# to perf python scripting.
-#
-# Measures futex contention
-
-from __future__ import print_function
-
-import os
-import sys
-sys.path.append(os.environ['PERF_EXEC_PATH'] +
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-from Util import *
-
-process_names = {}
-thread_thislock = {}
-thread_blocktime = {}
-
-lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
-process_names = {} # long-lived pid-to-execname mapping
-
-
-def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
- nr, uaddr, op, val, utime, uaddr2, val3):
- cmd = op & FUTEX_CMD_MASK
- if cmd != FUTEX_WAIT:
- return # we don't care about originators of WAKE events
-
- process_names[tid] = comm
- thread_thislock[tid] = uaddr
- thread_blocktime[tid] = nsecs(s, ns)
-
-
-def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
- nr, ret):
- if tid in thread_blocktime:
- elapsed = nsecs(s, ns) - thread_blocktime[tid]
- add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed)
- del thread_blocktime[tid]
- del thread_thislock[tid]
-
-
-def trace_begin():
- print("Press control+C to stop and show the summary")
-
-
-def trace_end():
- for (tid, lock) in lock_waits:
- min, max, avg, count = lock_waits[tid, lock]
- print("%s[%d] lock %x contended %d times, %d avg ns [max: %d ns, min %d ns]" %
- (process_names[tid], tid, lock, count, avg, max, min))
diff --git a/tools/perf/scripts/python/gecko.py b/tools/perf/scripts/python/gecko.py
deleted file mode 100644
index bc5a72f94bfa..000000000000
--- a/tools/perf/scripts/python/gecko.py
+++ /dev/null
@@ -1,395 +0,0 @@
-# gecko.py - Convert perf record output to Firefox's gecko profile format
-# SPDX-License-Identifier: GPL-2.0
-#
-# The script converts perf.data to Gecko Profile Format,
-# which can be read by https://profiler.firefox.com/.
-#
-# Usage:
-#
-# perf record -a -g -F 99 sleep 60
-# perf script report gecko
-#
-# Combined:
-#
-# perf script gecko -F 99 -a sleep 60
-
-import os
-import sys
-import time
-import json
-import string
-import random
-import argparse
-import threading
-import webbrowser
-import urllib.parse
-from os import system
-from functools import reduce
-from dataclasses import dataclass, field
-from http.server import HTTPServer, SimpleHTTPRequestHandler, test
-from typing import List, Dict, Optional, NamedTuple, Set, Tuple, Any
-
-# Add the Perf-Trace-Util library to the Python path
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-
-StringID = int
-StackID = int
-FrameID = int
-CategoryID = int
-Milliseconds = float
-
-# start_time is intialiazed only once for the all event traces.
-start_time = None
-
-# https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/profile.js#L425
-# Follow Brendan Gregg's Flamegraph convention: orange for kernel and yellow for user space by default.
-CATEGORIES = None
-
-# The product name is used by the profiler UI to show the Operating system and Processor.
-PRODUCT = os.popen('uname -op').read().strip()
-
-# store the output file
-output_file = None
-
-# Here key = tid, value = Thread
-tid_to_thread = dict()
-
-# The HTTP server is used to serve the profile to the profiler UI.
-http_server_thread = None
-
-# The category index is used by the profiler UI to show the color of the flame graph.
-USER_CATEGORY_INDEX = 0
-KERNEL_CATEGORY_INDEX = 1
-
-# https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L156
-class Frame(NamedTuple):
- string_id: StringID
- relevantForJS: bool
- innerWindowID: int
- implementation: None
- optimizations: None
- line: None
- column: None
- category: CategoryID
- subcategory: int
-
-# https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L216
-class Stack(NamedTuple):
- prefix_id: Optional[StackID]
- frame_id: FrameID
-
-# https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L90
-class Sample(NamedTuple):
- stack_id: Optional[StackID]
- time_ms: Milliseconds
- responsiveness: int
-
-@dataclass
-class Thread:
- """A builder for a profile of the thread.
-
- Attributes:
- comm: Thread command-line (name).
- pid: process ID of containing process.
- tid: thread ID.
- samples: Timeline of profile samples.
- frameTable: interned stack frame ID -> stack frame.
- stringTable: interned string ID -> string.
- stringMap: interned string -> string ID.
- stackTable: interned stack ID -> stack.
- stackMap: (stack prefix ID, leaf stack frame ID) -> interned Stack ID.
- frameMap: Stack Frame string -> interned Frame ID.
- comm: str
- pid: int
- tid: int
- samples: List[Sample] = field(default_factory=list)
- frameTable: List[Frame] = field(default_factory=list)
- stringTable: List[str] = field(default_factory=list)
- stringMap: Dict[str, int] = field(default_factory=dict)
- stackTable: List[Stack] = field(default_factory=list)
- stackMap: Dict[Tuple[Optional[int], int], int] = field(default_factory=dict)
- frameMap: Dict[str, int] = field(default_factory=dict)
- """
- comm: str
- pid: int
- tid: int
- samples: List[Sample] = field(default_factory=list)
- frameTable: List[Frame] = field(default_factory=list)
- stringTable: List[str] = field(default_factory=list)
- stringMap: Dict[str, int] = field(default_factory=dict)
- stackTable: List[Stack] = field(default_factory=list)
- stackMap: Dict[Tuple[Optional[int], int], int] = field(default_factory=dict)
- frameMap: Dict[str, int] = field(default_factory=dict)
-
- def _intern_stack(self, frame_id: int, prefix_id: Optional[int]) -> int:
- """Gets a matching stack, or saves the new stack. Returns a Stack ID."""
- key = f"{frame_id}" if prefix_id is None else f"{frame_id},{prefix_id}"
- # key = (prefix_id, frame_id)
- stack_id = self.stackMap.get(key)
- if stack_id is None:
- # return stack_id
- stack_id = len(self.stackTable)
- self.stackTable.append(Stack(prefix_id=prefix_id, frame_id=frame_id))
- self.stackMap[key] = stack_id
- return stack_id
-
- def _intern_string(self, string: str) -> int:
- """Gets a matching string, or saves the new string. Returns a String ID."""
- string_id = self.stringMap.get(string)
- if string_id is not None:
- return string_id
- string_id = len(self.stringTable)
- self.stringTable.append(string)
- self.stringMap[string] = string_id
- return string_id
-
- def _intern_frame(self, frame_str: str) -> int:
- """Gets a matching stack frame, or saves the new frame. Returns a Frame ID."""
- frame_id = self.frameMap.get(frame_str)
- if frame_id is not None:
- return frame_id
- frame_id = len(self.frameTable)
- self.frameMap[frame_str] = frame_id
- string_id = self._intern_string(frame_str)
-
- symbol_name_to_category = KERNEL_CATEGORY_INDEX if frame_str.find('kallsyms') != -1 \
- or frame_str.find('/vmlinux') != -1 \
- or frame_str.endswith('.ko)') \
- else USER_CATEGORY_INDEX
-
- self.frameTable.append(Frame(
- string_id=string_id,
- relevantForJS=False,
- innerWindowID=0,
- implementation=None,
- optimizations=None,
- line=None,
- column=None,
- category=symbol_name_to_category,
- subcategory=None,
- ))
- return frame_id
-
- def _add_sample(self, comm: str, stack: List[str], time_ms: Milliseconds) -> None:
- """Add a timestamped stack trace sample to the thread builder.
- Args:
- comm: command-line (name) of the thread at this sample
- stack: sampled stack frames. Root first, leaf last.
- time_ms: timestamp of sample in milliseconds.
- """
- # Ihreads may not set their names right after they are created.
- # Instead, they might do it later. In such situations, to use the latest name they have set.
- if self.comm != comm:
- self.comm = comm
-
- prefix_stack_id = reduce(lambda prefix_id, frame: self._intern_stack
- (self._intern_frame(frame), prefix_id), stack, None)
- if prefix_stack_id is not None:
- self.samples.append(Sample(stack_id=prefix_stack_id,
- time_ms=time_ms,
- responsiveness=0))
-
- def _to_json_dict(self) -> Dict:
- """Converts current Thread to GeckoThread JSON format."""
- # Gecko profile format is row-oriented data as List[List],
- # And a schema for interpreting each index.
- # Schema:
- # https://github.com/firefox-devtools/profiler/blob/main/docs-developer/gecko-profile-format.md
- # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L230
- return {
- "tid": self.tid,
- "pid": self.pid,
- "name": self.comm,
- # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L51
- "markers": {
- "schema": {
- "name": 0,
- "startTime": 1,
- "endTime": 2,
- "phase": 3,
- "category": 4,
- "data": 5,
- },
- "data": [],
- },
-
- # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L90
- "samples": {
- "schema": {
- "stack": 0,
- "time": 1,
- "responsiveness": 2,
- },
- "data": self.samples
- },
-
- # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L156
- "frameTable": {
- "schema": {
- "location": 0,
- "relevantForJS": 1,
- "innerWindowID": 2,
- "implementation": 3,
- "optimizations": 4,
- "line": 5,
- "column": 6,
- "category": 7,
- "subcategory": 8,
- },
- "data": self.frameTable,
- },
-
- # https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L216
- "stackTable": {
- "schema": {
- "prefix": 0,
- "frame": 1,
- },
- "data": self.stackTable,
- },
- "stringTable": self.stringTable,
- "registerTime": 0,
- "unregisterTime": None,
- "processType": "default",
- }
-
-# Uses perf script python interface to parse each
-# event and store the data in the thread builder.
-def process_event(param_dict: Dict) -> None:
- global start_time
- global tid_to_thread
- time_stamp = (param_dict['sample']['time'] // 1000) / 1000
- pid = param_dict['sample']['pid']
- tid = param_dict['sample']['tid']
- comm = param_dict['comm']
-
- # Start time is the time of the first sample
- if not start_time:
- start_time = time_stamp
-
- # Parse and append the callchain of the current sample into a stack.
- stack = []
- if param_dict['callchain']:
- for call in param_dict['callchain']:
- if 'sym' not in call:
- continue
- stack.append(f'{call["sym"]["name"]} (in {call["dso"]})')
- if len(stack) != 0:
- # Reverse the stack, as root come first and the leaf at the end.
- stack = stack[::-1]
-
- # During perf record if -g is not used, the callchain is not available.
- # In that case, the symbol and dso are available in the event parameters.
- else:
- func = param_dict['symbol'] if 'symbol' in param_dict else '[unknown]'
- dso = param_dict['dso'] if 'dso' in param_dict else '[unknown]'
- stack.append(f'{func} (in {dso})')
-
- # Add sample to the specific thread.
- thread = tid_to_thread.get(tid)
- if thread is None:
- thread = Thread(comm=comm, pid=pid, tid=tid)
- tid_to_thread[tid] = thread
- thread._add_sample(comm=comm, stack=stack, time_ms=time_stamp)
-
-def trace_begin() -> None:
- global output_file
- if (output_file is None):
- print("Staring Firefox Profiler on your default browser...")
- global http_server_thread
- http_server_thread = threading.Thread(target=test, args=(CORSRequestHandler, HTTPServer,))
- http_server_thread.daemon = True
- http_server_thread.start()
-
-# Trace_end runs at the end and will be used to aggregate
-# the data into the final json object and print it out to stdout.
-def trace_end() -> None:
- global output_file
- threads = [thread._to_json_dict() for thread in tid_to_thread.values()]
-
- # Schema: https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L305
- gecko_profile_with_meta = {
- "meta": {
- "interval": 1,
- "processType": 0,
- "product": PRODUCT,
- "stackwalk": 1,
- "debug": 0,
- "gcpoison": 0,
- "asyncstack": 1,
- "startTime": start_time,
- "shutdownTime": None,
- "version": 24,
- "presymbolicated": True,
- "categories": CATEGORIES,
- "markerSchema": [],
- },
- "libs": [],
- "threads": threads,
- "processes": [],
- "pausedRanges": [],
- }
- # launch the profiler on local host if not specified --save-only args, otherwise print to file
- if (output_file is None):
- output_file = 'gecko_profile.json'
- with open(output_file, 'w') as f:
- json.dump(gecko_profile_with_meta, f, indent=2)
- launchFirefox(output_file)
- time.sleep(1)
- print(f'[ perf gecko: Captured and wrote into {output_file} ]')
- else:
- print(f'[ perf gecko: Captured and wrote into {output_file} ]')
- with open(output_file, 'w') as f:
- json.dump(gecko_profile_with_meta, f, indent=2)
-
-# Used to enable Cross-Origin Resource Sharing (CORS) for requests coming from 'https://profiler.firefox.com', allowing it to access resources from this server.
-class CORSRequestHandler(SimpleHTTPRequestHandler):
- def end_headers (self):
- self.send_header('Access-Control-Allow-Origin', 'https://profiler.firefox.com')
- SimpleHTTPRequestHandler.end_headers(self)
-
-# start a local server to serve the gecko_profile.json file to the profiler.firefox.com
-def launchFirefox(file):
- safe_string = urllib.parse.quote_plus(f'http://localhost:8000/{file}')
- url = 'https://profiler.firefox.com/from-url/' + safe_string
- webbrowser.open(f'{url}')
-
-def main() -> None:
- global output_file
- global CATEGORIES
- parser = argparse.ArgumentParser(description="Convert perf.data to Firefox\'s Gecko Profile format which can be uploaded to profiler.firefox.com for visualization")
-
- # Add the command-line options
- # Colors must be defined according to this:
- # https://github.com/firefox-devtools/profiler/blob/50124adbfa488adba6e2674a8f2618cf34b59cd2/res/css/categories.css
- parser.add_argument('--user-color', default='yellow', help='Color for the User category', choices=['yellow', 'blue', 'purple', 'green', 'orange', 'red', 'grey', 'magenta'])
- parser.add_argument('--kernel-color', default='orange', help='Color for the Kernel category', choices=['yellow', 'blue', 'purple', 'green', 'orange', 'red', 'grey', 'magenta'])
- # If --save-only is specified, the output will be saved to a file instead of opening Firefox's profiler directly.
- parser.add_argument('--save-only', help='Save the output to a file instead of opening Firefox\'s profiler')
-
- # Parse the command-line arguments
- args = parser.parse_args()
- # Access the values provided by the user
- user_color = args.user_color
- kernel_color = args.kernel_color
- output_file = args.save_only
-
- CATEGORIES = [
- {
- "name": 'User',
- "color": user_color,
- "subcategories": ['Other']
- },
- {
- "name": 'Kernel',
- "color": kernel_color,
- "subcategories": ['Other']
- },
- ]
-
-if __name__ == '__main__':
- main()
diff --git a/tools/perf/scripts/python/intel-pt-events.py b/tools/perf/scripts/python/intel-pt-events.py
deleted file mode 100644
index 346c89bd16d6..000000000000
--- a/tools/perf/scripts/python/intel-pt-events.py
+++ /dev/null
@@ -1,494 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# intel-pt-events.py: Print Intel PT Events including Power Events and PTWRITE
-# Copyright (c) 2017-2021, Intel Corporation.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms and conditions of the GNU General Public License,
-# version 2, as published by the Free Software Foundation.
-#
-# This program is distributed in the hope it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-
-from __future__ import division, print_function
-
-import io
-import os
-import sys
-import struct
-import argparse
-import contextlib
-
-from libxed import LibXED
-from ctypes import create_string_buffer, addressof
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import perf_set_itrace_options, \
- perf_sample_insn, perf_sample_srccode
-
-try:
- broken_pipe_exception = BrokenPipeError
-except:
- broken_pipe_exception = IOError
-
-glb_switch_str = {}
-glb_insn = False
-glb_disassembler = None
-glb_src = False
-glb_source_file_name = None
-glb_line_number = None
-glb_dso = None
-glb_stash_dict = {}
-glb_output = None
-glb_output_pos = 0
-glb_cpu = -1
-glb_time = 0
-
-def get_optional_null(perf_dict, field):
- if field in perf_dict:
- return perf_dict[field]
- return ""
-
-def get_optional_zero(perf_dict, field):
- if field in perf_dict:
- return perf_dict[field]
- return 0
-
-def get_optional_bytes(perf_dict, field):
- if field in perf_dict:
- return perf_dict[field]
- return bytes()
-
-def get_optional(perf_dict, field):
- if field in perf_dict:
- return perf_dict[field]
- return "[unknown]"
-
-def get_offset(perf_dict, field):
- if field in perf_dict:
- return "+%#x" % perf_dict[field]
- return ""
-
-def trace_begin():
- ap = argparse.ArgumentParser(usage = "", add_help = False)
- ap.add_argument("--insn-trace", action='store_true')
- ap.add_argument("--src-trace", action='store_true')
- ap.add_argument("--all-switch-events", action='store_true')
- ap.add_argument("--interleave", type=int, nargs='?', const=4, default=0)
- global glb_args
- global glb_insn
- global glb_src
- glb_args = ap.parse_args()
- if glb_args.insn_trace:
- print("Intel PT Instruction Trace")
- itrace = "i0nsepwxI"
- glb_insn = True
- elif glb_args.src_trace:
- print("Intel PT Source Trace")
- itrace = "i0nsepwxI"
- glb_insn = True
- glb_src = True
- else:
- print("Intel PT Branch Trace, Power Events, Event Trace and PTWRITE")
- itrace = "bepwxI"
- global glb_disassembler
- try:
- glb_disassembler = LibXED()
- except:
- glb_disassembler = None
- perf_set_itrace_options(perf_script_context, itrace)
-
-def trace_end():
- if glb_args.interleave:
- flush_stashed_output()
- print("End")
-
-def trace_unhandled(event_name, context, event_fields_dict):
- print(' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]))
-
-def stash_output():
- global glb_stash_dict
- global glb_output_pos
- output_str = glb_output.getvalue()[glb_output_pos:]
- n = len(output_str)
- if n:
- glb_output_pos += n
- if glb_cpu not in glb_stash_dict:
- glb_stash_dict[glb_cpu] = []
- glb_stash_dict[glb_cpu].append(output_str)
-
-def flush_stashed_output():
- global glb_stash_dict
- while glb_stash_dict:
- cpus = list(glb_stash_dict.keys())
- # Output at most glb_args.interleave output strings per cpu
- for cpu in cpus:
- items = glb_stash_dict[cpu]
- countdown = glb_args.interleave
- while len(items) and countdown:
- sys.stdout.write(items[0])
- del items[0]
- countdown -= 1
- if not items:
- del glb_stash_dict[cpu]
-
-def print_ptwrite(raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- flags = data[0]
- payload = data[1]
- exact_ip = flags & 1
- try:
- s = payload.to_bytes(8, "little").decode("ascii").rstrip("\x00")
- if not s.isprintable():
- s = ""
- except:
- s = ""
- print("IP: %u payload: %#x" % (exact_ip, payload), s, end=' ')
-
-def print_cbr(raw_buf):
- data = struct.unpack_from("<BBBBII", raw_buf)
- cbr = data[0]
- f = (data[4] + 500) / 1000
- p = ((cbr * 1000 / data[2]) + 5) / 10
- print("%3u freq: %4u MHz (%3u%%)" % (cbr, f, p), end=' ')
-
-def print_mwait(raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- payload = data[1]
- hints = payload & 0xff
- extensions = (payload >> 32) & 0x3
- print("hints: %#x extensions: %#x" % (hints, extensions), end=' ')
-
-def print_pwre(raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- payload = data[1]
- hw = (payload >> 7) & 1
- cstate = (payload >> 12) & 0xf
- subcstate = (payload >> 8) & 0xf
- print("hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate),
- end=' ')
-
-def print_exstop(raw_buf):
- data = struct.unpack_from("<I", raw_buf)
- flags = data[0]
- exact_ip = flags & 1
- print("IP: %u" % (exact_ip), end=' ')
-
-def print_pwrx(raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- payload = data[1]
- deepest_cstate = payload & 0xf
- last_cstate = (payload >> 4) & 0xf
- wake_reason = (payload >> 8) & 0xf
- print("deepest cstate: %u last cstate: %u wake reason: %#x" %
- (deepest_cstate, last_cstate, wake_reason), end=' ')
-
-def print_psb(raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- offset = data[1]
- print("offset: %#x" % (offset), end=' ')
-
-glb_cfe = ["", "INTR", "IRET", "SMI", "RSM", "SIPI", "INIT", "VMENTRY", "VMEXIT",
- "VMEXIT_INTR", "SHUTDOWN", "", "UINT", "UIRET"] + [""] * 18
-glb_evd = ["", "PFA", "VMXQ", "VMXR"] + [""] * 60
-
-def print_evt(raw_buf):
- data = struct.unpack_from("<BBH", raw_buf)
- typ = data[0] & 0x1f
- ip_flag = (data[0] & 0x80) >> 7
- vector = data[1]
- evd_cnt = data[2]
- s = glb_cfe[typ]
- if s:
- print(" cfe: %s IP: %u vector: %u" % (s, ip_flag, vector), end=' ')
- else:
- print(" cfe: %u IP: %u vector: %u" % (typ, ip_flag, vector), end=' ')
- pos = 4
- for i in range(evd_cnt):
- data = struct.unpack_from("<QQ", raw_buf)
- et = data[0] & 0x3f
- s = glb_evd[et]
- if s:
- print("%s: %#x" % (s, data[1]), end=' ')
- else:
- print("EVD_%u: %#x" % (et, data[1]), end=' ')
-
-def print_iflag(raw_buf):
- data = struct.unpack_from("<IQ", raw_buf)
- iflag = data[0] & 1
- old_iflag = iflag ^ 1
- via_branch = data[0] & 2
- branch_ip = data[1]
- if via_branch:
- s = "via"
- else:
- s = "non"
- print("IFLAG: %u->%u %s branch" % (old_iflag, iflag, s), end=' ')
-
-def common_start_str(comm, sample):
- ts = sample["time"]
- cpu = sample["cpu"]
- pid = sample["pid"]
- tid = sample["tid"]
- if "machine_pid" in sample:
- machine_pid = sample["machine_pid"]
- vcpu = sample["vcpu"]
- return "VM:%5d VCPU:%03d %16s %5u/%-5u [%03u] %9u.%09u " % (machine_pid, vcpu, comm, pid, tid, cpu, ts / 1000000000, ts %1000000000)
- else:
- return "%16s %5u/%-5u [%03u] %9u.%09u " % (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000)
-
-def print_common_start(comm, sample, name):
- flags_disp = get_optional_null(sample, "flags_disp")
- # Unused fields:
- # period = sample["period"]
- # phys_addr = sample["phys_addr"]
- # weight = sample["weight"]
- # transaction = sample["transaction"]
- # cpumode = get_optional_zero(sample, "cpumode")
- print(common_start_str(comm, sample) + "%8s %21s" % (name, flags_disp), end=' ')
-
-def print_instructions_start(comm, sample):
- if "x" in get_optional_null(sample, "flags"):
- print(common_start_str(comm, sample) + "x", end=' ')
- else:
- print(common_start_str(comm, sample), end=' ')
-
-def disassem(insn, ip):
- inst = glb_disassembler.Instruction()
- glb_disassembler.SetMode(inst, 0) # Assume 64-bit
- buf = create_string_buffer(64)
- buf.value = insn
- return glb_disassembler.DisassembleOne(inst, addressof(buf), len(insn), ip)
-
-def print_common_ip(param_dict, sample, symbol, dso):
- ip = sample["ip"]
- offs = get_offset(param_dict, "symoff")
- if "cyc_cnt" in sample:
- cyc_cnt = sample["cyc_cnt"]
- insn_cnt = get_optional_zero(sample, "insn_cnt")
- ipc_str = " IPC: %#.2f (%u/%u)" % (insn_cnt / cyc_cnt, insn_cnt, cyc_cnt)
- else:
- ipc_str = ""
- if glb_insn and glb_disassembler is not None:
- insn = perf_sample_insn(perf_script_context)
- if insn and len(insn):
- cnt, text = disassem(insn, ip)
- byte_str = ("%x" % ip).rjust(16)
- if sys.version_info.major >= 3:
- for k in range(cnt):
- byte_str += " %02x" % insn[k]
- else:
- for k in xrange(cnt):
- byte_str += " %02x" % ord(insn[k])
- print("%-40s %-30s" % (byte_str, text), end=' ')
- print("%s%s (%s)" % (symbol, offs, dso), end=' ')
- else:
- print("%16x %s%s (%s)" % (ip, symbol, offs, dso), end=' ')
- if "addr_correlates_sym" in sample:
- addr = sample["addr"]
- dso = get_optional(sample, "addr_dso")
- symbol = get_optional(sample, "addr_symbol")
- offs = get_offset(sample, "addr_symoff")
- print("=> %x %s%s (%s)%s" % (addr, symbol, offs, dso, ipc_str))
- else:
- print(ipc_str)
-
-def print_srccode(comm, param_dict, sample, symbol, dso, with_insn):
- ip = sample["ip"]
- if symbol == "[unknown]":
- start_str = common_start_str(comm, sample) + ("%x" % ip).rjust(16).ljust(40)
- else:
- offs = get_offset(param_dict, "symoff")
- start_str = common_start_str(comm, sample) + (symbol + offs).ljust(40)
-
- if with_insn and glb_insn and glb_disassembler is not None:
- insn = perf_sample_insn(perf_script_context)
- if insn and len(insn):
- cnt, text = disassem(insn, ip)
- start_str += text.ljust(30)
-
- global glb_source_file_name
- global glb_line_number
- global glb_dso
-
- source_file_name, line_number, source_line = perf_sample_srccode(perf_script_context)
- if source_file_name:
- if glb_line_number == line_number and glb_source_file_name == source_file_name:
- src_str = ""
- else:
- if len(source_file_name) > 40:
- src_file = ("..." + source_file_name[-37:]) + " "
- else:
- src_file = source_file_name.ljust(41)
- if source_line is None:
- src_str = src_file + str(line_number).rjust(4) + " "
- else:
- src_str = src_file + str(line_number).rjust(4) + " " + source_line
- glb_dso = None
- elif dso == glb_dso:
- src_str = ""
- else:
- src_str = dso
- glb_dso = dso
-
- glb_line_number = line_number
- glb_source_file_name = source_file_name
-
- print(start_str, src_str)
-
-def do_process_event(param_dict):
- sample = param_dict["sample"]
- raw_buf = param_dict["raw_buf"]
- comm = param_dict["comm"]
- name = param_dict["ev_name"]
- # Unused fields:
- # callchain = param_dict["callchain"]
- # brstack = param_dict["brstack"]
- # brstacksym = param_dict["brstacksym"]
- # event_attr = param_dict["attr"]
-
- # Symbol and dso info are not always resolved
- dso = get_optional(param_dict, "dso")
- symbol = get_optional(param_dict, "symbol")
-
- cpu = sample["cpu"]
- if cpu in glb_switch_str:
- print(glb_switch_str[cpu])
- del glb_switch_str[cpu]
-
- if name.startswith("instructions"):
- if glb_src:
- print_srccode(comm, param_dict, sample, symbol, dso, True)
- else:
- print_instructions_start(comm, sample)
- print_common_ip(param_dict, sample, symbol, dso)
- elif name.startswith("branches"):
- if glb_src:
- print_srccode(comm, param_dict, sample, symbol, dso, False)
- else:
- print_common_start(comm, sample, name)
- print_common_ip(param_dict, sample, symbol, dso)
- elif name == "ptwrite":
- print_common_start(comm, sample, name)
- print_ptwrite(raw_buf)
- print_common_ip(param_dict, sample, symbol, dso)
- elif name == "cbr":
- print_common_start(comm, sample, name)
- print_cbr(raw_buf)
- print_common_ip(param_dict, sample, symbol, dso)
- elif name == "mwait":
- print_common_start(comm, sample, name)
- print_mwait(raw_buf)
- print_common_ip(param_dict, sample, symbol, dso)
- elif name == "pwre":
- print_common_start(comm, sample, name)
- print_pwre(raw_buf)
- print_common_ip(param_dict, sample, symbol, dso)
- elif name == "exstop":
- print_common_start(comm, sample, name)
- print_exstop(raw_buf)
- print_common_ip(param_dict, sample, symbol, dso)
- elif name == "pwrx":
- print_common_start(comm, sample, name)
- print_pwrx(raw_buf)
- print_common_ip(param_dict, sample, symbol, dso)
- elif name == "psb":
- print_common_start(comm, sample, name)
- print_psb(raw_buf)
- print_common_ip(param_dict, sample, symbol, dso)
- elif name == "evt":
- print_common_start(comm, sample, name)
- print_evt(raw_buf)
- print_common_ip(param_dict, sample, symbol, dso)
- elif name == "iflag":
- print_common_start(comm, sample, name)
- print_iflag(raw_buf)
- print_common_ip(param_dict, sample, symbol, dso)
- else:
- print_common_start(comm, sample, name)
- print_common_ip(param_dict, sample, symbol, dso)
-
-def interleave_events(param_dict):
- global glb_cpu
- global glb_time
- global glb_output
- global glb_output_pos
-
- sample = param_dict["sample"]
- glb_cpu = sample["cpu"]
- ts = sample["time"]
-
- if glb_time != ts:
- glb_time = ts
- flush_stashed_output()
-
- glb_output_pos = 0
- with contextlib.redirect_stdout(io.StringIO()) as glb_output:
- do_process_event(param_dict)
-
- stash_output()
-
-def process_event(param_dict):
- try:
- if glb_args.interleave:
- interleave_events(param_dict)
- else:
- do_process_event(param_dict)
- except broken_pipe_exception:
- # Stop python printing broken pipe errors and traceback
- sys.stdout = open(os.devnull, 'w')
- sys.exit(1)
-
-def auxtrace_error(typ, code, cpu, pid, tid, ip, ts, msg, cpumode, *x):
- if glb_args.interleave:
- flush_stashed_output()
- if len(x) >= 2 and x[0]:
- machine_pid = x[0]
- vcpu = x[1]
- else:
- machine_pid = 0
- vcpu = -1
- try:
- if machine_pid:
- print("VM:%5d VCPU:%03d %16s %5u/%-5u [%03u] %9u.%09u error type %u code %u: %s ip 0x%16x" %
- (machine_pid, vcpu, "Trace error", pid, tid, cpu, ts / 1000000000, ts %1000000000, typ, code, msg, ip))
- else:
- print("%16s %5u/%-5u [%03u] %9u.%09u error type %u code %u: %s ip 0x%16x" %
- ("Trace error", pid, tid, cpu, ts / 1000000000, ts %1000000000, typ, code, msg, ip))
- except broken_pipe_exception:
- # Stop python printing broken pipe errors and traceback
- sys.stdout = open(os.devnull, 'w')
- sys.exit(1)
-
-def context_switch(ts, cpu, pid, tid, np_pid, np_tid, machine_pid, out, out_preempt, *x):
- if glb_args.interleave:
- flush_stashed_output()
- if out:
- out_str = "Switch out "
- else:
- out_str = "Switch In "
- if out_preempt:
- preempt_str = "preempt"
- else:
- preempt_str = ""
- if len(x) >= 2 and x[0]:
- machine_pid = x[0]
- vcpu = x[1]
- else:
- vcpu = None;
- if machine_pid == -1:
- machine_str = ""
- elif vcpu is None:
- machine_str = "machine PID %d" % machine_pid
- else:
- machine_str = "machine PID %d VCPU %d" % (machine_pid, vcpu)
- switch_str = "%16s %5d/%-5d [%03u] %9u.%09u %5d/%-5d %s %s" % \
- (out_str, pid, tid, cpu, ts / 1000000000, ts %1000000000, np_pid, np_tid, machine_str, preempt_str)
- if glb_args.all_switch_events:
- print(switch_str)
- else:
- global glb_switch_str
- glb_switch_str[cpu] = switch_str
diff --git a/tools/perf/scripts/python/libxed.py b/tools/perf/scripts/python/libxed.py
deleted file mode 100644
index 2c70a5a7eb9c..000000000000
--- a/tools/perf/scripts/python/libxed.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/usr/bin/env python
-# SPDX-License-Identifier: GPL-2.0
-# libxed.py: Python wrapper for libxed.so
-# Copyright (c) 2014-2021, Intel Corporation.
-
-# To use Intel XED, libxed.so must be present. To build and install
-# libxed.so:
-# git clone https://github.com/intelxed/mbuild.git mbuild
-# git clone https://github.com/intelxed/xed
-# cd xed
-# ./mfile.py --share
-# sudo ./mfile.py --prefix=/usr/local install
-# sudo ldconfig
-#
-
-import sys
-
-from ctypes import CDLL, Structure, create_string_buffer, addressof, sizeof, \
- c_void_p, c_bool, c_byte, c_char, c_int, c_uint, c_longlong, c_ulonglong
-
-# XED Disassembler
-
-class xed_state_t(Structure):
-
- _fields_ = [
- ("mode", c_int),
- ("width", c_int)
- ]
-
-class XEDInstruction():
-
- def __init__(self, libxed):
- # Current xed_decoded_inst_t structure is 192 bytes. Use 512 to allow for future expansion
- xedd_t = c_byte * 512
- self.xedd = xedd_t()
- self.xedp = addressof(self.xedd)
- libxed.xed_decoded_inst_zero(self.xedp)
- self.state = xed_state_t()
- self.statep = addressof(self.state)
- # Buffer for disassembled instruction text
- self.buffer = create_string_buffer(256)
- self.bufferp = addressof(self.buffer)
-
-class LibXED():
-
- def __init__(self):
- try:
- self.libxed = CDLL("libxed.so")
- except:
- self.libxed = None
- if not self.libxed:
- self.libxed = CDLL("/usr/local/lib/libxed.so")
-
- self.xed_tables_init = self.libxed.xed_tables_init
- self.xed_tables_init.restype = None
- self.xed_tables_init.argtypes = []
-
- self.xed_decoded_inst_zero = self.libxed.xed_decoded_inst_zero
- self.xed_decoded_inst_zero.restype = None
- self.xed_decoded_inst_zero.argtypes = [ c_void_p ]
-
- self.xed_operand_values_set_mode = self.libxed.xed_operand_values_set_mode
- self.xed_operand_values_set_mode.restype = None
- self.xed_operand_values_set_mode.argtypes = [ c_void_p, c_void_p ]
-
- self.xed_decoded_inst_zero_keep_mode = self.libxed.xed_decoded_inst_zero_keep_mode
- self.xed_decoded_inst_zero_keep_mode.restype = None
- self.xed_decoded_inst_zero_keep_mode.argtypes = [ c_void_p ]
-
- self.xed_decode = self.libxed.xed_decode
- self.xed_decode.restype = c_int
- self.xed_decode.argtypes = [ c_void_p, c_void_p, c_uint ]
-
- self.xed_format_context = self.libxed.xed_format_context
- self.xed_format_context.restype = c_uint
- self.xed_format_context.argtypes = [ c_int, c_void_p, c_void_p, c_int, c_ulonglong, c_void_p, c_void_p ]
-
- self.xed_tables_init()
-
- def Instruction(self):
- return XEDInstruction(self)
-
- def SetMode(self, inst, mode):
- if mode:
- inst.state.mode = 4 # 32-bit
- inst.state.width = 4 # 4 bytes
- else:
- inst.state.mode = 1 # 64-bit
- inst.state.width = 8 # 8 bytes
- self.xed_operand_values_set_mode(inst.xedp, inst.statep)
-
- def DisassembleOne(self, inst, bytes_ptr, bytes_cnt, ip):
- self.xed_decoded_inst_zero_keep_mode(inst.xedp)
- err = self.xed_decode(inst.xedp, bytes_ptr, bytes_cnt)
- if err:
- return 0, ""
- # Use AT&T mode (2), alternative is Intel (3)
- ok = self.xed_format_context(2, inst.xedp, inst.bufferp, sizeof(inst.buffer), ip, 0, 0)
- if not ok:
- return 0, ""
- if sys.version_info[0] == 2:
- result = inst.buffer.value
- else:
- result = inst.buffer.value.decode()
- # Return instruction length and the disassembled instruction text
- # For now, assume the length is in byte 166
- return inst.xedd[166], result
diff --git a/tools/perf/scripts/python/mem-phys-addr.py b/tools/perf/scripts/python/mem-phys-addr.py
deleted file mode 100644
index 5e237a5a5f1b..000000000000
--- a/tools/perf/scripts/python/mem-phys-addr.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# mem-phys-addr.py: Resolve physical address samples
-# SPDX-License-Identifier: GPL-2.0
-#
-# Copyright (c) 2018, Intel Corporation.
-
-import os
-import sys
-import re
-import bisect
-import collections
-from dataclasses import dataclass
-from typing import (Dict, Optional)
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-@dataclass(frozen=True)
-class IomemEntry:
- """Read from a line in /proc/iomem"""
- begin: int
- end: int
- indent: int
- label: str
-
-# Physical memory layout from /proc/iomem. Key is the indent and then
-# a list of ranges.
-iomem: Dict[int, list[IomemEntry]] = collections.defaultdict(list)
-# Child nodes from the iomem parent.
-children: Dict[IomemEntry, set[IomemEntry]] = collections.defaultdict(set)
-# Maximum indent seen before an entry in the iomem file.
-max_indent: int = 0
-# Count for each range of memory.
-load_mem_type_cnt: Dict[IomemEntry, int] = collections.Counter()
-# Perf event name set from the first sample in the data.
-event_name: Optional[str] = None
-
-def parse_iomem():
- """Populate iomem from /proc/iomem file"""
- global iomem
- global max_indent
- global children
- with open('/proc/iomem', 'r', encoding='ascii') as f:
- for line in f:
- indent = 0
- while line[indent] == ' ':
- indent += 1
- if indent > max_indent:
- max_indent = indent
- m = re.split('-|:', line, 2)
- begin = int(m[0], 16)
- end = int(m[1], 16)
- label = m[2].strip()
- entry = IomemEntry(begin, end, indent, label)
- # Before adding entry, search for a parent node using its begin.
- if indent > 0:
- parent = find_memory_type(begin)
- assert parent, f"Given indent expected a parent for {label}"
- children[parent].add(entry)
- iomem[indent].append(entry)
-
-def find_memory_type(phys_addr) -> Optional[IomemEntry]:
- """Search iomem for the range containing phys_addr with the maximum indent"""
- for i in range(max_indent, -1, -1):
- if i not in iomem:
- continue
- position = bisect.bisect_right(iomem[i], phys_addr,
- key=lambda entry: entry.begin)
- if position is None:
- continue
- iomem_entry = iomem[i][position-1]
- if iomem_entry.begin <= phys_addr <= iomem_entry.end:
- return iomem_entry
- print(f"Didn't find {phys_addr}")
- return None
-
-def print_memory_type():
- print(f"Event: {event_name}")
- print(f"{'Memory type':<40} {'count':>10} {'percentage':>10}")
- print(f"{'-' * 40:<40} {'-' * 10:>10} {'-' * 10:>10}")
- total = sum(load_mem_type_cnt.values())
- # Add count from children into the parent.
- for i in range(max_indent, -1, -1):
- if i not in iomem:
- continue
- for entry in iomem[i]:
- global children
- for child in children[entry]:
- if load_mem_type_cnt[child] > 0:
- load_mem_type_cnt[entry] += load_mem_type_cnt[child]
-
- def print_entries(entries):
- """Print counts from parents down to their children"""
- global children
- for entry in sorted(entries,
- key = lambda entry: load_mem_type_cnt[entry],
- reverse = True):
- count = load_mem_type_cnt[entry]
- if count > 0:
- mem_type = ' ' * entry.indent + f"{entry.begin:x}-{entry.end:x} : {entry.label}"
- percent = 100 * count / total
- print(f"{mem_type:<40} {count:>10} {percent:>10.1f}")
- print_entries(children[entry])
-
- print_entries(iomem[0])
-
-def trace_begin():
- parse_iomem()
-
-def trace_end():
- print_memory_type()
-
-def process_event(param_dict):
- if "sample" not in param_dict:
- return
-
- sample = param_dict["sample"]
- if "phys_addr" not in sample:
- return
-
- phys_addr = sample["phys_addr"]
- entry = find_memory_type(phys_addr)
- if entry:
- load_mem_type_cnt[entry] += 1
-
- global event_name
- if event_name is None:
- event_name = param_dict["ev_name"]
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
deleted file mode 100755
index a97e7a6e0940..000000000000
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Monitor the system for dropped packets and proudce a report of drop locations and counts
-# SPDX-License-Identifier: GPL-2.0
-
-from __future__ import print_function
-
-import os
-import sys
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-from Util import *
-
-drop_log = {}
-kallsyms = []
-
-def get_kallsyms_table():
- global kallsyms
-
- try:
- f = open("/proc/kallsyms", "r")
- except:
- return
-
- for line in f:
- loc = int(line.split()[0], 16)
- name = line.split()[2]
- kallsyms.append((loc, name))
- kallsyms.sort()
-
-def get_sym(sloc):
- loc = int(sloc)
-
- # Invariant: kallsyms[i][0] <= loc for all 0 <= i <= start
- # kallsyms[i][0] > loc for all end <= i < len(kallsyms)
- start, end = -1, len(kallsyms)
- while end != start + 1:
- pivot = (start + end) // 2
- if loc < kallsyms[pivot][0]:
- end = pivot
- else:
- start = pivot
-
- # Now (start == -1 or kallsyms[start][0] <= loc)
- # and (start == len(kallsyms) - 1 or loc < kallsyms[start + 1][0])
- if start >= 0:
- symloc, name = kallsyms[start]
- return (name, loc - symloc)
- else:
- return (None, 0)
-
-def print_drop_table():
- print("%25s %25s %25s" % ("LOCATION", "OFFSET", "COUNT"))
- for i in drop_log.keys():
- (sym, off) = get_sym(i)
- if sym == None:
- sym = i
- print("%25s %25s %25s" % (sym, off, drop_log[i]))
-
-
-def trace_begin():
- print("Starting trace (Ctrl-C to dump results)")
-
-def trace_end():
- print("Gathering kallsyms data")
- get_kallsyms_table()
- print_drop_table()
-
-# called from perf, when it finds a corresponding event
-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
- skbaddr, location, protocol, reason):
- slocation = str(location)
- try:
- drop_log[slocation] = drop_log[slocation] + 1
- except:
- drop_log[slocation] = 1
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
deleted file mode 100644
index 30c4bccee5b2..000000000000
--- a/tools/perf/scripts/python/netdev-times.py
+++ /dev/null
@@ -1,473 +0,0 @@
-# Display a process of packets and processed time.
-# SPDX-License-Identifier: GPL-2.0
-# It helps us to investigate networking or network device.
-#
-# options
-# tx: show only tx chart
-# rx: show only rx chart
-# dev=: show only thing related to specified device
-# debug: work with debug mode. It shows buffer status.
-
-from __future__ import print_function
-
-import os
-import sys
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-from Util import *
-from functools import cmp_to_key
-
-all_event_list = []; # insert all tracepoint event related with this script
-irq_dic = {}; # key is cpu and value is a list which stacks irqs
- # which raise NET_RX softirq
-net_rx_dic = {}; # key is cpu and value include time of NET_RX softirq-entry
- # and a list which stacks receive
-receive_hunk_list = []; # a list which include a sequence of receive events
-rx_skb_list = []; # received packet list for matching
- # skb_copy_datagram_iovec
-
-buffer_budget = 65536; # the budget of rx_skb_list, tx_queue_list and
- # tx_xmit_list
-of_count_rx_skb_list = 0; # overflow count
-
-tx_queue_list = []; # list of packets which pass through dev_queue_xmit
-of_count_tx_queue_list = 0; # overflow count
-
-tx_xmit_list = []; # list of packets which pass through dev_hard_start_xmit
-of_count_tx_xmit_list = 0; # overflow count
-
-tx_free_list = []; # list of packets which is freed
-
-# options
-show_tx = 0;
-show_rx = 0;
-dev = 0; # store a name of device specified by option "dev="
-debug = 0;
-
-# indices of event_info tuple
-EINFO_IDX_NAME= 0
-EINFO_IDX_CONTEXT=1
-EINFO_IDX_CPU= 2
-EINFO_IDX_TIME= 3
-EINFO_IDX_PID= 4
-EINFO_IDX_COMM= 5
-
-# Calculate a time interval(msec) from src(nsec) to dst(nsec)
-def diff_msec(src, dst):
- return (dst - src) / 1000000.0
-
-# Display a process of transmitting a packet
-def print_transmit(hunk):
- if dev != 0 and hunk['dev'].find(dev) < 0:
- return
- print("%7s %5d %6d.%06dsec %12.3fmsec %12.3fmsec" %
- (hunk['dev'], hunk['len'],
- nsecs_secs(hunk['queue_t']),
- nsecs_nsecs(hunk['queue_t'])/1000,
- diff_msec(hunk['queue_t'], hunk['xmit_t']),
- diff_msec(hunk['xmit_t'], hunk['free_t'])))
-
-# Format for displaying rx packet processing
-PF_IRQ_ENTRY= " irq_entry(+%.3fmsec irq=%d:%s)"
-PF_SOFT_ENTRY=" softirq_entry(+%.3fmsec)"
-PF_NAPI_POLL= " napi_poll_exit(+%.3fmsec %s)"
-PF_JOINT= " |"
-PF_WJOINT= " | |"
-PF_NET_RECV= " |---netif_receive_skb(+%.3fmsec skb=%x len=%d)"
-PF_NET_RX= " |---netif_rx(+%.3fmsec skb=%x)"
-PF_CPY_DGRAM= " | skb_copy_datagram_iovec(+%.3fmsec %d:%s)"
-PF_KFREE_SKB= " | kfree_skb(+%.3fmsec location=%x)"
-PF_CONS_SKB= " | consume_skb(+%.3fmsec)"
-
-# Display a process of received packets and interrputs associated with
-# a NET_RX softirq
-def print_receive(hunk):
- show_hunk = 0
- irq_list = hunk['irq_list']
- cpu = irq_list[0]['cpu']
- base_t = irq_list[0]['irq_ent_t']
- # check if this hunk should be showed
- if dev != 0:
- for i in range(len(irq_list)):
- if irq_list[i]['name'].find(dev) >= 0:
- show_hunk = 1
- break
- else:
- show_hunk = 1
- if show_hunk == 0:
- return
-
- print("%d.%06dsec cpu=%d" %
- (nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu))
- for i in range(len(irq_list)):
- print(PF_IRQ_ENTRY %
- (diff_msec(base_t, irq_list[i]['irq_ent_t']),
- irq_list[i]['irq'], irq_list[i]['name']))
- print(PF_JOINT)
- irq_event_list = irq_list[i]['event_list']
- for j in range(len(irq_event_list)):
- irq_event = irq_event_list[j]
- if irq_event['event'] == 'netif_rx':
- print(PF_NET_RX %
- (diff_msec(base_t, irq_event['time']),
- irq_event['skbaddr']))
- print(PF_JOINT)
- print(PF_SOFT_ENTRY %
- diff_msec(base_t, hunk['sirq_ent_t']))
- print(PF_JOINT)
- event_list = hunk['event_list']
- for i in range(len(event_list)):
- event = event_list[i]
- if event['event_name'] == 'napi_poll':
- print(PF_NAPI_POLL %
- (diff_msec(base_t, event['event_t']),
- event['dev']))
- if i == len(event_list) - 1:
- print("")
- else:
- print(PF_JOINT)
- else:
- print(PF_NET_RECV %
- (diff_msec(base_t, event['event_t']),
- event['skbaddr'],
- event['len']))
- if 'comm' in event.keys():
- print(PF_WJOINT)
- print(PF_CPY_DGRAM %
- (diff_msec(base_t, event['comm_t']),
- event['pid'], event['comm']))
- elif 'handle' in event.keys():
- print(PF_WJOINT)
- if event['handle'] == "kfree_skb":
- print(PF_KFREE_SKB %
- (diff_msec(base_t,
- event['comm_t']),
- event['location']))
- elif event['handle'] == "consume_skb":
- print(PF_CONS_SKB %
- diff_msec(base_t,
- event['comm_t']))
- print(PF_JOINT)
-
-def trace_begin():
- global show_tx
- global show_rx
- global dev
- global debug
-
- for i in range(len(sys.argv)):
- if i == 0:
- continue
- arg = sys.argv[i]
- if arg == 'tx':
- show_tx = 1
- elif arg =='rx':
- show_rx = 1
- elif arg.find('dev=',0, 4) >= 0:
- dev = arg[4:]
- elif arg == 'debug':
- debug = 1
- if show_tx == 0 and show_rx == 0:
- show_tx = 1
- show_rx = 1
-
-def trace_end():
- # order all events in time
- all_event_list.sort(key=cmp_to_key(lambda a,b :a[EINFO_IDX_TIME] < b[EINFO_IDX_TIME]))
- # process all events
- for i in range(len(all_event_list)):
- event_info = all_event_list[i]
- name = event_info[EINFO_IDX_NAME]
- if name == 'irq__softirq_exit':
- handle_irq_softirq_exit(event_info)
- elif name == 'irq__softirq_entry':
- handle_irq_softirq_entry(event_info)
- elif name == 'irq__softirq_raise':
- handle_irq_softirq_raise(event_info)
- elif name == 'irq__irq_handler_entry':
- handle_irq_handler_entry(event_info)
- elif name == 'irq__irq_handler_exit':
- handle_irq_handler_exit(event_info)
- elif name == 'napi__napi_poll':
- handle_napi_poll(event_info)
- elif name == 'net__netif_receive_skb':
- handle_netif_receive_skb(event_info)
- elif name == 'net__netif_rx':
- handle_netif_rx(event_info)
- elif name == 'skb__skb_copy_datagram_iovec':
- handle_skb_copy_datagram_iovec(event_info)
- elif name == 'net__net_dev_queue':
- handle_net_dev_queue(event_info)
- elif name == 'net__net_dev_xmit':
- handle_net_dev_xmit(event_info)
- elif name == 'skb__kfree_skb':
- handle_kfree_skb(event_info)
- elif name == 'skb__consume_skb':
- handle_consume_skb(event_info)
- # display receive hunks
- if show_rx:
- for i in range(len(receive_hunk_list)):
- print_receive(receive_hunk_list[i])
- # display transmit hunks
- if show_tx:
- print(" dev len Qdisc "
- " netdevice free")
- for i in range(len(tx_free_list)):
- print_transmit(tx_free_list[i])
- if debug:
- print("debug buffer status")
- print("----------------------------")
- print("xmit Qdisc:remain:%d overflow:%d" %
- (len(tx_queue_list), of_count_tx_queue_list))
- print("xmit netdevice:remain:%d overflow:%d" %
- (len(tx_xmit_list), of_count_tx_xmit_list))
- print("receive:remain:%d overflow:%d" %
- (len(rx_skb_list), of_count_rx_skb_list))
-
-# called from perf, when it finds a correspoinding event
-def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
- if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
- return
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
- all_event_list.append(event_info)
-
-def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
- if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
- return
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
- all_event_list.append(event_info)
-
-def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
- if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
- return
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
- all_event_list.append(event_info)
-
-def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
- callchain, irq, irq_name):
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
- irq, irq_name)
- all_event_list.append(event_info)
-
-def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret):
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
- all_event_list.append(event_info)
-
-def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi,
- dev_name, work=None, budget=None):
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
- napi, dev_name, work, budget)
- all_event_list.append(event_info)
-
-def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
- skblen, dev_name):
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
- skbaddr, skblen, dev_name)
- all_event_list.append(event_info)
-
-def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
- skblen, dev_name):
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
- skbaddr, skblen, dev_name)
- all_event_list.append(event_info)
-
-def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain,
- skbaddr, skblen, dev_name):
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
- skbaddr, skblen, dev_name)
- all_event_list.append(event_info)
-
-def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain,
- skbaddr, skblen, rc, dev_name):
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
- skbaddr, skblen, rc ,dev_name)
- all_event_list.append(event_info)
-
-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
- skbaddr, location, protocol, reason):
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
- skbaddr, location, protocol, reason)
- all_event_list.append(event_info)
-
-def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
- skbaddr, location):
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
- skbaddr)
- all_event_list.append(event_info)
-
-def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain,
- skbaddr, skblen):
- event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
- skbaddr, skblen)
- all_event_list.append(event_info)
-
-def handle_irq_handler_entry(event_info):
- (name, context, cpu, time, pid, comm, irq, irq_name) = event_info
- if cpu not in irq_dic.keys():
- irq_dic[cpu] = []
- irq_record = {'irq':irq, 'name':irq_name, 'cpu':cpu, 'irq_ent_t':time}
- irq_dic[cpu].append(irq_record)
-
-def handle_irq_handler_exit(event_info):
- (name, context, cpu, time, pid, comm, irq, ret) = event_info
- if cpu not in irq_dic.keys():
- return
- irq_record = irq_dic[cpu].pop()
- if irq != irq_record['irq']:
- return
- irq_record.update({'irq_ext_t':time})
- # if an irq doesn't include NET_RX softirq, drop.
- if 'event_list' in irq_record.keys():
- irq_dic[cpu].append(irq_record)
-
-def handle_irq_softirq_raise(event_info):
- (name, context, cpu, time, pid, comm, vec) = event_info
- if cpu not in irq_dic.keys() \
- or len(irq_dic[cpu]) == 0:
- return
- irq_record = irq_dic[cpu].pop()
- if 'event_list' in irq_record.keys():
- irq_event_list = irq_record['event_list']
- else:
- irq_event_list = []
- irq_event_list.append({'time':time, 'event':'sirq_raise'})
- irq_record.update({'event_list':irq_event_list})
- irq_dic[cpu].append(irq_record)
-
-def handle_irq_softirq_entry(event_info):
- (name, context, cpu, time, pid, comm, vec) = event_info
- net_rx_dic[cpu] = {'sirq_ent_t':time, 'event_list':[]}
-
-def handle_irq_softirq_exit(event_info):
- (name, context, cpu, time, pid, comm, vec) = event_info
- irq_list = []
- event_list = 0
- if cpu in irq_dic.keys():
- irq_list = irq_dic[cpu]
- del irq_dic[cpu]
- if cpu in net_rx_dic.keys():
- sirq_ent_t = net_rx_dic[cpu]['sirq_ent_t']
- event_list = net_rx_dic[cpu]['event_list']
- del net_rx_dic[cpu]
- if irq_list == [] or event_list == 0:
- return
- rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time,
- 'irq_list':irq_list, 'event_list':event_list}
- # merge information related to a NET_RX softirq
- receive_hunk_list.append(rec_data)
-
-def handle_napi_poll(event_info):
- (name, context, cpu, time, pid, comm, napi, dev_name,
- work, budget) = event_info
- if cpu in net_rx_dic.keys():
- event_list = net_rx_dic[cpu]['event_list']
- rec_data = {'event_name':'napi_poll',
- 'dev':dev_name, 'event_t':time,
- 'work':work, 'budget':budget}
- event_list.append(rec_data)
-
-def handle_netif_rx(event_info):
- (name, context, cpu, time, pid, comm,
- skbaddr, skblen, dev_name) = event_info
- if cpu not in irq_dic.keys() \
- or len(irq_dic[cpu]) == 0:
- return
- irq_record = irq_dic[cpu].pop()
- if 'event_list' in irq_record.keys():
- irq_event_list = irq_record['event_list']
- else:
- irq_event_list = []
- irq_event_list.append({'time':time, 'event':'netif_rx',
- 'skbaddr':skbaddr, 'skblen':skblen, 'dev_name':dev_name})
- irq_record.update({'event_list':irq_event_list})
- irq_dic[cpu].append(irq_record)
-
-def handle_netif_receive_skb(event_info):
- global of_count_rx_skb_list
-
- (name, context, cpu, time, pid, comm,
- skbaddr, skblen, dev_name) = event_info
- if cpu in net_rx_dic.keys():
- rec_data = {'event_name':'netif_receive_skb',
- 'event_t':time, 'skbaddr':skbaddr, 'len':skblen}
- event_list = net_rx_dic[cpu]['event_list']
- event_list.append(rec_data)
- rx_skb_list.insert(0, rec_data)
- if len(rx_skb_list) > buffer_budget:
- rx_skb_list.pop()
- of_count_rx_skb_list += 1
-
-def handle_net_dev_queue(event_info):
- global of_count_tx_queue_list
-
- (name, context, cpu, time, pid, comm,
- skbaddr, skblen, dev_name) = event_info
- skb = {'dev':dev_name, 'skbaddr':skbaddr, 'len':skblen, 'queue_t':time}
- tx_queue_list.insert(0, skb)
- if len(tx_queue_list) > buffer_budget:
- tx_queue_list.pop()
- of_count_tx_queue_list += 1
-
-def handle_net_dev_xmit(event_info):
- global of_count_tx_xmit_list
-
- (name, context, cpu, time, pid, comm,
- skbaddr, skblen, rc, dev_name) = event_info
- if rc == 0: # NETDEV_TX_OK
- for i in range(len(tx_queue_list)):
- skb = tx_queue_list[i]
- if skb['skbaddr'] == skbaddr:
- skb['xmit_t'] = time
- tx_xmit_list.insert(0, skb)
- del tx_queue_list[i]
- if len(tx_xmit_list) > buffer_budget:
- tx_xmit_list.pop()
- of_count_tx_xmit_list += 1
- return
-
-def handle_kfree_skb(event_info):
- (name, context, cpu, time, pid, comm,
- skbaddr, location, protocol, reason) = event_info
- for i in range(len(tx_queue_list)):
- skb = tx_queue_list[i]
- if skb['skbaddr'] == skbaddr:
- del tx_queue_list[i]
- return
- for i in range(len(tx_xmit_list)):
- skb = tx_xmit_list[i]
- if skb['skbaddr'] == skbaddr:
- skb['free_t'] = time
- tx_free_list.append(skb)
- del tx_xmit_list[i]
- return
- for i in range(len(rx_skb_list)):
- rec_data = rx_skb_list[i]
- if rec_data['skbaddr'] == skbaddr:
- rec_data.update({'handle':"kfree_skb",
- 'comm':comm, 'pid':pid, 'comm_t':time})
- del rx_skb_list[i]
- return
-
-def handle_consume_skb(event_info):
- (name, context, cpu, time, pid, comm, skbaddr) = event_info
- for i in range(len(tx_xmit_list)):
- skb = tx_xmit_list[i]
- if skb['skbaddr'] == skbaddr:
- skb['free_t'] = time
- tx_free_list.append(skb)
- del tx_xmit_list[i]
- return
-
-def handle_skb_copy_datagram_iovec(event_info):
- (name, context, cpu, time, pid, comm, skbaddr, skblen) = event_info
- for i in range(len(rx_skb_list)):
- rec_data = rx_skb_list[i]
- if skbaddr == rec_data['skbaddr']:
- rec_data.update({'handle':"skb_copy_datagram_iovec",
- 'comm':comm, 'pid':pid, 'comm_t':time})
- del rx_skb_list[i]
- return
diff --git a/tools/perf/scripts/python/powerpc-hcalls.py b/tools/perf/scripts/python/powerpc-hcalls.py
deleted file mode 100644
index 8b78dc790adb..000000000000
--- a/tools/perf/scripts/python/powerpc-hcalls.py
+++ /dev/null
@@ -1,202 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0+
-#
-# Copyright (C) 2018 Ravi Bangoria, IBM Corporation
-#
-# Hypervisor call statisics
-
-from __future__ import print_function
-
-import os
-import sys
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-from Util import *
-
-# output: {
-# opcode: {
-# 'min': minimum time nsec
-# 'max': maximum time nsec
-# 'time': average time nsec
-# 'cnt': counter
-# } ...
-# }
-output = {}
-
-# d_enter: {
-# cpu: {
-# opcode: nsec
-# } ...
-# }
-d_enter = {}
-
-hcall_table = {
- 4: 'H_REMOVE',
- 8: 'H_ENTER',
- 12: 'H_READ',
- 16: 'H_CLEAR_MOD',
- 20: 'H_CLEAR_REF',
- 24: 'H_PROTECT',
- 28: 'H_GET_TCE',
- 32: 'H_PUT_TCE',
- 36: 'H_SET_SPRG0',
- 40: 'H_SET_DABR',
- 44: 'H_PAGE_INIT',
- 48: 'H_SET_ASR',
- 52: 'H_ASR_ON',
- 56: 'H_ASR_OFF',
- 60: 'H_LOGICAL_CI_LOAD',
- 64: 'H_LOGICAL_CI_STORE',
- 68: 'H_LOGICAL_CACHE_LOAD',
- 72: 'H_LOGICAL_CACHE_STORE',
- 76: 'H_LOGICAL_ICBI',
- 80: 'H_LOGICAL_DCBF',
- 84: 'H_GET_TERM_CHAR',
- 88: 'H_PUT_TERM_CHAR',
- 92: 'H_REAL_TO_LOGICAL',
- 96: 'H_HYPERVISOR_DATA',
- 100: 'H_EOI',
- 104: 'H_CPPR',
- 108: 'H_IPI',
- 112: 'H_IPOLL',
- 116: 'H_XIRR',
- 120: 'H_MIGRATE_DMA',
- 124: 'H_PERFMON',
- 220: 'H_REGISTER_VPA',
- 224: 'H_CEDE',
- 228: 'H_CONFER',
- 232: 'H_PROD',
- 236: 'H_GET_PPP',
- 240: 'H_SET_PPP',
- 244: 'H_PURR',
- 248: 'H_PIC',
- 252: 'H_REG_CRQ',
- 256: 'H_FREE_CRQ',
- 260: 'H_VIO_SIGNAL',
- 264: 'H_SEND_CRQ',
- 272: 'H_COPY_RDMA',
- 276: 'H_REGISTER_LOGICAL_LAN',
- 280: 'H_FREE_LOGICAL_LAN',
- 284: 'H_ADD_LOGICAL_LAN_BUFFER',
- 288: 'H_SEND_LOGICAL_LAN',
- 292: 'H_BULK_REMOVE',
- 304: 'H_MULTICAST_CTRL',
- 308: 'H_SET_XDABR',
- 312: 'H_STUFF_TCE',
- 316: 'H_PUT_TCE_INDIRECT',
- 332: 'H_CHANGE_LOGICAL_LAN_MAC',
- 336: 'H_VTERM_PARTNER_INFO',
- 340: 'H_REGISTER_VTERM',
- 344: 'H_FREE_VTERM',
- 348: 'H_RESET_EVENTS',
- 352: 'H_ALLOC_RESOURCE',
- 356: 'H_FREE_RESOURCE',
- 360: 'H_MODIFY_QP',
- 364: 'H_QUERY_QP',
- 368: 'H_REREGISTER_PMR',
- 372: 'H_REGISTER_SMR',
- 376: 'H_QUERY_MR',
- 380: 'H_QUERY_MW',
- 384: 'H_QUERY_HCA',
- 388: 'H_QUERY_PORT',
- 392: 'H_MODIFY_PORT',
- 396: 'H_DEFINE_AQP1',
- 400: 'H_GET_TRACE_BUFFER',
- 404: 'H_DEFINE_AQP0',
- 408: 'H_RESIZE_MR',
- 412: 'H_ATTACH_MCQP',
- 416: 'H_DETACH_MCQP',
- 420: 'H_CREATE_RPT',
- 424: 'H_REMOVE_RPT',
- 428: 'H_REGISTER_RPAGES',
- 432: 'H_DISABLE_AND_GETC',
- 436: 'H_ERROR_DATA',
- 440: 'H_GET_HCA_INFO',
- 444: 'H_GET_PERF_COUNT',
- 448: 'H_MANAGE_TRACE',
- 468: 'H_FREE_LOGICAL_LAN_BUFFER',
- 472: 'H_POLL_PENDING',
- 484: 'H_QUERY_INT_STATE',
- 580: 'H_ILLAN_ATTRIBUTES',
- 592: 'H_MODIFY_HEA_QP',
- 596: 'H_QUERY_HEA_QP',
- 600: 'H_QUERY_HEA',
- 604: 'H_QUERY_HEA_PORT',
- 608: 'H_MODIFY_HEA_PORT',
- 612: 'H_REG_BCMC',
- 616: 'H_DEREG_BCMC',
- 620: 'H_REGISTER_HEA_RPAGES',
- 624: 'H_DISABLE_AND_GET_HEA',
- 628: 'H_GET_HEA_INFO',
- 632: 'H_ALLOC_HEA_RESOURCE',
- 644: 'H_ADD_CONN',
- 648: 'H_DEL_CONN',
- 664: 'H_JOIN',
- 676: 'H_VASI_STATE',
- 688: 'H_ENABLE_CRQ',
- 696: 'H_GET_EM_PARMS',
- 720: 'H_SET_MPP',
- 724: 'H_GET_MPP',
- 748: 'H_HOME_NODE_ASSOCIATIVITY',
- 756: 'H_BEST_ENERGY',
- 764: 'H_XIRR_X',
- 768: 'H_RANDOM',
- 772: 'H_COP',
- 788: 'H_GET_MPP_X',
- 796: 'H_SET_MODE',
- 61440: 'H_RTAS',
-}
-
-def hcall_table_lookup(opcode):
- if (opcode in hcall_table):
- return hcall_table[opcode]
- else:
- return opcode
-
-print_ptrn = '%-28s%10s%10s%10s%10s'
-
-def trace_end():
- print(print_ptrn % ('hcall', 'count', 'min(ns)', 'max(ns)', 'avg(ns)'))
- print('-' * 68)
- for opcode in output:
- h_name = hcall_table_lookup(opcode)
- time = output[opcode]['time']
- cnt = output[opcode]['cnt']
- min_t = output[opcode]['min']
- max_t = output[opcode]['max']
-
- print(print_ptrn % (h_name, cnt, min_t, max_t, time//cnt))
-
-def powerpc__hcall_exit(name, context, cpu, sec, nsec, pid, comm, callchain,
- opcode, retval):
- if (cpu in d_enter and opcode in d_enter[cpu]):
- diff = nsecs(sec, nsec) - d_enter[cpu][opcode]
-
- if (opcode in output):
- output[opcode]['time'] += diff
- output[opcode]['cnt'] += 1
- if (output[opcode]['min'] > diff):
- output[opcode]['min'] = diff
- if (output[opcode]['max'] < diff):
- output[opcode]['max'] = diff
- else:
- output[opcode] = {
- 'time': diff,
- 'cnt': 1,
- 'min': diff,
- 'max': diff,
- }
-
- del d_enter[cpu][opcode]
-# else:
-# print("Can't find matching hcall_enter event. Ignoring sample")
-
-def powerpc__hcall_entry(event_name, context, cpu, sec, nsec, pid, comm,
- callchain, opcode):
- if (cpu in d_enter):
- d_enter[cpu][opcode] = nsecs(sec, nsec)
- else:
- d_enter[cpu] = {opcode: nsecs(sec, nsec)}
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
deleted file mode 100644
index 8196e3087c9e..000000000000
--- a/tools/perf/scripts/python/sched-migration.py
+++ /dev/null
@@ -1,462 +0,0 @@
-# Cpu task migration overview toy
-#
-# Copyright (C) 2010 Frederic Weisbecker <fweisbec@gmail.com>
-#
-# perf script event handlers have been generated by perf script -g python
-#
-# This software is distributed under the terms of the GNU General
-# Public License ("GPL") version 2 as published by the Free Software
-# Foundation.
-from __future__ import print_function
-
-import os
-import sys
-
-from collections import defaultdict
-try:
- from UserList import UserList
-except ImportError:
- # Python 3: UserList moved to the collections package
- from collections import UserList
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-sys.path.append('scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-from SchedGui import *
-
-
-threads = { 0 : "idle"}
-
-def thread_name(pid):
- return "%s:%d" % (threads[pid], pid)
-
-class RunqueueEventUnknown:
- @staticmethod
- def color():
- return None
-
- def __repr__(self):
- return "unknown"
-
-class RunqueueEventSleep:
- @staticmethod
- def color():
- return (0, 0, 0xff)
-
- def __init__(self, sleeper):
- self.sleeper = sleeper
-
- def __repr__(self):
- return "%s gone to sleep" % thread_name(self.sleeper)
-
-class RunqueueEventWakeup:
- @staticmethod
- def color():
- return (0xff, 0xff, 0)
-
- def __init__(self, wakee):
- self.wakee = wakee
-
- def __repr__(self):
- return "%s woke up" % thread_name(self.wakee)
-
-class RunqueueEventFork:
- @staticmethod
- def color():
- return (0, 0xff, 0)
-
- def __init__(self, child):
- self.child = child
-
- def __repr__(self):
- return "new forked task %s" % thread_name(self.child)
-
-class RunqueueMigrateIn:
- @staticmethod
- def color():
- return (0, 0xf0, 0xff)
-
- def __init__(self, new):
- self.new = new
-
- def __repr__(self):
- return "task migrated in %s" % thread_name(self.new)
-
-class RunqueueMigrateOut:
- @staticmethod
- def color():
- return (0xff, 0, 0xff)
-
- def __init__(self, old):
- self.old = old
-
- def __repr__(self):
- return "task migrated out %s" % thread_name(self.old)
-
-class RunqueueSnapshot:
- def __init__(self, tasks = [0], event = RunqueueEventUnknown()):
- self.tasks = tuple(tasks)
- self.event = event
-
- def sched_switch(self, prev, prev_state, next):
- event = RunqueueEventUnknown()
-
- if taskState(prev_state) == "R" and next in self.tasks \
- and prev in self.tasks:
- return self
-
- if taskState(prev_state) != "R":
- event = RunqueueEventSleep(prev)
-
- next_tasks = list(self.tasks[:])
- if prev in self.tasks:
- if taskState(prev_state) != "R":
- next_tasks.remove(prev)
- elif taskState(prev_state) == "R":
- next_tasks.append(prev)
-
- if next not in next_tasks:
- next_tasks.append(next)
-
- return RunqueueSnapshot(next_tasks, event)
-
- def migrate_out(self, old):
- if old not in self.tasks:
- return self
- next_tasks = [task for task in self.tasks if task != old]
-
- return RunqueueSnapshot(next_tasks, RunqueueMigrateOut(old))
-
- def __migrate_in(self, new, event):
- if new in self.tasks:
- self.event = event
- return self
- next_tasks = self.tasks[:] + tuple([new])
-
- return RunqueueSnapshot(next_tasks, event)
-
- def migrate_in(self, new):
- return self.__migrate_in(new, RunqueueMigrateIn(new))
-
- def wake_up(self, new):
- return self.__migrate_in(new, RunqueueEventWakeup(new))
-
- def wake_up_new(self, new):
- return self.__migrate_in(new, RunqueueEventFork(new))
-
- def load(self):
- """ Provide the number of tasks on the runqueue.
- Don't count idle"""
- return len(self.tasks) - 1
-
- def __repr__(self):
- ret = self.tasks.__repr__()
- ret += self.origin_tostring()
-
- return ret
-
-class TimeSlice:
- def __init__(self, start, prev):
- self.start = start
- self.prev = prev
- self.end = start
- # cpus that triggered the event
- self.event_cpus = []
- if prev is not None:
- self.total_load = prev.total_load
- self.rqs = prev.rqs.copy()
- else:
- self.rqs = defaultdict(RunqueueSnapshot)
- self.total_load = 0
-
- def __update_total_load(self, old_rq, new_rq):
- diff = new_rq.load() - old_rq.load()
- self.total_load += diff
-
- def sched_switch(self, ts_list, prev, prev_state, next, cpu):
- old_rq = self.prev.rqs[cpu]
- new_rq = old_rq.sched_switch(prev, prev_state, next)
-
- if old_rq is new_rq:
- return
-
- self.rqs[cpu] = new_rq
- self.__update_total_load(old_rq, new_rq)
- ts_list.append(self)
- self.event_cpus = [cpu]
-
- def migrate(self, ts_list, new, old_cpu, new_cpu):
- if old_cpu == new_cpu:
- return
- old_rq = self.prev.rqs[old_cpu]
- out_rq = old_rq.migrate_out(new)
- self.rqs[old_cpu] = out_rq
- self.__update_total_load(old_rq, out_rq)
-
- new_rq = self.prev.rqs[new_cpu]
- in_rq = new_rq.migrate_in(new)
- self.rqs[new_cpu] = in_rq
- self.__update_total_load(new_rq, in_rq)
-
- ts_list.append(self)
-
- if old_rq is not out_rq:
- self.event_cpus.append(old_cpu)
- self.event_cpus.append(new_cpu)
-
- def wake_up(self, ts_list, pid, cpu, fork):
- old_rq = self.prev.rqs[cpu]
- if fork:
- new_rq = old_rq.wake_up_new(pid)
- else:
- new_rq = old_rq.wake_up(pid)
-
- if new_rq is old_rq:
- return
- self.rqs[cpu] = new_rq
- self.__update_total_load(old_rq, new_rq)
- ts_list.append(self)
- self.event_cpus = [cpu]
-
- def next(self, t):
- self.end = t
- return TimeSlice(t, self)
-
-class TimeSliceList(UserList):
- def __init__(self, arg = []):
- self.data = arg
-
- def get_time_slice(self, ts):
- if len(self.data) == 0:
- slice = TimeSlice(ts, TimeSlice(-1, None))
- else:
- slice = self.data[-1].next(ts)
- return slice
-
- def find_time_slice(self, ts):
- start = 0
- end = len(self.data)
- found = -1
- searching = True
- while searching:
- if start == end or start == end - 1:
- searching = False
-
- i = (end + start) / 2
- if self.data[i].start <= ts and self.data[i].end >= ts:
- found = i
- end = i
- continue
-
- if self.data[i].end < ts:
- start = i
-
- elif self.data[i].start > ts:
- end = i
-
- return found
-
- def set_root_win(self, win):
- self.root_win = win
-
- def mouse_down(self, cpu, t):
- idx = self.find_time_slice(t)
- if idx == -1:
- return
-
- ts = self[idx]
- rq = ts.rqs[cpu]
- raw = "CPU: %d\n" % cpu
- raw += "Last event : %s\n" % rq.event.__repr__()
- raw += "Timestamp : %d.%06d\n" % (ts.start / (10 ** 9), (ts.start % (10 ** 9)) / 1000)
- raw += "Duration : %6d us\n" % ((ts.end - ts.start) / (10 ** 6))
- raw += "Load = %d\n" % rq.load()
- for t in rq.tasks:
- raw += "%s \n" % thread_name(t)
-
- self.root_win.update_summary(raw)
-
- def update_rectangle_cpu(self, slice, cpu):
- rq = slice.rqs[cpu]
-
- if slice.total_load != 0:
- load_rate = rq.load() / float(slice.total_load)
- else:
- load_rate = 0
-
- red_power = int(0xff - (0xff * load_rate))
- color = (0xff, red_power, red_power)
-
- top_color = None
-
- if cpu in slice.event_cpus:
- top_color = rq.event.color()
-
- self.root_win.paint_rectangle_zone(cpu, color, top_color, slice.start, slice.end)
-
- def fill_zone(self, start, end):
- i = self.find_time_slice(start)
- if i == -1:
- return
-
- for i in range(i, len(self.data)):
- timeslice = self.data[i]
- if timeslice.start > end:
- return
-
- for cpu in timeslice.rqs:
- self.update_rectangle_cpu(timeslice, cpu)
-
- def interval(self):
- if len(self.data) == 0:
- return (0, 0)
-
- return (self.data[0].start, self.data[-1].end)
-
- def nr_rectangles(self):
- last_ts = self.data[-1]
- max_cpu = 0
- for cpu in last_ts.rqs:
- if cpu > max_cpu:
- max_cpu = cpu
- return max_cpu
-
-
-class SchedEventProxy:
- def __init__(self):
- self.current_tsk = defaultdict(lambda : -1)
- self.timeslices = TimeSliceList()
-
- def sched_switch(self, headers, prev_comm, prev_pid, prev_prio, prev_state,
- next_comm, next_pid, next_prio):
- """ Ensure the task we sched out this cpu is really the one
- we logged. Otherwise we may have missed traces """
-
- on_cpu_task = self.current_tsk[headers.cpu]
-
- if on_cpu_task != -1 and on_cpu_task != prev_pid:
- print("Sched switch event rejected ts: %s cpu: %d prev: %s(%d) next: %s(%d)" % \
- headers.ts_format(), headers.cpu, prev_comm, prev_pid, next_comm, next_pid)
-
- threads[prev_pid] = prev_comm
- threads[next_pid] = next_comm
- self.current_tsk[headers.cpu] = next_pid
-
- ts = self.timeslices.get_time_slice(headers.ts())
- ts.sched_switch(self.timeslices, prev_pid, prev_state, next_pid, headers.cpu)
-
- def migrate(self, headers, pid, prio, orig_cpu, dest_cpu):
- ts = self.timeslices.get_time_slice(headers.ts())
- ts.migrate(self.timeslices, pid, orig_cpu, dest_cpu)
-
- def wake_up(self, headers, comm, pid, success, target_cpu, fork):
- if success == 0:
- return
- ts = self.timeslices.get_time_slice(headers.ts())
- ts.wake_up(self.timeslices, pid, target_cpu, fork)
-
-
-def trace_begin():
- global parser
- parser = SchedEventProxy()
-
-def trace_end():
- app = wx.App(False)
- timeslices = parser.timeslices
- frame = RootFrame(timeslices, "Migration")
- app.MainLoop()
-
-def sched__sched_stat_runtime(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, runtime, vruntime):
- pass
-
-def sched__sched_stat_iowait(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, delay):
- pass
-
-def sched__sched_stat_sleep(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, delay):
- pass
-
-def sched__sched_stat_wait(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, delay):
- pass
-
-def sched__sched_process_fork(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, parent_comm, parent_pid, child_comm, child_pid):
- pass
-
-def sched__sched_process_wait(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, prio):
- pass
-
-def sched__sched_process_exit(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, prio):
- pass
-
-def sched__sched_process_free(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, prio):
- pass
-
-def sched__sched_migrate_task(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, prio, orig_cpu,
- dest_cpu):
- headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm, common_callchain)
- parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)
-
-def sched__sched_switch(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm, common_callchain,
- prev_comm, prev_pid, prev_prio, prev_state,
- next_comm, next_pid, next_prio):
-
- headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm, common_callchain)
- parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
- next_comm, next_pid, next_prio)
-
-def sched__sched_wakeup_new(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, prio, success,
- target_cpu):
- headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm, common_callchain)
- parser.wake_up(headers, comm, pid, success, target_cpu, 1)
-
-def sched__sched_wakeup(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, prio, success,
- target_cpu):
- headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm, common_callchain)
- parser.wake_up(headers, comm, pid, success, target_cpu, 0)
-
-def sched__sched_wait_task(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid, prio):
- pass
-
-def sched__sched_kthread_stop_ret(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, ret):
- pass
-
-def sched__sched_kthread_stop(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, comm, pid):
- pass
-
-def trace_unhandled(event_name, context, event_fields_dict):
- pass
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
deleted file mode 100644
index 6e0278dcb092..000000000000
--- a/tools/perf/scripts/python/sctop.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# system call top
-# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
-# Licensed under the terms of the GNU GPL License version 2
-#
-# Periodically displays system-wide system call totals, broken down by
-# syscall. If a [comm] arg is specified, only syscalls called by
-# [comm] are displayed. If an [interval] arg is specified, the display
-# will be refreshed every [interval] seconds. The default interval is
-# 3 seconds.
-
-from __future__ import print_function
-
-import os, sys, time
-
-try:
- import thread
-except ImportError:
- import _thread as thread
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-from Util import *
-
-usage = "perf script -s sctop.py [comm] [interval]\n";
-
-for_comm = None
-default_interval = 3
-interval = default_interval
-
-if len(sys.argv) > 3:
- sys.exit(usage)
-
-if len(sys.argv) > 2:
- for_comm = sys.argv[1]
- interval = int(sys.argv[2])
-elif len(sys.argv) > 1:
- try:
- interval = int(sys.argv[1])
- except ValueError:
- for_comm = sys.argv[1]
- interval = default_interval
-
-syscalls = autodict()
-
-def trace_begin():
- thread.start_new_thread(print_syscall_totals, (interval,))
- pass
-
-def raw_syscalls__sys_enter(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, id, args):
- if for_comm is not None:
- if common_comm != for_comm:
- return
- try:
- syscalls[id] += 1
- except TypeError:
- syscalls[id] = 1
-
-def syscalls__sys_enter(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- id, args):
- raw_syscalls__sys_enter(**locals())
-
-def print_syscall_totals(interval):
- while 1:
- clear_term()
- if for_comm is not None:
- print("\nsyscall events for %s:\n" % (for_comm))
- else:
- print("\nsyscall events:\n")
-
- print("%-40s %10s" % ("event", "count"))
- print("%-40s %10s" %
- ("----------------------------------------",
- "----------"))
-
- for id, val in sorted(syscalls.items(),
- key = lambda kv: (kv[1], kv[0]),
- reverse = True):
- try:
- print("%-40s %10d" % (syscall_name(id), val))
- except TypeError:
- pass
- syscalls.clear()
- time.sleep(interval)
diff --git a/tools/perf/scripts/python/stackcollapse.py b/tools/perf/scripts/python/stackcollapse.py
deleted file mode 100755
index b1c4def1410a..000000000000
--- a/tools/perf/scripts/python/stackcollapse.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# stackcollapse.py - format perf samples with one line per distinct call stack
-# SPDX-License-Identifier: GPL-2.0
-#
-# This script's output has two space-separated fields. The first is a semicolon
-# separated stack including the program name (from the "comm" field) and the
-# function names from the call stack. The second is a count:
-#
-# swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 2
-#
-# The file is sorted according to the first field.
-#
-# Input may be created and processed using:
-#
-# perf record -a -g -F 99 sleep 60
-# perf script report stackcollapse > out.stacks-folded
-#
-# (perf script record stackcollapse works too).
-#
-# Written by Paolo Bonzini <pbonzini@redhat.com>
-# Based on Brendan Gregg's stackcollapse-perf.pl script.
-
-from __future__ import print_function
-
-import os
-import sys
-from collections import defaultdict
-from optparse import OptionParser, make_option
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-from EventClass import *
-
-# command line parsing
-
-option_list = [
- # formatting options for the bottom entry of the stack
- make_option("--include-tid", dest="include_tid",
- action="store_true", default=False,
- help="include thread id in stack"),
- make_option("--include-pid", dest="include_pid",
- action="store_true", default=False,
- help="include process id in stack"),
- make_option("--no-comm", dest="include_comm",
- action="store_false", default=True,
- help="do not separate stacks according to comm"),
- make_option("--tidy-java", dest="tidy_java",
- action="store_true", default=False,
- help="beautify Java signatures"),
- make_option("--kernel", dest="annotate_kernel",
- action="store_true", default=False,
- help="annotate kernel functions with _[k]")
-]
-
-parser = OptionParser(option_list=option_list)
-(opts, args) = parser.parse_args()
-
-if len(args) != 0:
- parser.error("unexpected command line argument")
-if opts.include_tid and not opts.include_comm:
- parser.error("requesting tid but not comm is invalid")
-if opts.include_pid and not opts.include_comm:
- parser.error("requesting pid but not comm is invalid")
-
-# event handlers
-
-lines = defaultdict(lambda: 0)
-
-def process_event(param_dict):
- def tidy_function_name(sym, dso):
- if sym is None:
- sym = '[unknown]'
-
- sym = sym.replace(';', ':')
- if opts.tidy_java:
- # the original stackcollapse-perf.pl script gives the
- # example of converting this:
- # Lorg/mozilla/javascript/MemberBox;.<init>(Ljava/lang/reflect/Method;)V
- # to this:
- # org/mozilla/javascript/MemberBox:.init
- sym = sym.replace('<', '')
- sym = sym.replace('>', '')
- if sym[0] == 'L' and sym.find('/'):
- sym = sym[1:]
- try:
- sym = sym[:sym.index('(')]
- except ValueError:
- pass
-
- if opts.annotate_kernel and dso == '[kernel.kallsyms]':
- return sym + '_[k]'
- else:
- return sym
-
- stack = list()
- if 'callchain' in param_dict:
- for entry in param_dict['callchain']:
- entry.setdefault('sym', dict())
- entry['sym'].setdefault('name', None)
- entry.setdefault('dso', None)
- stack.append(tidy_function_name(entry['sym']['name'],
- entry['dso']))
- else:
- param_dict.setdefault('symbol', None)
- param_dict.setdefault('dso', None)
- stack.append(tidy_function_name(param_dict['symbol'],
- param_dict['dso']))
-
- if opts.include_comm:
- comm = param_dict["comm"].replace(' ', '_')
- sep = "-"
- if opts.include_pid:
- comm = comm + sep + str(param_dict['sample']['pid'])
- sep = "/"
- if opts.include_tid:
- comm = comm + sep + str(param_dict['sample']['tid'])
- stack.append(comm)
-
- stack_string = ';'.join(reversed(stack))
- lines[stack_string] = lines[stack_string] + 1
-
-def trace_end():
- list = sorted(lines)
- for stack in list:
- print("%s %d" % (stack, lines[stack]))
diff --git a/tools/perf/scripts/python/stat-cpi.py b/tools/perf/scripts/python/stat-cpi.py
deleted file mode 100644
index 01fa933ff3cf..000000000000
--- a/tools/perf/scripts/python/stat-cpi.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-from __future__ import print_function
-
-data = {}
-times = []
-threads = []
-cpus = []
-
-def get_key(time, event, cpu, thread):
- return "%d-%s-%d-%d" % (time, event, cpu, thread)
-
-def store_key(time, cpu, thread):
- if (time not in times):
- times.append(time)
-
- if (cpu not in cpus):
- cpus.append(cpu)
-
- if (thread not in threads):
- threads.append(thread)
-
-def store(time, event, cpu, thread, val, ena, run):
- #print("event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" %
- # (event, cpu, thread, time, val, ena, run))
-
- store_key(time, cpu, thread)
- key = get_key(time, event, cpu, thread)
- data[key] = [ val, ena, run]
-
-def get(time, event, cpu, thread):
- key = get_key(time, event, cpu, thread)
- return data[key][0]
-
-def stat__cycles_k(cpu, thread, time, val, ena, run):
- store(time, "cycles", cpu, thread, val, ena, run);
-
-def stat__instructions_k(cpu, thread, time, val, ena, run):
- store(time, "instructions", cpu, thread, val, ena, run);
-
-def stat__cycles_u(cpu, thread, time, val, ena, run):
- store(time, "cycles", cpu, thread, val, ena, run);
-
-def stat__instructions_u(cpu, thread, time, val, ena, run):
- store(time, "instructions", cpu, thread, val, ena, run);
-
-def stat__cycles(cpu, thread, time, val, ena, run):
- store(time, "cycles", cpu, thread, val, ena, run);
-
-def stat__instructions(cpu, thread, time, val, ena, run):
- store(time, "instructions", cpu, thread, val, ena, run);
-
-def stat__interval(time):
- for cpu in cpus:
- for thread in threads:
- cyc = get(time, "cycles", cpu, thread)
- ins = get(time, "instructions", cpu, thread)
- cpi = 0
-
- if ins != 0:
- cpi = cyc/float(ins)
-
- print("%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins))
-
-def trace_end():
- pass
-# XXX trace_end callback could be used as an alternative place
-# to compute same values as in the script above:
-#
-# for time in times:
-# for cpu in cpus:
-# for thread in threads:
-# cyc = get(time, "cycles", cpu, thread)
-# ins = get(time, "instructions", cpu, thread)
-#
-# if ins != 0:
-# cpi = cyc/float(ins)
-#
-# print("time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi))
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
deleted file mode 100644
index f254e40c6f0f..000000000000
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# system call counts, by pid
-# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
-# Licensed under the terms of the GNU GPL License version 2
-#
-# Displays system-wide system call totals, broken down by syscall.
-# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
-
-from __future__ import print_function
-
-import os, sys
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-from Util import syscall_name
-
-usage = "perf script -s syscall-counts-by-pid.py [comm]\n";
-
-for_comm = None
-for_pid = None
-
-if len(sys.argv) > 2:
- sys.exit(usage)
-
-if len(sys.argv) > 1:
- try:
- for_pid = int(sys.argv[1])
- except:
- for_comm = sys.argv[1]
-
-syscalls = autodict()
-
-def trace_begin():
- print("Press control+C to stop and show the summary")
-
-def trace_end():
- print_syscall_totals()
-
-def raw_syscalls__sys_enter(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, id, args):
- if (for_comm and common_comm != for_comm) or \
- (for_pid and common_pid != for_pid ):
- return
- try:
- syscalls[common_comm][common_pid][id] += 1
- except TypeError:
- syscalls[common_comm][common_pid][id] = 1
-
-def syscalls__sys_enter(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- id, args):
- raw_syscalls__sys_enter(**locals())
-
-def print_syscall_totals():
- if for_comm is not None:
- print("\nsyscall events for %s:\n" % (for_comm))
- else:
- print("\nsyscall events by comm/pid:\n")
-
- print("%-40s %10s" % ("comm [pid]/syscalls", "count"))
- print("%-40s %10s" % ("----------------------------------------",
- "----------"))
-
- comm_keys = syscalls.keys()
- for comm in comm_keys:
- pid_keys = syscalls[comm].keys()
- for pid in pid_keys:
- print("\n%s [%d]" % (comm, pid))
- id_keys = syscalls[comm][pid].keys()
- for id, val in sorted(syscalls[comm][pid].items(),
- key = lambda kv: (kv[1], kv[0]), reverse = True):
- print(" %-38s %10d" % (syscall_name(id), val))
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
deleted file mode 100644
index 8adb95ff1664..000000000000
--- a/tools/perf/scripts/python/syscall-counts.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# system call counts
-# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
-# Licensed under the terms of the GNU GPL License version 2
-#
-# Displays system-wide system call totals, broken down by syscall.
-# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
-
-from __future__ import print_function
-
-import os
-import sys
-
-sys.path.append(os.environ['PERF_EXEC_PATH'] + \
- '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
-
-from perf_trace_context import *
-from Core import *
-from Util import syscall_name
-
-usage = "perf script -s syscall-counts.py [comm]\n";
-
-for_comm = None
-
-if len(sys.argv) > 2:
- sys.exit(usage)
-
-if len(sys.argv) > 1:
- for_comm = sys.argv[1]
-
-syscalls = autodict()
-
-def trace_begin():
- print("Press control+C to stop and show the summary")
-
-def trace_end():
- print_syscall_totals()
-
-def raw_syscalls__sys_enter(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
- common_callchain, id, args):
- if for_comm is not None:
- if common_comm != for_comm:
- return
- try:
- syscalls[id] += 1
- except TypeError:
- syscalls[id] = 1
-
-def syscalls__sys_enter(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm, id, args):
- raw_syscalls__sys_enter(**locals())
-
-def print_syscall_totals():
- if for_comm is not None:
- print("\nsyscall events for %s:\n" % (for_comm))
- else:
- print("\nsyscall events:\n")
-
- print("%-40s %10s" % ("event", "count"))
- print("%-40s %10s" % ("----------------------------------------",
- "-----------"))
-
- for id, val in sorted(syscalls.items(),
- key = lambda kv: (kv[1], kv[0]), reverse = True):
- print("%-40s %10d" % (syscall_name(id), val))
diff --git a/tools/perf/scripts/python/task-analyzer.py b/tools/perf/scripts/python/task-analyzer.py
deleted file mode 100755
index 3f1df9894246..000000000000
--- a/tools/perf/scripts/python/task-analyzer.py
+++ /dev/null
@@ -1,934 +0,0 @@
-# task-analyzer.py - comprehensive perf tasks analysis
-# SPDX-License-Identifier: GPL-2.0
-# Copyright (c) 2022, Hagen Paul Pfeifer <hagen@jauu.net>
-# Licensed under the terms of the GNU GPL License version 2
-#
-# Usage:
-#
-# perf record -e sched:sched_switch -a -- sleep 10
-# perf script report task-analyzer
-#
-
-from __future__ import print_function
-import sys
-import os
-import string
-import argparse
-import decimal
-
-
-sys.path.append(
- os.environ["PERF_EXEC_PATH"] + "/scripts/python/Perf-Trace-Util/lib/Perf/Trace"
-)
-from perf_trace_context import *
-from Core import *
-
-# Definition of possible ASCII color codes
-_COLORS = {
- "grey": "\033[90m",
- "red": "\033[91m",
- "green": "\033[92m",
- "yellow": "\033[93m",
- "blue": "\033[94m",
- "violet": "\033[95m",
- "reset": "\033[0m",
-}
-
-# Columns will have a static size to align everything properly
-# Support of 116 days of active update with nano precision
-LEN_SWITCHED_IN = len("9999999.999999999") # 17
-LEN_SWITCHED_OUT = len("9999999.999999999") # 17
-LEN_CPU = len("000")
-LEN_PID = len("maxvalue") # 8
-LEN_TID = len("maxvalue") # 8
-LEN_COMM = len("max-comms-length") # 16
-LEN_RUNTIME = len("999999.999") # 10
-# Support of 3.45 hours of timespans
-LEN_OUT_IN = len("99999999999.999") # 15
-LEN_OUT_OUT = len("99999999999.999") # 15
-LEN_IN_IN = len("99999999999.999") # 15
-LEN_IN_OUT = len("99999999999.999") # 15
-
-
-# py2/py3 compatibility layer, see PEP469
-try:
- dict.iteritems
-except AttributeError:
- # py3
- def itervalues(d):
- return iter(d.values())
-
- def iteritems(d):
- return iter(d.items())
-
-else:
- # py2
- def itervalues(d):
- return d.itervalues()
-
- def iteritems(d):
- return d.iteritems()
-
-
-def _check_color():
- global _COLORS
- """user enforced no-color or if stdout is no tty we disable colors"""
- if sys.stdout.isatty() and args.stdio_color != "never":
- return
- _COLORS = {
- "grey": "",
- "red": "",
- "green": "",
- "yellow": "",
- "blue": "",
- "violet": "",
- "reset": "",
- }
-
-
-def _parse_args():
- global args
- parser = argparse.ArgumentParser(description="Analyze tasks behavior")
- parser.add_argument(
- "--time-limit",
- default=[],
- help=
- "print tasks only in time[s] window e.g"
- " --time-limit 123.111:789.222(print all between 123.111 and 789.222)"
- " --time-limit 123: (print all from 123)"
- " --time-limit :456 (print all until incl. 456)",
- )
- parser.add_argument(
- "--summary", action="store_true", help="print addtional runtime information"
- )
- parser.add_argument(
- "--summary-only", action="store_true", help="print only summary without traces"
- )
- parser.add_argument(
- "--summary-extended",
- action="store_true",
- help="print the summary with additional information of max inter task times"
- " relative to the prev task",
- )
- parser.add_argument(
- "--ns", action="store_true", help="show timestamps in nanoseconds"
- )
- parser.add_argument(
- "--ms", action="store_true", help="show timestamps in milliseconds"
- )
- parser.add_argument(
- "--extended-times",
- action="store_true",
- help="Show the elapsed times between schedule in/schedule out"
- " of this task and the schedule in/schedule out of previous occurrence"
- " of the same task",
- )
- parser.add_argument(
- "--filter-tasks",
- default=[],
- help="filter out unneeded tasks by tid, pid or processname."
- " E.g --filter-task 1337,/sbin/init ",
- )
- parser.add_argument(
- "--limit-to-tasks",
- default=[],
- help="limit output to selected task by tid, pid, processname."
- " E.g --limit-to-tasks 1337,/sbin/init",
- )
- parser.add_argument(
- "--highlight-tasks",
- default="",
- help="colorize special tasks by their pid/tid/comm."
- " E.g. --highlight-tasks 1:red,mutt:yellow"
- " Colors available: red,grey,yellow,blue,violet,green",
- )
- parser.add_argument(
- "--rename-comms-by-tids",
- default="",
- help="rename task names by using tid (<tid>:<newname>,<tid>:<newname>)"
- " This option is handy for inexpressive processnames like python interpreted"
- " process. E.g --rename 1337:my-python-app",
- )
- parser.add_argument(
- "--stdio-color",
- default="auto",
- choices=["always", "never", "auto"],
- help="always, never or auto, allowing configuring color output"
- " via the command line",
- )
- parser.add_argument(
- "--csv",
- default="",
- help="Write trace to file selected by user. Options, like --ns or --extended"
- "-times are used.",
- )
- parser.add_argument(
- "--csv-summary",
- default="",
- help="Write summary to file selected by user. Options, like --ns or"
- " --summary-extended are used.",
- )
- args = parser.parse_args()
- args.tid_renames = dict()
-
- _argument_filter_sanity_check()
- _argument_prepare_check()
-
-
-def time_uniter(unit):
- picker = {
- "s": 1,
- "ms": 1e3,
- "us": 1e6,
- "ns": 1e9,
- }
- return picker[unit]
-
-
-def _init_db():
- global db
- db = dict()
- db["running"] = dict()
- db["cpu"] = dict()
- db["tid"] = dict()
- db["global"] = []
- if args.summary or args.summary_extended or args.summary_only:
- db["task_info"] = dict()
- db["runtime_info"] = dict()
- # min values for summary depending on the header
- db["task_info"]["pid"] = len("PID")
- db["task_info"]["tid"] = len("TID")
- db["task_info"]["comm"] = len("Comm")
- db["runtime_info"]["runs"] = len("Runs")
- db["runtime_info"]["acc"] = len("Accumulated")
- db["runtime_info"]["max"] = len("Max")
- db["runtime_info"]["max_at"] = len("Max At")
- db["runtime_info"]["min"] = len("Min")
- db["runtime_info"]["mean"] = len("Mean")
- db["runtime_info"]["median"] = len("Median")
- if args.summary_extended:
- db["inter_times"] = dict()
- db["inter_times"]["out_in"] = len("Out-In")
- db["inter_times"]["inter_at"] = len("At")
- db["inter_times"]["out_out"] = len("Out-Out")
- db["inter_times"]["in_in"] = len("In-In")
- db["inter_times"]["in_out"] = len("In-Out")
-
-
-def _median(numbers):
- """phython3 hat statistics module - we have nothing"""
- n = len(numbers)
- index = n // 2
- if n % 2:
- return sorted(numbers)[index]
- return sum(sorted(numbers)[index - 1 : index + 1]) / 2
-
-
-def _mean(numbers):
- return sum(numbers) / len(numbers)
-
-
-class Timespans(object):
- """
- The elapsed time between two occurrences of the same task is being tracked with the
- help of this class. There are 4 of those Timespans Out-Out, In-Out, Out-In and
- In-In.
- The first half of the name signals the first time point of the
- first task. The second half of the name represents the second
- timepoint of the second task.
- """
-
- def __init__(self):
- self._last_start = None
- self._last_finish = None
- self.out_out = -1
- self.in_out = -1
- self.out_in = -1
- self.in_in = -1
- if args.summary_extended:
- self._time_in = -1
- self.max_out_in = -1
- self.max_at = -1
- self.max_in_out = -1
- self.max_in_in = -1
- self.max_out_out = -1
-
- def feed(self, task):
- """
- Called for every recorded trace event to find process pair and calculate the
- task timespans. Chronological ordering, feed does not do reordering
- """
- if not self._last_finish:
- self._last_start = task.time_in(time_unit)
- self._last_finish = task.time_out(time_unit)
- return
- self._time_in = task.time_in()
- time_in = task.time_in(time_unit)
- time_out = task.time_out(time_unit)
- self.in_in = time_in - self._last_start
- self.out_in = time_in - self._last_finish
- self.in_out = time_out - self._last_start
- self.out_out = time_out - self._last_finish
- if args.summary_extended:
- self._update_max_entries()
- self._last_finish = task.time_out(time_unit)
- self._last_start = task.time_in(time_unit)
-
- def _update_max_entries(self):
- if self.in_in > self.max_in_in:
- self.max_in_in = self.in_in
- if self.out_out > self.max_out_out:
- self.max_out_out = self.out_out
- if self.in_out > self.max_in_out:
- self.max_in_out = self.in_out
- if self.out_in > self.max_out_in:
- self.max_out_in = self.out_in
- self.max_at = self._time_in
-
-
-
-class Summary(object):
- """
- Primary instance for calculating the summary output. Processes the whole trace to
- find and memorize relevant data such as mean, max et cetera. This instance handles
- dynamic alignment aspects for summary output.
- """
-
- def __init__(self):
- self._body = []
-
- class AlignmentHelper:
- """
- Used to calculated the alignment for the output of the summary.
- """
- def __init__(self, pid, tid, comm, runs, acc, mean,
- median, min, max, max_at):
- self.pid = pid
- self.tid = tid
- self.comm = comm
- self.runs = runs
- self.acc = acc
- self.mean = mean
- self.median = median
- self.min = min
- self.max = max
- self.max_at = max_at
- if args.summary_extended:
- self.out_in = None
- self.inter_at = None
- self.out_out = None
- self.in_in = None
- self.in_out = None
-
- def _print_header(self):
- '''
- Output is trimmed in _format_stats thus additional adjustment in the header
- is needed, depending on the choice of timeunit. The adjustment corresponds
- to the amount of column titles being adjusted in _column_titles.
- '''
- decimal_precision = 6 if not args.ns else 9
- fmt = " {{:^{}}}".format(sum(db["task_info"].values()))
- fmt += " {{:^{}}}".format(
- sum(db["runtime_info"].values()) - 2 * decimal_precision
- )
- _header = ("Task Information", "Runtime Information")
-
- if args.summary_extended:
- fmt += " {{:^{}}}".format(
- sum(db["inter_times"].values()) - 4 * decimal_precision
- )
- _header += ("Max Inter Task Times",)
- fd_sum.write(fmt.format(*_header) + "\n")
-
- def _column_titles(self):
- """
- Cells are being processed and displayed in different way so an alignment adjust
- is implemented depeding on the choice of the timeunit. The positions of the max
- values are being displayed in grey. Thus in their format two additional {},
- are placed for color set and reset.
- """
- separator, fix_csv_align = _prepare_fmt_sep()
- decimal_precision, time_precision = _prepare_fmt_precision()
- fmt = "{{:>{}}}".format(db["task_info"]["pid"] * fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, db["task_info"]["tid"] * fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, db["task_info"]["comm"] * fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, db["runtime_info"]["runs"] * fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, db["runtime_info"]["acc"] * fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, db["runtime_info"]["mean"] * fix_csv_align)
- fmt += "{}{{:>{}}}".format(
- separator, db["runtime_info"]["median"] * fix_csv_align
- )
- fmt += "{}{{:>{}}}".format(
- separator, (db["runtime_info"]["min"] - decimal_precision) * fix_csv_align
- )
- fmt += "{}{{:>{}}}".format(
- separator, (db["runtime_info"]["max"] - decimal_precision) * fix_csv_align
- )
- fmt += "{}{{}}{{:>{}}}{{}}".format(
- separator, (db["runtime_info"]["max_at"] - time_precision) * fix_csv_align
- )
-
- column_titles = ("PID", "TID", "Comm")
- column_titles += ("Runs", "Accumulated", "Mean", "Median", "Min", "Max")
- column_titles += (_COLORS["grey"], "Max At", _COLORS["reset"])
-
- if args.summary_extended:
- fmt += "{}{{:>{}}}".format(
- separator,
- (db["inter_times"]["out_in"] - decimal_precision) * fix_csv_align
- )
- fmt += "{}{{}}{{:>{}}}{{}}".format(
- separator,
- (db["inter_times"]["inter_at"] - time_precision) * fix_csv_align
- )
- fmt += "{}{{:>{}}}".format(
- separator,
- (db["inter_times"]["out_out"] - decimal_precision) * fix_csv_align
- )
- fmt += "{}{{:>{}}}".format(
- separator,
- (db["inter_times"]["in_in"] - decimal_precision) * fix_csv_align
- )
- fmt += "{}{{:>{}}}".format(
- separator,
- (db["inter_times"]["in_out"] - decimal_precision) * fix_csv_align
- )
-
- column_titles += ("Out-In", _COLORS["grey"], "Max At", _COLORS["reset"],
- "Out-Out", "In-In", "In-Out")
-
- fd_sum.write(fmt.format(*column_titles) + "\n")
-
-
- def _task_stats(self):
- """calculates the stats of every task and constructs the printable summary"""
- for tid in sorted(db["tid"]):
- color_one_sample = _COLORS["grey"]
- color_reset = _COLORS["reset"]
- no_executed = 0
- runtimes = []
- time_in = []
- timespans = Timespans()
- for task in db["tid"][tid]:
- pid = task.pid
- comm = task.comm
- no_executed += 1
- runtimes.append(task.runtime(time_unit))
- time_in.append(task.time_in())
- timespans.feed(task)
- if len(runtimes) > 1:
- color_one_sample = ""
- color_reset = ""
- time_max = max(runtimes)
- time_min = min(runtimes)
- max_at = time_in[runtimes.index(max(runtimes))]
-
- # The size of the decimal after sum,mean and median varies, thus we cut
- # the decimal number, by rounding it. It has no impact on the output,
- # because we have a precision of the decimal points at the output.
- time_sum = round(sum(runtimes), 3)
- time_mean = round(_mean(runtimes), 3)
- time_median = round(_median(runtimes), 3)
-
- align_helper = self.AlignmentHelper(pid, tid, comm, no_executed, time_sum,
- time_mean, time_median, time_min, time_max, max_at)
- self._body.append([pid, tid, comm, no_executed, time_sum, color_one_sample,
- time_mean, time_median, time_min, time_max,
- _COLORS["grey"], max_at, _COLORS["reset"], color_reset])
- if args.summary_extended:
- self._body[-1].extend([timespans.max_out_in,
- _COLORS["grey"], timespans.max_at,
- _COLORS["reset"], timespans.max_out_out,
- timespans.max_in_in,
- timespans.max_in_out])
- align_helper.out_in = timespans.max_out_in
- align_helper.inter_at = timespans.max_at
- align_helper.out_out = timespans.max_out_out
- align_helper.in_in = timespans.max_in_in
- align_helper.in_out = timespans.max_in_out
- self._calc_alignments_summary(align_helper)
-
- def _format_stats(self):
- separator, fix_csv_align = _prepare_fmt_sep()
- decimal_precision, time_precision = _prepare_fmt_precision()
- len_pid = db["task_info"]["pid"] * fix_csv_align
- len_tid = db["task_info"]["tid"] * fix_csv_align
- len_comm = db["task_info"]["comm"] * fix_csv_align
- len_runs = db["runtime_info"]["runs"] * fix_csv_align
- len_acc = db["runtime_info"]["acc"] * fix_csv_align
- len_mean = db["runtime_info"]["mean"] * fix_csv_align
- len_median = db["runtime_info"]["median"] * fix_csv_align
- len_min = (db["runtime_info"]["min"] - decimal_precision) * fix_csv_align
- len_max = (db["runtime_info"]["max"] - decimal_precision) * fix_csv_align
- len_max_at = (db["runtime_info"]["max_at"] - time_precision) * fix_csv_align
- if args.summary_extended:
- len_out_in = (
- db["inter_times"]["out_in"] - decimal_precision
- ) * fix_csv_align
- len_inter_at = (
- db["inter_times"]["inter_at"] - time_precision
- ) * fix_csv_align
- len_out_out = (
- db["inter_times"]["out_out"] - decimal_precision
- ) * fix_csv_align
- len_in_in = (db["inter_times"]["in_in"] - decimal_precision) * fix_csv_align
- len_in_out = (
- db["inter_times"]["in_out"] - decimal_precision
- ) * fix_csv_align
-
- fmt = "{{:{}d}}".format(len_pid)
- fmt += "{}{{:{}d}}".format(separator, len_tid)
- fmt += "{}{{:>{}}}".format(separator, len_comm)
- fmt += "{}{{:{}d}}".format(separator, len_runs)
- fmt += "{}{{:{}.{}f}}".format(separator, len_acc, time_precision)
- fmt += "{}{{}}{{:{}.{}f}}".format(separator, len_mean, time_precision)
- fmt += "{}{{:{}.{}f}}".format(separator, len_median, time_precision)
- fmt += "{}{{:{}.{}f}}".format(separator, len_min, time_precision)
- fmt += "{}{{:{}.{}f}}".format(separator, len_max, time_precision)
- fmt += "{}{{}}{{:{}.{}f}}{{}}{{}}".format(
- separator, len_max_at, decimal_precision
- )
- if args.summary_extended:
- fmt += "{}{{:{}.{}f}}".format(separator, len_out_in, time_precision)
- fmt += "{}{{}}{{:{}.{}f}}{{}}".format(
- separator, len_inter_at, decimal_precision
- )
- fmt += "{}{{:{}.{}f}}".format(separator, len_out_out, time_precision)
- fmt += "{}{{:{}.{}f}}".format(separator, len_in_in, time_precision)
- fmt += "{}{{:{}.{}f}}".format(separator, len_in_out, time_precision)
- return fmt
-
-
- def _calc_alignments_summary(self, align_helper):
- # Length is being cut in 3 groups so that further addition is easier to handle.
- # The length of every argument from the alignment helper is being checked if it
- # is longer than the longest until now. In that case the length is being saved.
- for key in db["task_info"]:
- if len(str(getattr(align_helper, key))) > db["task_info"][key]:
- db["task_info"][key] = len(str(getattr(align_helper, key)))
- for key in db["runtime_info"]:
- if len(str(getattr(align_helper, key))) > db["runtime_info"][key]:
- db["runtime_info"][key] = len(str(getattr(align_helper, key)))
- if args.summary_extended:
- for key in db["inter_times"]:
- if len(str(getattr(align_helper, key))) > db["inter_times"][key]:
- db["inter_times"][key] = len(str(getattr(align_helper, key)))
-
-
- def print(self):
- self._task_stats()
- fmt = self._format_stats()
-
- if not args.csv_summary:
- print("\nSummary")
- self._print_header()
- self._column_titles()
- for i in range(len(self._body)):
- fd_sum.write(fmt.format(*tuple(self._body[i])) + "\n")
-
-
-
-class Task(object):
- """ The class is used to handle the information of a given task."""
-
- def __init__(self, id, tid, cpu, comm):
- self.id = id
- self.tid = tid
- self.cpu = cpu
- self.comm = comm
- self.pid = None
- self._time_in = None
- self._time_out = None
-
- def schedule_in_at(self, time):
- """set the time where the task was scheduled in"""
- self._time_in = time
-
- def schedule_out_at(self, time):
- """set the time where the task was scheduled out"""
- self._time_out = time
-
- def time_out(self, unit="s"):
- """return time where a given task was scheduled out"""
- factor = time_uniter(unit)
- return self._time_out * decimal.Decimal(factor)
-
- def time_in(self, unit="s"):
- """return time where a given task was scheduled in"""
- factor = time_uniter(unit)
- return self._time_in * decimal.Decimal(factor)
-
- def runtime(self, unit="us"):
- factor = time_uniter(unit)
- return (self._time_out - self._time_in) * decimal.Decimal(factor)
-
- def update_pid(self, pid):
- self.pid = pid
-
-
-def _task_id(pid, cpu):
- """returns a "unique-enough" identifier, please do not change"""
- return "{}-{}".format(pid, cpu)
-
-
-def _filter_non_printable(unfiltered):
- """comm names may contain loony chars like '\x00000'"""
- filtered = ""
- for char in unfiltered:
- if char not in string.printable:
- continue
- filtered += char
- return filtered
-
-
-def _fmt_header():
- separator, fix_csv_align = _prepare_fmt_sep()
- fmt = "{{:>{}}}".format(LEN_SWITCHED_IN*fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, LEN_SWITCHED_OUT*fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, LEN_CPU*fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, LEN_PID*fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, LEN_TID*fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, LEN_COMM*fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, LEN_RUNTIME*fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, LEN_OUT_IN*fix_csv_align)
- if args.extended_times:
- fmt += "{}{{:>{}}}".format(separator, LEN_OUT_OUT*fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, LEN_IN_IN*fix_csv_align)
- fmt += "{}{{:>{}}}".format(separator, LEN_IN_OUT*fix_csv_align)
- return fmt
-
-
-def _fmt_body():
- separator, fix_csv_align = _prepare_fmt_sep()
- decimal_precision, time_precision = _prepare_fmt_precision()
- fmt = "{{}}{{:{}.{}f}}".format(LEN_SWITCHED_IN*fix_csv_align, decimal_precision)
- fmt += "{}{{:{}.{}f}}".format(
- separator, LEN_SWITCHED_OUT*fix_csv_align, decimal_precision
- )
- fmt += "{}{{:{}d}}".format(separator, LEN_CPU*fix_csv_align)
- fmt += "{}{{:{}d}}".format(separator, LEN_PID*fix_csv_align)
- fmt += "{}{{}}{{:{}d}}{{}}".format(separator, LEN_TID*fix_csv_align)
- fmt += "{}{{}}{{:>{}}}".format(separator, LEN_COMM*fix_csv_align)
- fmt += "{}{{:{}.{}f}}".format(separator, LEN_RUNTIME*fix_csv_align, time_precision)
- if args.extended_times:
- fmt += "{}{{:{}.{}f}}".format(separator, LEN_OUT_IN*fix_csv_align, time_precision)
- fmt += "{}{{:{}.{}f}}".format(separator, LEN_OUT_OUT*fix_csv_align, time_precision)
- fmt += "{}{{:{}.{}f}}".format(separator, LEN_IN_IN*fix_csv_align, time_precision)
- fmt += "{}{{:{}.{}f}}{{}}".format(
- separator, LEN_IN_OUT*fix_csv_align, time_precision
- )
- else:
- fmt += "{}{{:{}.{}f}}{{}}".format(
- separator, LEN_OUT_IN*fix_csv_align, time_precision
- )
- return fmt
-
-
-def _print_header():
- fmt = _fmt_header()
- header = ("Switched-In", "Switched-Out", "CPU", "PID", "TID", "Comm", "Runtime",
- "Time Out-In")
- if args.extended_times:
- header += ("Time Out-Out", "Time In-In", "Time In-Out")
- fd_task.write(fmt.format(*header) + "\n")
-
-
-
-def _print_task_finish(task):
- """calculating every entry of a row and printing it immediately"""
- c_row_set = ""
- c_row_reset = ""
- out_in = -1
- out_out = -1
- in_in = -1
- in_out = -1
- fmt = _fmt_body()
- # depending on user provided highlight option we change the color
- # for particular tasks
- if str(task.tid) in args.highlight_tasks_map:
- c_row_set = _COLORS[args.highlight_tasks_map[str(task.tid)]]
- c_row_reset = _COLORS["reset"]
- if task.comm in args.highlight_tasks_map:
- c_row_set = _COLORS[args.highlight_tasks_map[task.comm]]
- c_row_reset = _COLORS["reset"]
- # grey-out entries if PID == TID, they
- # are identical, no threaded model so the
- # thread id (tid) do not matter
- c_tid_set = ""
- c_tid_reset = ""
- if task.pid == task.tid:
- c_tid_set = _COLORS["grey"]
- c_tid_reset = _COLORS["reset"]
- if task.tid in db["tid"]:
- # get last task of tid
- last_tid_task = db["tid"][task.tid][-1]
- # feed the timespan calculate, last in tid db
- # and second the current one
- timespan_gap_tid = Timespans()
- timespan_gap_tid.feed(last_tid_task)
- timespan_gap_tid.feed(task)
- out_in = timespan_gap_tid.out_in
- out_out = timespan_gap_tid.out_out
- in_in = timespan_gap_tid.in_in
- in_out = timespan_gap_tid.in_out
-
-
- if args.extended_times:
- line_out = fmt.format(c_row_set, task.time_in(), task.time_out(), task.cpu,
- task.pid, c_tid_set, task.tid, c_tid_reset, c_row_set, task.comm,
- task.runtime(time_unit), out_in, out_out, in_in, in_out,
- c_row_reset) + "\n"
- else:
- line_out = fmt.format(c_row_set, task.time_in(), task.time_out(), task.cpu,
- task.pid, c_tid_set, task.tid, c_tid_reset, c_row_set, task.comm,
- task.runtime(time_unit), out_in, c_row_reset) + "\n"
- try:
- fd_task.write(line_out)
- except(IOError):
- # don't mangle the output if user SIGINT this script
- sys.exit()
-
-def _record_cleanup(_list):
- """
- no need to store more then one element if --summarize
- is not enabled
- """
- if not args.summary and len(_list) > 1:
- _list = _list[len(_list) - 1 :]
-
-
-def _record_by_tid(task):
- tid = task.tid
- if tid not in db["tid"]:
- db["tid"][tid] = []
- db["tid"][tid].append(task)
- _record_cleanup(db["tid"][tid])
-
-
-def _record_by_cpu(task):
- cpu = task.cpu
- if cpu not in db["cpu"]:
- db["cpu"][cpu] = []
- db["cpu"][cpu].append(task)
- _record_cleanup(db["cpu"][cpu])
-
-
-def _record_global(task):
- """record all executed task, ordered by finish chronological"""
- db["global"].append(task)
- _record_cleanup(db["global"])
-
-
-def _handle_task_finish(tid, cpu, time, perf_sample_dict):
- if tid == 0:
- return
- _id = _task_id(tid, cpu)
- if _id not in db["running"]:
- # may happen, if we missed the switch to
- # event. Seen in combination with --exclude-perf
- # where the start is filtered out, but not the
- # switched in. Probably a bug in exclude-perf
- # option.
- return
- task = db["running"][_id]
- task.schedule_out_at(time)
-
- # record tid, during schedule in the tid
- # is not available, update now
- pid = int(perf_sample_dict["sample"]["pid"])
-
- task.update_pid(pid)
- del db["running"][_id]
-
- # print only tasks which are not being filtered and no print of trace
- # for summary only, but record every task.
- if not _limit_filtered(tid, pid, task.comm) and not args.summary_only:
- _print_task_finish(task)
- _record_by_tid(task)
- _record_by_cpu(task)
- _record_global(task)
-
-
-def _handle_task_start(tid, cpu, comm, time):
- if tid == 0:
- return
- if tid in args.tid_renames:
- comm = args.tid_renames[tid]
- _id = _task_id(tid, cpu)
- if _id in db["running"]:
- # handle corner cases where already running tasks
- # are switched-to again - saw this via --exclude-perf
- # recorded traces. We simple ignore this "second start"
- # event.
- return
- assert _id not in db["running"]
- task = Task(_id, tid, cpu, comm)
- task.schedule_in_at(time)
- db["running"][_id] = task
-
-
-def _time_to_internal(time_ns):
- """
- To prevent float rounding errors we use Decimal internally
- """
- return decimal.Decimal(time_ns) / decimal.Decimal(1e9)
-
-
-def _limit_filtered(tid, pid, comm):
- if args.filter_tasks:
- if str(tid) in args.filter_tasks or comm in args.filter_tasks:
- return True
- else:
- return False
- if args.limit_to_tasks:
- if str(tid) in args.limit_to_tasks or comm in args.limit_to_tasks:
- return False
- else:
- return True
-
-
-def _argument_filter_sanity_check():
- if args.limit_to_tasks and args.filter_tasks:
- sys.exit("Error: Filter and Limit at the same time active.")
- if args.extended_times and args.summary_only:
- sys.exit("Error: Summary only and extended times active.")
- if args.time_limit and ":" not in args.time_limit:
- sys.exit(
- "Error: No bound set for time limit. Please set bound by ':' e.g :123."
- )
- if args.time_limit and (args.summary or args.summary_only or args.summary_extended):
- sys.exit("Error: Cannot set time limit and print summary")
- if args.csv_summary:
- args.summary = True
- if args.csv == args.csv_summary:
- sys.exit("Error: Chosen files for csv and csv summary are the same")
- if args.csv and (args.summary_extended or args.summary) and not args.csv_summary:
- sys.exit("Error: No file chosen to write summary to. Choose with --csv-summary "
- "<file>")
- if args.csv and args.summary_only:
- sys.exit("Error: --csv chosen and --summary-only. Standard task would not be"
- "written to csv file.")
-
-def _argument_prepare_check():
- global time_unit, fd_task, fd_sum
- if args.filter_tasks:
- args.filter_tasks = args.filter_tasks.split(",")
- if args.limit_to_tasks:
- args.limit_to_tasks = args.limit_to_tasks.split(",")
- if args.time_limit:
- args.time_limit = args.time_limit.split(":")
- for rename_tuple in args.rename_comms_by_tids.split(","):
- tid_name = rename_tuple.split(":")
- if len(tid_name) != 2:
- continue
- args.tid_renames[int(tid_name[0])] = tid_name[1]
- args.highlight_tasks_map = dict()
- for highlight_tasks_tuple in args.highlight_tasks.split(","):
- tasks_color_map = highlight_tasks_tuple.split(":")
- # default highlight color to red if no color set by user
- if len(tasks_color_map) == 1:
- tasks_color_map.append("red")
- if args.highlight_tasks and tasks_color_map[1].lower() not in _COLORS:
- sys.exit(
- "Error: Color not defined, please choose from grey,red,green,yellow,blue,"
- "violet"
- )
- if len(tasks_color_map) != 2:
- continue
- args.highlight_tasks_map[tasks_color_map[0]] = tasks_color_map[1]
- time_unit = "us"
- if args.ns:
- time_unit = "ns"
- elif args.ms:
- time_unit = "ms"
-
-
- fd_task = sys.stdout
- if args.csv:
- args.stdio_color = "never"
- fd_task = open(args.csv, "w")
- print("generating csv at",args.csv,)
-
- fd_sum = sys.stdout
- if args.csv_summary:
- args.stdio_color = "never"
- fd_sum = open(args.csv_summary, "w")
- print("generating csv summary at",args.csv_summary)
- if not args.csv:
- args.summary_only = True
-
-
-def _is_within_timelimit(time):
- """
- Check if a time limit was given by parameter, if so ignore the rest. If not,
- process the recorded trace in its entirety.
- """
- if not args.time_limit:
- return True
- lower_time_limit = args.time_limit[0]
- upper_time_limit = args.time_limit[1]
- # check for upper limit
- if upper_time_limit == "":
- if time >= decimal.Decimal(lower_time_limit):
- return True
- # check for lower limit
- if lower_time_limit == "":
- if time <= decimal.Decimal(upper_time_limit):
- return True
- # quit if time exceeds upper limit. Good for big datasets
- else:
- quit()
- if lower_time_limit != "" and upper_time_limit != "":
- if (time >= decimal.Decimal(lower_time_limit) and
- time <= decimal.Decimal(upper_time_limit)):
- return True
- # quit if time exceeds upper limit. Good for big datasets
- elif time > decimal.Decimal(upper_time_limit):
- quit()
-
-def _prepare_fmt_precision():
- decimal_precision = 6
- time_precision = 3
- if args.ns:
- decimal_precision = 9
- time_precision = 0
- return decimal_precision, time_precision
-
-def _prepare_fmt_sep():
- separator = " "
- fix_csv_align = 1
- if args.csv or args.csv_summary:
- separator = ";"
- fix_csv_align = 0
- return separator, fix_csv_align
-
-def trace_unhandled(event_name, context, event_fields_dict, perf_sample_dict):
- pass
-
-
-def trace_begin():
- _parse_args()
- _check_color()
- _init_db()
- if not args.summary_only:
- _print_header()
-
-def trace_end():
- if args.summary or args.summary_extended or args.summary_only:
- Summary().print()
-
-def sched__sched_switch(event_name, context, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm, common_callchain, prev_comm,
- prev_pid, prev_prio, prev_state, next_comm, next_pid,
- next_prio, perf_sample_dict):
- # ignore common_secs & common_nsecs cause we need
- # high res timestamp anyway, using the raw value is
- # faster
- time = _time_to_internal(perf_sample_dict["sample"]["time"])
- if not _is_within_timelimit(time):
- # user specific --time-limit a:b set
- return
-
- next_comm = _filter_non_printable(next_comm)
- _handle_task_finish(prev_pid, common_cpu, time, perf_sample_dict)
- _handle_task_start(next_pid, common_cpu, next_comm, time)
diff --git a/tools/perf/tests/shell/script_python.sh b/tools/perf/tests/shell/script_python.sh
deleted file mode 100755
index 6bc66074a31f..000000000000
--- a/tools/perf/tests/shell/script_python.sh
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/bin/bash
-# perf script python tests
-# SPDX-License-Identifier: GPL-2.0
-
-set -e
-
-# set PERF_EXEC_PATH to find scripts in the source directory
-perfdir=$(dirname "$0")/../..
-if [ -e "$perfdir/scripts/python/Perf-Trace-Util" ]; then
- export PERF_EXEC_PATH=$perfdir
-fi
-
-
-perfdata=$(mktemp /tmp/__perf_test_script_python.perf.data.XXXXX)
-generated_script=$(mktemp /tmp/__perf_test_script.XXXXX.py)
-
-cleanup() {
- rm -f "${perfdata}"
- rm -f "${generated_script}"
- trap - EXIT TERM INT
-}
-
-trap_cleanup() {
- echo "Unexpected signal in ${FUNCNAME[1]}"
- cleanup
- exit 1
-}
-trap trap_cleanup TERM INT
-trap cleanup EXIT
-
-check_python_support() {
- if perf check feature -q libpython; then
- return 0
- fi
- echo "perf script python test [Skipped: no libpython support]"
- return 2
-}
-
-test_script() {
- local event_name=$1
- local expected_output=$2
- local record_opts=$3
-
- echo "Testing event: $event_name"
-
- # Try to record. If this fails, it might be permissions or lack of
- # support. Return 2 to indicate "skip this event" rather than "fail
- # test".
- if ! perf record -o "${perfdata}" -e "$event_name" $record_opts -- perf test -w thloop > /dev/null 2>&1; then
- echo "perf script python test [Skipped: failed to record $event_name]"
- return 2
- fi
-
- echo "Generating python script..."
- if ! perf script -i "${perfdata}" -g "${generated_script}"; then
- echo "perf script python test [Failed: script generation for $event_name]"
- return 1
- fi
-
- if [ ! -f "${generated_script}" ]; then
- echo "perf script python test [Failed: script not generated for $event_name]"
- return 1
- fi
-
- # Perf script -g python doesn't generate process_event for generic
- # events so append it manually to test that the callback works.
- if ! grep -q "def process_event" "${generated_script}"; then
- cat <<EOF >> "${generated_script}"
-
-def process_event(param_dict):
- print("param_dict: %s" % param_dict)
-EOF
- fi
-
- echo "Executing python script..."
- output=$(perf script -i "${perfdata}" -s "${generated_script}" 2>&1)
-
- if echo "$output" | grep -q "$expected_output"; then
- echo "perf script python test [Success: $event_name triggered $expected_output]"
- return 0
- else
- echo "perf script python test [Failed: $event_name did not trigger $expected_output]"
- echo "Output was:"
- echo "$output" | head -n 20
- return 1
- fi
-}
-
-check_python_support || exit 2
-
-# Try tracepoint first
-test_script "sched:sched_switch" "sched__sched_switch" "-c 1" && res=0 || res=$?
-
-if [ $res -eq 0 ]; then
- exit 0
-elif [ $res -eq 1 ]; then
- exit 1
-fi
-
-# If tracepoint skipped (res=2), try task-clock
-# For generic events like task-clock, the generated script uses process_event()
-# which prints the param_dict.
-test_script "task-clock" "param_dict" "-c 100" && res=0 || res=$?
-
-if [ $res -eq 0 ]; then
- exit 0
-elif [ $res -eq 1 ]; then
- exit 1
-fi
-
-# If both skipped
-echo "perf script python test [Skipped: Could not record tracepoint or task-clock]"
-exit 2
diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build
index ce14ef44b200..54920e7e1d5d 100644
--- a/tools/perf/util/scripting-engines/Build
+++ b/tools/perf/util/scripting-engines/Build
@@ -1,7 +1 @@
-
-perf-util-$(CONFIG_LIBPYTHON) += trace-event-python.o
-
-
-
-# -Wno-declaration-after-statement: The python headers have mixed code with declarations (decls after asserts, for instance)
-CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-deprecated-declarations -Wno-switch-enum -Wno-declaration-after-statement
+# No embedded scripting engines
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
deleted file mode 100644
index 5a30caaec73e..000000000000
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ /dev/null
@@ -1,2209 +0,0 @@
-/*
- * trace-event-python. Feed trace events to an embedded Python interpreter.
- *
- * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <Python.h>
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <linux/bitmap.h>
-#include <linux/compiler.h>
-#include <linux/time64.h>
-#ifdef HAVE_LIBTRACEEVENT
-#include <event-parse.h>
-#endif
-
-#include "../build-id.h"
-#include "../counts.h"
-#include "../debug.h"
-#include "../dso.h"
-#include "../callchain.h"
-#include "../env.h"
-#include "../evsel.h"
-#include "../event.h"
-#include "../thread.h"
-#include "../comm.h"
-#include "../machine.h"
-#include "../mem-info.h"
-#include "../db-export.h"
-#include "../thread-stack.h"
-#include "../trace-event.h"
-#include "../call-path.h"
-#include "dwarf-regs.h"
-#include "map.h"
-#include "symbol.h"
-#include "thread_map.h"
-#include "print_binary.h"
-#include "stat.h"
-#include "mem-events.h"
-#include "util/perf_regs.h"
-
-#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);
-
-#ifdef HAVE_LIBTRACEEVENT
-#define TRACE_EVENT_TYPE_MAX \
- ((1 << (sizeof(unsigned short) * 8)) - 1)
-
-#define N_COMMON_FIELDS 7
-
-static char *cur_field_name;
-static int zero_flag_atom;
-#endif
-
-#define MAX_FIELDS 64
-
-extern struct scripting_context *scripting_context;
-
-static PyObject *main_module, *main_dict;
-
-struct tables {
- struct db_export dbe;
- PyObject *evsel_handler;
- PyObject *machine_handler;
- PyObject *thread_handler;
- PyObject *comm_handler;
- PyObject *comm_thread_handler;
- PyObject *dso_handler;
- PyObject *symbol_handler;
- PyObject *branch_type_handler;
- PyObject *sample_handler;
- PyObject *call_path_handler;
- PyObject *call_return_handler;
- PyObject *synth_handler;
- PyObject *context_switch_handler;
- bool db_export_mode;
-};
-
-static struct tables tables_global;
-
-static void handler_call_die(const char *handler_name) __noreturn;
-static void handler_call_die(const char *handler_name)
-{
- PyErr_Print();
- Py_FatalError("problem in Python trace event handler");
- // Py_FatalError does not return
- // but we have to make the compiler happy
- abort();
-}
-
-/*
- * Insert val into the dictionary and decrement the reference counter.
- * This is necessary for dictionaries since PyDict_SetItemString() does not
- * steal a reference, as opposed to PyTuple_SetItem().
- */
-static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val)
-{
- PyDict_SetItemString(dict, key, val);
- Py_DECREF(val);
-}
-
-static PyObject *get_handler(const char *handler_name)
-{
- PyObject *handler;
-
- handler = PyDict_GetItemString(main_dict, handler_name);
- if (handler && !PyCallable_Check(handler))
- return NULL;
- return handler;
-}
-
-static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
-{
- PyObject *retval;
-
- retval = PyObject_CallObject(handler, args);
- if (retval == NULL)
- handler_call_die(die_msg);
- Py_DECREF(retval);
-}
-
-static void try_call_object(const char *handler_name, PyObject *args)
-{
- PyObject *handler;
-
- handler = get_handler(handler_name);
- if (handler)
- call_object(handler, args, handler_name);
-}
-
-#ifdef HAVE_LIBTRACEEVENT
-static int get_argument_count(PyObject *handler)
-{
- int arg_count = 0;
-
- PyObject *code_obj = code_obj = PyObject_GetAttrString(handler, "__code__");
- PyErr_Clear();
- if (code_obj) {
- PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
- "co_argcount");
- if (arg_count_obj) {
- arg_count = (int) _PyLong_AsLong(arg_count_obj);
- Py_DECREF(arg_count_obj);
- }
- Py_DECREF(code_obj);
- }
- return arg_count;
-}
-
-static void define_value(enum tep_print_arg_type field_type,
- const char *ev_name,
- const char *field_name,
- const char *field_value,
- const char *field_str)
-{
- const char *handler_name = "define_flag_value";
- PyObject *t;
- unsigned long long value;
- unsigned n = 0;
-
- if (field_type == TEP_PRINT_SYMBOL)
- handler_name = "define_symbolic_value";
-
- t = PyTuple_New(4);
- if (!t)
- Py_FatalError("couldn't create Python tuple");
-
- value = eval_flag(field_value);
-
- 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);
-
- Py_DECREF(t);
-}
-
-static void define_values(enum tep_print_arg_type field_type,
- struct tep_print_flag_sym *field,
- const char *ev_name,
- const char *field_name)
-{
- define_value(field_type, ev_name, field_name, field->value,
- field->str);
-
- if (field->next)
- define_values(field_type, field->next, ev_name, field_name);
-}
-
-static void define_field(enum tep_print_arg_type field_type,
- const char *ev_name,
- const char *field_name,
- const char *delim)
-{
- const char *handler_name = "define_flag_field";
- PyObject *t;
- unsigned n = 0;
-
- if (field_type == TEP_PRINT_SYMBOL)
- handler_name = "define_symbolic_field";
-
- if (field_type == TEP_PRINT_FLAGS)
- t = PyTuple_New(3);
- else
- t = PyTuple_New(2);
- if (!t)
- Py_FatalError("couldn't create Python tuple");
-
- PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name));
- PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name));
- if (field_type == TEP_PRINT_FLAGS)
- PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim));
-
- try_call_object(handler_name, t);
-
- Py_DECREF(t);
-}
-
-static void define_event_symbols(struct tep_event *event,
- const char *ev_name,
- struct tep_print_arg *args)
-{
- if (args == NULL)
- return;
-
- switch (args->type) {
- case TEP_PRINT_NULL:
- break;
- case TEP_PRINT_ATOM:
- define_value(TEP_PRINT_FLAGS, ev_name, cur_field_name, "0",
- args->atom.atom);
- zero_flag_atom = 0;
- break;
- case TEP_PRINT_FIELD:
- free(cur_field_name);
- cur_field_name = strdup(args->field.name);
- break;
- case TEP_PRINT_FLAGS:
- define_event_symbols(event, ev_name, args->flags.field);
- define_field(TEP_PRINT_FLAGS, ev_name, cur_field_name,
- args->flags.delim);
- define_values(TEP_PRINT_FLAGS, args->flags.flags, ev_name,
- cur_field_name);
- break;
- case TEP_PRINT_SYMBOL:
- define_event_symbols(event, ev_name, args->symbol.field);
- define_field(TEP_PRINT_SYMBOL, ev_name, cur_field_name, NULL);
- define_values(TEP_PRINT_SYMBOL, args->symbol.symbols, ev_name,
- cur_field_name);
- break;
- case TEP_PRINT_HEX:
- case TEP_PRINT_HEX_STR:
- define_event_symbols(event, ev_name, args->hex.field);
- define_event_symbols(event, ev_name, args->hex.size);
- break;
- case TEP_PRINT_INT_ARRAY:
- define_event_symbols(event, ev_name, args->int_array.field);
- define_event_symbols(event, ev_name, args->int_array.count);
- define_event_symbols(event, ev_name, args->int_array.el_size);
- break;
- case TEP_PRINT_STRING:
- break;
- case TEP_PRINT_TYPE:
- define_event_symbols(event, ev_name, args->typecast.item);
- break;
- case TEP_PRINT_OP:
- if (strcmp(args->op.op, ":") == 0)
- zero_flag_atom = 1;
- define_event_symbols(event, ev_name, args->op.left);
- define_event_symbols(event, ev_name, args->op.right);
- break;
- default:
- /* gcc warns for these? */
- case TEP_PRINT_BSTRING:
- case TEP_PRINT_DYNAMIC_ARRAY:
- case TEP_PRINT_DYNAMIC_ARRAY_LEN:
- case TEP_PRINT_FUNC:
- case TEP_PRINT_BITMASK:
- /* we should warn... */
- return;
- }
-
- if (args->next)
- define_event_symbols(event, ev_name, args->next);
-}
-
-static PyObject *get_field_numeric_entry(struct tep_event *event,
- struct tep_format_field *field, void *data)
-{
- bool is_array = field->flags & TEP_FIELD_IS_ARRAY;
- PyObject *obj = NULL, *list = NULL;
- unsigned long long val;
- unsigned int item_size, n_items, i;
-
- if (is_array) {
- list = PyList_New(field->arraylen);
- if (!list)
- Py_FatalError("couldn't create Python list");
- item_size = field->size / field->arraylen;
- n_items = field->arraylen;
- } else {
- item_size = field->size;
- n_items = 1;
- }
-
- for (i = 0; i < n_items; i++) {
-
- val = read_size(event, data + field->offset + i * item_size,
- item_size);
- if (field->flags & TEP_FIELD_IS_SIGNED) {
- if ((long long)val >= LONG_MIN &&
- (long long)val <= LONG_MAX)
- obj = _PyLong_FromLong(val);
- else
- obj = PyLong_FromLongLong(val);
- } else {
- if (val <= LONG_MAX)
- obj = _PyLong_FromLong(val);
- else
- obj = PyLong_FromUnsignedLongLong(val);
- }
- if (is_array)
- PyList_SET_ITEM(list, i, obj);
- }
- if (is_array)
- obj = list;
- return obj;
-}
-#endif
-
-static const char *get_dsoname(struct map *map)
-{
- const char *dsoname = "[unknown]";
- struct dso *dso = map ? map__dso(map) : NULL;
-
- if (dso) {
- if (symbol_conf.show_kernel_path && dso__long_name(dso))
- dsoname = dso__long_name(dso);
- else
- dsoname = dso__name(dso);
- }
-
- return dsoname;
-}
-
-static unsigned long get_offset(struct symbol *sym, struct addr_location *al)
-{
- unsigned long offset;
-
- if (al->addr < sym->end)
- offset = al->addr - sym->start;
- else
- offset = al->addr - map__start(al->map) - sym->start;
-
- return offset;
-}
-
-static PyObject *python_process_callchain(struct perf_sample *sample,
- struct evsel *evsel,
- struct addr_location *al)
-{
- PyObject *pylist;
- struct callchain_cursor *cursor;
-
- pylist = PyList_New(0);
- if (!pylist)
- Py_FatalError("couldn't create Python list");
-
- if (!symbol_conf.use_callchain || !sample->callchain)
- goto exit;
-
- cursor = get_tls_callchain_cursor();
- if (thread__resolve_callchain(al->thread, cursor, evsel,
- sample, NULL, NULL,
- scripting_max_stack) != 0) {
- pr_err("Failed to resolve callchain. Skipping\n");
- goto exit;
- }
- callchain_cursor_commit(cursor);
-
-
- while (1) {
- PyObject *pyelem;
- struct callchain_cursor_node *node;
- node = callchain_cursor_current(cursor);
- if (!node)
- break;
-
- pyelem = PyDict_New();
- if (!pyelem)
- Py_FatalError("couldn't create Python dictionary");
-
-
- pydict_set_item_string_decref(pyelem, "ip",
- PyLong_FromUnsignedLongLong(node->ip));
-
- if (node->ms.sym) {
- PyObject *pysym = PyDict_New();
- if (!pysym)
- Py_FatalError("couldn't create Python dictionary");
- pydict_set_item_string_decref(pysym, "start",
- PyLong_FromUnsignedLongLong(node->ms.sym->start));
- pydict_set_item_string_decref(pysym, "end",
- PyLong_FromUnsignedLongLong(node->ms.sym->end));
- pydict_set_item_string_decref(pysym, "binding",
- _PyLong_FromLong(node->ms.sym->binding));
- pydict_set_item_string_decref(pysym, "name",
- _PyUnicode_FromStringAndSize(node->ms.sym->name,
- node->ms.sym->namelen));
- pydict_set_item_string_decref(pyelem, "sym", pysym);
-
- if (node->ms.map) {
- struct map *map = node->ms.map;
- struct addr_location node_al;
- unsigned long offset;
-
- addr_location__init(&node_al);
- node_al.addr = map__map_ip(map, node->ip);
- node_al.map = map__get(map);
- offset = get_offset(node->ms.sym, &node_al);
- addr_location__exit(&node_al);
-
- pydict_set_item_string_decref(
- pyelem, "sym_off",
- PyLong_FromUnsignedLongLong(offset));
- }
- if (node->srcline && strcmp(":0", node->srcline)) {
- pydict_set_item_string_decref(
- pyelem, "sym_srcline",
- _PyUnicode_FromString(node->srcline));
- }
- }
-
- if (node->ms.map) {
- const char *dsoname = get_dsoname(node->ms.map);
-
- pydict_set_item_string_decref(pyelem, "dso",
- _PyUnicode_FromString(dsoname));
- }
-
- callchain_cursor_advance(cursor);
- PyList_Append(pylist, pyelem);
- Py_DECREF(pyelem);
- }
-
-exit:
- return pylist;
-}
-
-static PyObject *python_process_brstack(struct perf_sample *sample,
- struct thread *thread)
-{
- struct branch_stack *br = sample->branch_stack;
- struct branch_entry *entries = perf_sample__branch_entries(sample);
- PyObject *pylist;
- u64 i;
-
- pylist = PyList_New(0);
- if (!pylist)
- Py_FatalError("couldn't create Python list");
-
- if (!(br && br->nr))
- goto exit;
-
- for (i = 0; i < br->nr; i++) {
- PyObject *pyelem;
- struct addr_location al;
- const char *dsoname;
-
- pyelem = PyDict_New();
- if (!pyelem)
- Py_FatalError("couldn't create Python dictionary");
-
- pydict_set_item_string_decref(pyelem, "from",
- PyLong_FromUnsignedLongLong(entries[i].from));
- pydict_set_item_string_decref(pyelem, "to",
- PyLong_FromUnsignedLongLong(entries[i].to));
- pydict_set_item_string_decref(pyelem, "mispred",
- PyBool_FromLong(entries[i].flags.mispred));
- pydict_set_item_string_decref(pyelem, "predicted",
- PyBool_FromLong(entries[i].flags.predicted));
- pydict_set_item_string_decref(pyelem, "in_tx",
- PyBool_FromLong(entries[i].flags.in_tx));
- pydict_set_item_string_decref(pyelem, "abort",
- PyBool_FromLong(entries[i].flags.abort));
- pydict_set_item_string_decref(pyelem, "cycles",
- PyLong_FromUnsignedLongLong(entries[i].flags.cycles));
-
- addr_location__init(&al);
- thread__find_map_fb(thread, sample->cpumode,
- entries[i].from, &al);
- dsoname = get_dsoname(al.map);
- pydict_set_item_string_decref(pyelem, "from_dsoname",
- _PyUnicode_FromString(dsoname));
-
- thread__find_map_fb(thread, sample->cpumode,
- entries[i].to, &al);
- dsoname = get_dsoname(al.map);
- pydict_set_item_string_decref(pyelem, "to_dsoname",
- _PyUnicode_FromString(dsoname));
-
- addr_location__exit(&al);
- PyList_Append(pylist, pyelem);
- Py_DECREF(pyelem);
- }
-
-exit:
- return pylist;
-}
-
-static int get_symoff(struct symbol *sym, struct addr_location *al,
- bool print_off, char *bf, int size)
-{
- unsigned long offset;
-
- if (!sym || !sym->name[0])
- return scnprintf(bf, size, "%s", "[unknown]");
-
- if (!print_off)
- return scnprintf(bf, size, "%s", sym->name);
-
- offset = get_offset(sym, al);
-
- return scnprintf(bf, size, "%s+0x%x", sym->name, offset);
-}
-
-static int get_br_mspred(struct branch_flags *flags, char *bf, int size)
-{
- if (!flags->mispred && !flags->predicted)
- return scnprintf(bf, size, "%s", "-");
-
- if (flags->mispred)
- return scnprintf(bf, size, "%s", "M");
-
- return scnprintf(bf, size, "%s", "P");
-}
-
-static PyObject *python_process_brstacksym(struct perf_sample *sample,
- struct thread *thread)
-{
- struct branch_stack *br = sample->branch_stack;
- struct branch_entry *entries = perf_sample__branch_entries(sample);
- PyObject *pylist;
- u64 i;
- char bf[512];
-
- pylist = PyList_New(0);
- if (!pylist)
- Py_FatalError("couldn't create Python list");
-
- if (!(br && br->nr))
- goto exit;
-
- for (i = 0; i < br->nr; i++) {
- PyObject *pyelem;
- struct addr_location al;
-
- addr_location__init(&al);
- pyelem = PyDict_New();
- if (!pyelem)
- Py_FatalError("couldn't create Python dictionary");
-
- thread__find_symbol_fb(thread, sample->cpumode,
- entries[i].from, &al);
- get_symoff(al.sym, &al, true, bf, sizeof(bf));
- pydict_set_item_string_decref(pyelem, "from",
- _PyUnicode_FromString(bf));
-
- thread__find_symbol_fb(thread, sample->cpumode,
- entries[i].to, &al);
- get_symoff(al.sym, &al, true, bf, sizeof(bf));
- pydict_set_item_string_decref(pyelem, "to",
- _PyUnicode_FromString(bf));
-
- get_br_mspred(&entries[i].flags, bf, sizeof(bf));
- pydict_set_item_string_decref(pyelem, "pred",
- _PyUnicode_FromString(bf));
-
- if (entries[i].flags.in_tx) {
- pydict_set_item_string_decref(pyelem, "in_tx",
- _PyUnicode_FromString("X"));
- } else {
- pydict_set_item_string_decref(pyelem, "in_tx",
- _PyUnicode_FromString("-"));
- }
-
- if (entries[i].flags.abort) {
- pydict_set_item_string_decref(pyelem, "abort",
- _PyUnicode_FromString("A"));
- } else {
- pydict_set_item_string_decref(pyelem, "abort",
- _PyUnicode_FromString("-"));
- }
-
- PyList_Append(pylist, pyelem);
- Py_DECREF(pyelem);
- addr_location__exit(&al);
- }
-
-exit:
- return pylist;
-}
-
-static PyObject *get_sample_value_as_tuple(struct sample_read_value *value,
- u64 read_format)
-{
- PyObject *t;
-
- t = PyTuple_New(3);
- if (!t)
- Py_FatalError("couldn't create Python tuple");
- PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
- PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
- if (read_format & PERF_FORMAT_LOST)
- PyTuple_SetItem(t, 2, PyLong_FromUnsignedLongLong(value->lost));
-
- return t;
-}
-
-static void set_sample_read_in_dict(PyObject *dict_sample,
- struct perf_sample *sample,
- struct evsel *evsel)
-{
- u64 read_format = evsel->core.attr.read_format;
- PyObject *values;
- unsigned int i;
-
- if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
- pydict_set_item_string_decref(dict_sample, "time_enabled",
- PyLong_FromUnsignedLongLong(sample->read.time_enabled));
- }
-
- if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
- pydict_set_item_string_decref(dict_sample, "time_running",
- PyLong_FromUnsignedLongLong(sample->read.time_running));
- }
-
- if (read_format & PERF_FORMAT_GROUP)
- values = PyList_New(sample->read.group.nr);
- else
- values = PyList_New(1);
-
- if (!values)
- Py_FatalError("couldn't create Python list");
-
- if (read_format & PERF_FORMAT_GROUP) {
- struct sample_read_value *v = sample->read.group.values;
-
- i = 0;
- sample_read_group__for_each(v, sample->read.group.nr, read_format) {
- PyObject *t = get_sample_value_as_tuple(v, read_format);
- PyList_SET_ITEM(values, i, t);
- i++;
- }
- } else {
- PyObject *t = get_sample_value_as_tuple(&sample->read.one,
- read_format);
- PyList_SET_ITEM(values, 0, t);
- }
- pydict_set_item_string_decref(dict_sample, "values", values);
-}
-
-static void set_sample_datasrc_in_dict(PyObject *dict,
- struct perf_sample *sample)
-{
- struct mem_info *mi = mem_info__new();
- char decode[100];
-
- if (!mi)
- Py_FatalError("couldn't create mem-info");
-
- pydict_set_item_string_decref(dict, "datasrc",
- PyLong_FromUnsignedLongLong(sample->data_src));
-
- mem_info__data_src(mi)->val = sample->data_src;
- perf_script__meminfo_scnprintf(decode, 100, mi);
- mem_info__put(mi);
-
- pydict_set_item_string_decref(dict, "datasrc_decode",
- _PyUnicode_FromString(decode));
-}
-
-static void regs_map(struct regs_dump *regs, uint64_t mask, uint16_t e_machine, uint32_t e_flags,
- char *bf, int size)
-{
- unsigned int i = 0, r;
- int printed = 0;
-
- bf[0] = 0;
-
- if (size <= 0)
- return;
-
- if (!regs || !regs->regs)
- return;
-
- for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
- u64 val = regs->regs[i++];
-
- printed += scnprintf(bf + printed, size - printed,
- "%5s:0x%" PRIx64 " ",
- perf_reg_name(r, e_machine, e_flags), val);
- }
-}
-
-#define MAX_REG_SIZE 128
-
-static int set_regs_in_dict(PyObject *dict,
- struct perf_sample *sample,
- struct evsel *evsel,
- uint16_t e_machine,
- uint32_t e_flags)
-{
- struct perf_event_attr *attr = &evsel->core.attr;
-
- int size = (__sw_hweight64(attr->sample_regs_intr) * MAX_REG_SIZE) + 1;
- char *bf = NULL;
-
- if (sample->intr_regs) {
- bf = malloc(size);
- if (!bf)
- return -1;
-
- regs_map(sample->intr_regs, attr->sample_regs_intr, e_machine, e_flags, bf, size);
-
- pydict_set_item_string_decref(dict, "iregs",
- _PyUnicode_FromString(bf));
- }
-
- if (sample->user_regs) {
- if (!bf) {
- bf = malloc(size);
- if (!bf)
- return -1;
- }
- regs_map(sample->user_regs, attr->sample_regs_user, e_machine, e_flags, bf, size);
-
- pydict_set_item_string_decref(dict, "uregs",
- _PyUnicode_FromString(bf));
- }
- free(bf);
-
- return 0;
-}
-
-static void set_sym_in_dict(PyObject *dict, struct addr_location *al,
- const char *dso_field, const char *dso_bid_field,
- const char *dso_map_start, const char *dso_map_end,
- const char *sym_field, const char *symoff_field,
- const char *map_pgoff)
-{
- if (al->map) {
- char sbuild_id[SBUILD_ID_SIZE];
- struct dso *dso = map__dso(al->map);
-
- pydict_set_item_string_decref(dict, dso_field,
- _PyUnicode_FromString(dso__name(dso)));
- build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
- pydict_set_item_string_decref(dict, dso_bid_field,
- _PyUnicode_FromString(sbuild_id));
- pydict_set_item_string_decref(dict, dso_map_start,
- PyLong_FromUnsignedLong(map__start(al->map)));
- pydict_set_item_string_decref(dict, dso_map_end,
- PyLong_FromUnsignedLong(map__end(al->map)));
- pydict_set_item_string_decref(dict, map_pgoff,
- PyLong_FromUnsignedLongLong(map__pgoff(al->map)));
- }
- if (al->sym) {
- pydict_set_item_string_decref(dict, sym_field,
- _PyUnicode_FromString(al->sym->name));
- pydict_set_item_string_decref(dict, symoff_field,
- PyLong_FromUnsignedLong(get_offset(al->sym, al)));
- }
-}
-
-static void set_sample_flags(PyObject *dict, u32 flags)
-{
- const char *ch = PERF_IP_FLAG_CHARS;
- char *p, str[33];
-
- for (p = str; *ch; ch++, flags >>= 1) {
- if (flags & 1)
- *p++ = *ch;
- }
- *p = 0;
- pydict_set_item_string_decref(dict, "flags", _PyUnicode_FromString(str));
-}
-
-static void python_process_sample_flags(struct perf_sample *sample, PyObject *dict_sample)
-{
- char flags_disp[SAMPLE_FLAGS_BUF_SIZE];
-
- set_sample_flags(dict_sample, sample->flags);
- perf_sample__sprintf_flags(sample->flags, flags_disp, sizeof(flags_disp));
- pydict_set_item_string_decref(dict_sample, "flags_disp",
- _PyUnicode_FromString(flags_disp));
-}
-
-static PyObject *get_perf_sample_dict(struct perf_sample *sample,
- struct evsel *evsel,
- struct addr_location *al,
- struct addr_location *addr_al,
- PyObject *callchain)
-{
- PyObject *dict, *dict_sample, *brstack, *brstacksym;
- uint16_t e_machine = EM_HOST;
- uint32_t e_flags = EF_HOST;
-
- dict = PyDict_New();
- if (!dict)
- Py_FatalError("couldn't create Python dictionary");
-
- dict_sample = PyDict_New();
- if (!dict_sample)
- Py_FatalError("couldn't create Python dictionary");
-
- pydict_set_item_string_decref(dict, "ev_name", _PyUnicode_FromString(evsel__name(evsel)));
- pydict_set_item_string_decref(dict, "attr", _PyBytes_FromStringAndSize((const char *)&evsel->core.attr, sizeof(evsel->core.attr)));
-
- pydict_set_item_string_decref(dict_sample, "id",
- PyLong_FromUnsignedLongLong(sample->id));
- pydict_set_item_string_decref(dict_sample, "stream_id",
- PyLong_FromUnsignedLongLong(sample->stream_id));
- pydict_set_item_string_decref(dict_sample, "pid",
- _PyLong_FromLong(sample->pid));
- pydict_set_item_string_decref(dict_sample, "tid",
- _PyLong_FromLong(sample->tid));
- pydict_set_item_string_decref(dict_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",
- PyLong_FromUnsignedLongLong(sample->time));
- pydict_set_item_string_decref(dict_sample, "period",
- PyLong_FromUnsignedLongLong(sample->period));
- pydict_set_item_string_decref(dict_sample, "phys_addr",
- PyLong_FromUnsignedLongLong(sample->phys_addr));
- pydict_set_item_string_decref(dict_sample, "addr",
- PyLong_FromUnsignedLongLong(sample->addr));
- set_sample_read_in_dict(dict_sample, sample, evsel);
- pydict_set_item_string_decref(dict_sample, "weight",
- PyLong_FromUnsignedLongLong(sample->weight));
- pydict_set_item_string_decref(dict_sample, "ins_lat",
- PyLong_FromUnsignedLong(sample->ins_lat));
- pydict_set_item_string_decref(dict_sample, "transaction",
- PyLong_FromUnsignedLongLong(sample->transaction));
- set_sample_datasrc_in_dict(dict_sample, sample);
- pydict_set_item_string_decref(dict, "sample", dict_sample);
-
- 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",
- _PyUnicode_FromString(thread__comm_str(al->thread)));
- set_sym_in_dict(dict, al, "dso", "dso_bid", "dso_map_start", "dso_map_end",
- "symbol", "symoff", "map_pgoff");
-
- pydict_set_item_string_decref(dict, "callchain", callchain);
-
- brstack = python_process_brstack(sample, al->thread);
- pydict_set_item_string_decref(dict, "brstack", brstack);
-
- brstacksym = python_process_brstacksym(sample, al->thread);
- pydict_set_item_string_decref(dict, "brstacksym", brstacksym);
-
- if (sample->machine_pid) {
- pydict_set_item_string_decref(dict_sample, "machine_pid",
- _PyLong_FromLong(sample->machine_pid));
- pydict_set_item_string_decref(dict_sample, "vcpu",
- _PyLong_FromLong(sample->vcpu));
- }
-
- pydict_set_item_string_decref(dict_sample, "cpumode",
- _PyLong_FromLong((unsigned long)sample->cpumode));
-
- if (addr_al) {
- pydict_set_item_string_decref(dict_sample, "addr_correlates_sym",
- PyBool_FromLong(1));
- set_sym_in_dict(dict_sample, addr_al, "addr_dso", "addr_dso_bid",
- "addr_dso_map_start", "addr_dso_map_end",
- "addr_symbol", "addr_symoff", "addr_map_pgoff");
- }
-
- if (sample->flags)
- python_process_sample_flags(sample, dict_sample);
-
- /* Instructions per cycle (IPC) */
- if (sample->insn_cnt && sample->cyc_cnt) {
- pydict_set_item_string_decref(dict_sample, "insn_cnt",
- PyLong_FromUnsignedLongLong(sample->insn_cnt));
- pydict_set_item_string_decref(dict_sample, "cyc_cnt",
- PyLong_FromUnsignedLongLong(sample->cyc_cnt));
- }
-
- if (al->thread)
- e_machine = thread__e_machine(al->thread, /*machine=*/NULL, &e_flags);
-
- if (set_regs_in_dict(dict, sample, evsel, e_machine, e_flags))
- Py_FatalError("Failed to setting regs in dict");
-
- return dict;
-}
-
-#ifdef HAVE_LIBTRACEEVENT
-static void python_process_tracepoint(struct perf_sample *sample,
- struct evsel *evsel,
- struct addr_location *al,
- struct addr_location *addr_al)
-{
- struct tep_event *event;
- PyObject *handler, *context, *t, *obj = NULL, *callchain;
- PyObject *dict = NULL, *all_entries_dict = NULL;
- static char handler_name[256];
- struct tep_format_field *field;
- unsigned long s, ns;
- unsigned n = 0;
- int pid;
- int cpu = sample->cpu;
- void *data = sample->raw_data;
- unsigned long long nsecs = sample->time;
- const char *comm = thread__comm_str(al->thread);
- const char *default_handler_name = "trace_unhandled";
- DECLARE_BITMAP(events_defined, TRACE_EVENT_TYPE_MAX);
-
- bitmap_zero(events_defined, TRACE_EVENT_TYPE_MAX);
-
- event = evsel__tp_format(evsel);
- if (!event) {
- snprintf(handler_name, sizeof(handler_name),
- "ug! no event found for type %" PRIu64, (u64)evsel->core.attr.config);
- Py_FatalError(handler_name);
- }
-
- pid = raw_field_value(event, "common_pid", data);
-
- sprintf(handler_name, "%s__%s", event->system, event->name);
-
- if (!__test_and_set_bit(event->id, events_defined))
- define_event_symbols(event, handler_name, event->print_fmt.args);
-
- handler = get_handler(handler_name);
- if (!handler) {
- handler = get_handler(default_handler_name);
- if (!handler)
- return;
- dict = PyDict_New();
- if (!dict)
- Py_FatalError("couldn't create Python dict");
- }
-
- t = PyTuple_New(MAX_FIELDS);
- if (!t)
- Py_FatalError("couldn't create Python tuple");
-
-
- s = nsecs / NSEC_PER_SEC;
- ns = nsecs - s * NSEC_PER_SEC;
-
- context = _PyCapsule_New(scripting_context, NULL, NULL);
-
- PyTuple_SetItem(t, n++, _PyUnicode_FromString(handler_name));
- PyTuple_SetItem(t, n++, context);
-
- /* ip unwinding */
- callchain = python_process_callchain(sample, evsel, al);
- /* Need an additional reference for the perf_sample dict */
- Py_INCREF(callchain);
-
- if (!dict) {
- 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", _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) {
- unsigned int offset, len;
- unsigned long long val;
-
- if (field->flags & TEP_FIELD_IS_ARRAY) {
- offset = field->offset;
- len = field->size;
- if (field->flags & TEP_FIELD_IS_DYNAMIC) {
- val = tep_read_number(scripting_context->pevent,
- data + offset, len);
- offset = val;
- len = offset >> 16;
- offset &= 0xffff;
- if (tep_field_is_relative(field->flags))
- offset += field->offset + field->size;
- }
- if (field->flags & TEP_FIELD_IS_STRING &&
- is_printable_array(data + offset, len)) {
- obj = _PyUnicode_FromString((char *) data + offset);
- } else {
- obj = PyByteArray_FromStringAndSize((const char *) data + offset, len);
- field->flags &= ~TEP_FIELD_IS_STRING;
- }
- } else { /* FIELD_IS_NUMERIC */
- obj = get_field_numeric_entry(event, field, data);
- }
- if (!dict)
- PyTuple_SetItem(t, n++, obj);
- else
- pydict_set_item_string_decref(dict, field->name, obj);
-
- }
-
- if (dict)
- PyTuple_SetItem(t, n++, dict);
-
- if (get_argument_count(handler) == (int) n + 1) {
- all_entries_dict = get_perf_sample_dict(sample, evsel, al, addr_al,
- callchain);
- PyTuple_SetItem(t, n++, all_entries_dict);
- } else {
- Py_DECREF(callchain);
- }
-
- if (_PyTuple_Resize(&t, n) == -1)
- Py_FatalError("error resizing Python tuple");
-
- if (!dict)
- call_object(handler, t, handler_name);
- else
- call_object(handler, t, default_handler_name);
-
- Py_DECREF(t);
-}
-#else
-static void python_process_tracepoint(struct perf_sample *sample __maybe_unused,
- struct evsel *evsel __maybe_unused,
- struct addr_location *al __maybe_unused,
- struct addr_location *addr_al __maybe_unused)
-{
- fprintf(stderr, "Tracepoint events are not supported because "
- "perf is not linked with libtraceevent.\n");
-}
-#endif
-
-static PyObject *tuple_new(unsigned int sz)
-{
- PyObject *t;
-
- t = PyTuple_New(sz);
- if (!t)
- Py_FatalError("couldn't create Python tuple");
- return t;
-}
-
-static int tuple_set_s64(PyObject *t, unsigned int pos, s64 val)
-{
-#if BITS_PER_LONG == 64
- return PyTuple_SetItem(t, pos, _PyLong_FromLong(val));
-#endif
-#if BITS_PER_LONG == 32
- return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val));
-#endif
-}
-
-/*
- * Databases support only signed 64-bit numbers, so even though we are
- * exporting a u64, it must be as s64.
- */
-#define tuple_set_d64 tuple_set_s64
-
-static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
-{
-#if BITS_PER_LONG == 64
- return PyTuple_SetItem(t, pos, PyLong_FromUnsignedLong(val));
-#endif
-#if BITS_PER_LONG == 32
- return PyTuple_SetItem(t, pos, PyLong_FromUnsignedLongLong(val));
-#endif
-}
-
-static int tuple_set_u32(PyObject *t, unsigned int pos, u32 val)
-{
- return PyTuple_SetItem(t, pos, PyLong_FromUnsignedLong(val));
-}
-
-static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val)
-{
- return PyTuple_SetItem(t, pos, _PyLong_FromLong(val));
-}
-
-static int tuple_set_bool(PyObject *t, unsigned int pos, bool val)
-{
- return PyTuple_SetItem(t, pos, PyBool_FromLong(val));
-}
-
-static int tuple_set_string(PyObject *t, unsigned int pos, const char *s)
-{
- return PyTuple_SetItem(t, pos, _PyUnicode_FromString(s));
-}
-
-static int tuple_set_bytes(PyObject *t, unsigned int pos, void *bytes,
- unsigned int sz)
-{
- return PyTuple_SetItem(t, pos, _PyBytes_FromStringAndSize(bytes, sz));
-}
-
-static int python_export_evsel(struct db_export *dbe, struct evsel *evsel)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- PyObject *t;
-
- t = tuple_new(2);
-
- tuple_set_d64(t, 0, evsel->db_id);
- tuple_set_string(t, 1, evsel__name(evsel));
-
- call_object(tables->evsel_handler, t, "evsel_table");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static int python_export_machine(struct db_export *dbe,
- struct machine *machine)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- PyObject *t;
-
- t = tuple_new(3);
-
- tuple_set_d64(t, 0, machine->db_id);
- tuple_set_s32(t, 1, machine->pid);
- tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : "");
-
- call_object(tables->machine_handler, t, "machine_table");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static int python_export_thread(struct db_export *dbe, struct thread *thread,
- u64 main_thread_db_id, struct machine *machine)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- PyObject *t;
-
- t = tuple_new(5);
-
- tuple_set_d64(t, 0, thread__db_id(thread));
- tuple_set_d64(t, 1, machine->db_id);
- tuple_set_d64(t, 2, main_thread_db_id);
- tuple_set_s32(t, 3, thread__pid(thread));
- tuple_set_s32(t, 4, thread__tid(thread));
-
- call_object(tables->thread_handler, t, "thread_table");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static int python_export_comm(struct db_export *dbe, struct comm *comm,
- struct thread *thread)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- PyObject *t;
-
- t = tuple_new(5);
-
- tuple_set_d64(t, 0, comm->db_id);
- tuple_set_string(t, 1, comm__str(comm));
- tuple_set_d64(t, 2, thread__db_id(thread));
- tuple_set_d64(t, 3, comm->start);
- tuple_set_s32(t, 4, comm->exec);
-
- call_object(tables->comm_handler, t, "comm_table");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static int python_export_comm_thread(struct db_export *dbe, u64 db_id,
- struct comm *comm, struct thread *thread)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- PyObject *t;
-
- t = tuple_new(3);
-
- tuple_set_d64(t, 0, db_id);
- tuple_set_d64(t, 1, comm->db_id);
- tuple_set_d64(t, 2, thread__db_id(thread));
-
- call_object(tables->comm_thread_handler, t, "comm_thread_table");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static int python_export_dso(struct db_export *dbe, struct dso *dso,
- struct machine *machine)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- char sbuild_id[SBUILD_ID_SIZE];
- PyObject *t;
-
- build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
-
- t = tuple_new(5);
-
- tuple_set_d64(t, 0, dso__db_id(dso));
- tuple_set_d64(t, 1, machine->db_id);
- tuple_set_string(t, 2, dso__short_name(dso));
- tuple_set_string(t, 3, dso__long_name(dso));
- tuple_set_string(t, 4, sbuild_id);
-
- call_object(tables->dso_handler, t, "dso_table");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static int python_export_symbol(struct db_export *dbe, struct symbol *sym,
- struct dso *dso)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- u64 *sym_db_id = symbol__priv(sym);
- PyObject *t;
-
- t = tuple_new(6);
-
- tuple_set_d64(t, 0, *sym_db_id);
- tuple_set_d64(t, 1, dso__db_id(dso));
- tuple_set_d64(t, 2, sym->start);
- tuple_set_d64(t, 3, sym->end);
- tuple_set_s32(t, 4, sym->binding);
- tuple_set_string(t, 5, sym->name);
-
- call_object(tables->symbol_handler, t, "symbol_table");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static int python_export_branch_type(struct db_export *dbe, u32 branch_type,
- const char *name)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- PyObject *t;
-
- t = tuple_new(2);
-
- tuple_set_s32(t, 0, branch_type);
- tuple_set_string(t, 1, name);
-
- call_object(tables->branch_type_handler, t, "branch_type_table");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static void python_export_sample_table(struct db_export *dbe,
- struct export_sample *es)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- PyObject *t;
-
- t = tuple_new(28);
-
- tuple_set_d64(t, 0, es->db_id);
- tuple_set_d64(t, 1, es->evsel->db_id);
- tuple_set_d64(t, 2, maps__machine(thread__maps(es->al->thread))->db_id);
- tuple_set_d64(t, 3, thread__db_id(es->al->thread));
- tuple_set_d64(t, 4, es->comm_db_id);
- tuple_set_d64(t, 5, es->dso_db_id);
- tuple_set_d64(t, 6, es->sym_db_id);
- tuple_set_d64(t, 7, es->offset);
- tuple_set_d64(t, 8, es->sample->ip);
- tuple_set_d64(t, 9, es->sample->time);
- tuple_set_s32(t, 10, es->sample->cpu);
- tuple_set_d64(t, 11, es->addr_dso_db_id);
- tuple_set_d64(t, 12, es->addr_sym_db_id);
- tuple_set_d64(t, 13, es->addr_offset);
- tuple_set_d64(t, 14, es->sample->addr);
- tuple_set_d64(t, 15, es->sample->period);
- tuple_set_d64(t, 16, es->sample->weight);
- tuple_set_d64(t, 17, es->sample->transaction);
- tuple_set_d64(t, 18, es->sample->data_src);
- tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK);
- tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX));
- tuple_set_d64(t, 21, es->call_path_id);
- tuple_set_d64(t, 22, es->sample->insn_cnt);
- tuple_set_d64(t, 23, es->sample->cyc_cnt);
- tuple_set_s32(t, 24, es->sample->flags);
- tuple_set_d64(t, 25, es->sample->id);
- tuple_set_d64(t, 26, es->sample->stream_id);
- tuple_set_u32(t, 27, es->sample->ins_lat);
-
- call_object(tables->sample_handler, t, "sample_table");
-
- Py_DECREF(t);
-}
-
-static void python_export_synth(struct db_export *dbe, struct export_sample *es)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- PyObject *t;
-
- t = tuple_new(3);
-
- tuple_set_d64(t, 0, es->db_id);
- tuple_set_d64(t, 1, es->evsel->core.attr.config);
- tuple_set_bytes(t, 2, es->sample->raw_data, es->sample->raw_size);
-
- call_object(tables->synth_handler, t, "synth_data");
-
- Py_DECREF(t);
-}
-
-static int python_export_sample(struct db_export *dbe,
- struct export_sample *es)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
-
- python_export_sample_table(dbe, es);
-
- if (es->evsel->core.attr.type == PERF_TYPE_SYNTH && tables->synth_handler)
- python_export_synth(dbe, es);
-
- return 0;
-}
-
-static int python_export_call_path(struct db_export *dbe, struct call_path *cp)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- PyObject *t;
- u64 parent_db_id, sym_db_id;
-
- parent_db_id = cp->parent ? cp->parent->db_id : 0;
- sym_db_id = cp->sym ? *(u64 *)symbol__priv(cp->sym) : 0;
-
- t = tuple_new(4);
-
- tuple_set_d64(t, 0, cp->db_id);
- tuple_set_d64(t, 1, parent_db_id);
- tuple_set_d64(t, 2, sym_db_id);
- tuple_set_d64(t, 3, cp->ip);
-
- call_object(tables->call_path_handler, t, "call_path_table");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static int python_export_call_return(struct db_export *dbe,
- struct call_return *cr)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- u64 comm_db_id = cr->comm ? cr->comm->db_id : 0;
- PyObject *t;
-
- t = tuple_new(14);
-
- tuple_set_d64(t, 0, cr->db_id);
- tuple_set_d64(t, 1, thread__db_id(cr->thread));
- tuple_set_d64(t, 2, comm_db_id);
- tuple_set_d64(t, 3, cr->cp->db_id);
- tuple_set_d64(t, 4, cr->call_time);
- tuple_set_d64(t, 5, cr->return_time);
- tuple_set_d64(t, 6, cr->branch_count);
- tuple_set_d64(t, 7, cr->call_ref);
- tuple_set_d64(t, 8, cr->return_ref);
- tuple_set_d64(t, 9, cr->cp->parent->db_id);
- tuple_set_s32(t, 10, cr->flags);
- tuple_set_d64(t, 11, cr->parent_db_id);
- tuple_set_d64(t, 12, cr->insn_count);
- tuple_set_d64(t, 13, cr->cyc_count);
-
- call_object(tables->call_return_handler, t, "call_return_table");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static int python_export_context_switch(struct db_export *dbe, u64 db_id,
- struct machine *machine,
- struct perf_sample *sample,
- u64 th_out_id, u64 comm_out_id,
- u64 th_in_id, u64 comm_in_id, int flags)
-{
- struct tables *tables = container_of(dbe, struct tables, dbe);
- PyObject *t;
-
- t = tuple_new(9);
-
- tuple_set_d64(t, 0, db_id);
- tuple_set_d64(t, 1, machine->db_id);
- tuple_set_d64(t, 2, sample->time);
- tuple_set_s32(t, 3, sample->cpu);
- tuple_set_d64(t, 4, th_out_id);
- tuple_set_d64(t, 5, comm_out_id);
- tuple_set_d64(t, 6, th_in_id);
- tuple_set_d64(t, 7, comm_in_id);
- tuple_set_s32(t, 8, flags);
-
- call_object(tables->context_switch_handler, t, "context_switch");
-
- Py_DECREF(t);
-
- return 0;
-}
-
-static int python_process_call_return(struct call_return *cr, u64 *parent_db_id,
- void *data)
-{
- struct db_export *dbe = data;
-
- return db_export__call_return(dbe, cr, parent_db_id);
-}
-
-static void python_process_general_event(struct perf_sample *sample,
- struct evsel *evsel,
- struct addr_location *al,
- struct addr_location *addr_al)
-{
- PyObject *handler, *t, *dict, *callchain;
- static char handler_name[64];
- unsigned n = 0;
-
- snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
-
- handler = get_handler(handler_name);
- if (!handler)
- return;
-
- /*
- * Use the MAX_FIELDS to make the function expandable, though
- * currently there is only one item for the tuple.
- */
- t = PyTuple_New(MAX_FIELDS);
- if (!t)
- Py_FatalError("couldn't create Python tuple");
-
- /* ip unwinding */
- callchain = python_process_callchain(sample, evsel, al);
- dict = get_perf_sample_dict(sample, evsel, al, addr_al, callchain);
-
- PyTuple_SetItem(t, n++, dict);
- if (_PyTuple_Resize(&t, n) == -1)
- Py_FatalError("error resizing Python tuple");
-
- call_object(handler, t, handler_name);
-
- Py_DECREF(t);
-}
-
-static void python_process_event(union perf_event *event,
- struct perf_sample *sample,
- struct evsel *evsel,
- struct addr_location *al,
- struct addr_location *addr_al)
-{
- struct tables *tables = &tables_global;
-
- scripting_context__update(scripting_context, event, sample, evsel, al, addr_al);
-
- switch (evsel->core.attr.type) {
- case PERF_TYPE_TRACEPOINT:
- python_process_tracepoint(sample, evsel, al, addr_al);
- break;
- /* Reserve for future process_hw/sw/raw APIs */
- default:
- if (tables->db_export_mode)
- db_export__sample(&tables->dbe, event, sample, evsel, al, addr_al);
- else
- python_process_general_event(sample, evsel, al, addr_al);
- }
-}
-
-static void python_process_throttle(union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine)
-{
- const char *handler_name;
- PyObject *handler, *t;
-
- if (event->header.type == PERF_RECORD_THROTTLE)
- handler_name = "throttle";
- else
- handler_name = "unthrottle";
- handler = get_handler(handler_name);
- if (!handler)
- return;
-
- t = tuple_new(6);
- if (!t)
- return;
-
- tuple_set_u64(t, 0, event->throttle.time);
- tuple_set_u64(t, 1, event->throttle.id);
- tuple_set_u64(t, 2, event->throttle.stream_id);
- tuple_set_s32(t, 3, sample->cpu);
- tuple_set_s32(t, 4, sample->pid);
- tuple_set_s32(t, 5, sample->tid);
-
- call_object(handler, t, handler_name);
-
- Py_DECREF(t);
-}
-
-static void python_do_process_switch(union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine)
-{
- const char *handler_name = "context_switch";
- bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
- bool out_preempt = out && (event->header.misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT);
- pid_t np_pid = -1, np_tid = -1;
- PyObject *handler, *t;
-
- handler = get_handler(handler_name);
- if (!handler)
- return;
-
- if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) {
- np_pid = event->context_switch.next_prev_pid;
- np_tid = event->context_switch.next_prev_tid;
- }
-
- t = tuple_new(11);
- if (!t)
- return;
-
- tuple_set_u64(t, 0, sample->time);
- tuple_set_s32(t, 1, sample->cpu);
- tuple_set_s32(t, 2, sample->pid);
- tuple_set_s32(t, 3, sample->tid);
- tuple_set_s32(t, 4, np_pid);
- tuple_set_s32(t, 5, np_tid);
- tuple_set_s32(t, 6, machine->pid);
- tuple_set_bool(t, 7, out);
- tuple_set_bool(t, 8, out_preempt);
- tuple_set_s32(t, 9, sample->machine_pid);
- tuple_set_s32(t, 10, sample->vcpu);
-
- call_object(handler, t, handler_name);
-
- Py_DECREF(t);
-}
-
-static void python_process_switch(union perf_event *event,
- struct perf_sample *sample,
- struct machine *machine)
-{
- struct tables *tables = &tables_global;
-
- if (tables->db_export_mode)
- db_export__switch(&tables->dbe, event, sample, machine);
- else
- python_do_process_switch(event, sample, machine);
-}
-
-static void python_process_auxtrace_error(struct perf_session *session __maybe_unused,
- union perf_event *event)
-{
- struct perf_record_auxtrace_error *e = &event->auxtrace_error;
- u8 cpumode = e->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
- const char *handler_name = "auxtrace_error";
- unsigned long long tm = e->time;
- const char *msg = e->msg;
- PyObject *handler, *t;
-
- handler = get_handler(handler_name);
- if (!handler)
- return;
-
- if (!e->fmt) {
- tm = 0;
- msg = (const char *)&e->time;
- }
-
- t = tuple_new(11);
-
- tuple_set_u32(t, 0, e->type);
- tuple_set_u32(t, 1, e->code);
- tuple_set_s32(t, 2, e->cpu);
- tuple_set_s32(t, 3, e->pid);
- tuple_set_s32(t, 4, e->tid);
- tuple_set_u64(t, 5, e->ip);
- tuple_set_u64(t, 6, tm);
- tuple_set_string(t, 7, msg);
- tuple_set_u32(t, 8, cpumode);
- tuple_set_s32(t, 9, e->machine_pid);
- tuple_set_s32(t, 10, e->vcpu);
-
- call_object(handler, t, handler_name);
-
- Py_DECREF(t);
-}
-
-static void get_handler_name(char *str, size_t size,
- struct evsel *evsel)
-{
- char *p = str;
-
- scnprintf(str, size, "stat__%s", evsel__name(evsel));
-
- while ((p = strchr(p, ':'))) {
- *p = '_';
- p++;
- }
-}
-
-static void
-process_stat(struct evsel *counter, struct perf_cpu cpu, int thread, u64 tstamp,
- struct perf_counts_values *count)
-{
- PyObject *handler, *t;
- static char handler_name[256];
- int n = 0;
-
- t = PyTuple_New(MAX_FIELDS);
- if (!t)
- Py_FatalError("couldn't create Python tuple");
-
- get_handler_name(handler_name, sizeof(handler_name),
- counter);
-
- handler = get_handler(handler_name);
- if (!handler) {
- pr_debug("can't find python handler %s\n", handler_name);
- return;
- }
-
- PyTuple_SetItem(t, n++, _PyLong_FromLong(cpu.cpu));
- PyTuple_SetItem(t, n++, _PyLong_FromLong(thread));
-
- tuple_set_u64(t, n++, tstamp);
- tuple_set_u64(t, n++, count->val);
- tuple_set_u64(t, n++, count->ena);
- tuple_set_u64(t, n++, count->run);
-
- if (_PyTuple_Resize(&t, n) == -1)
- Py_FatalError("error resizing Python tuple");
-
- call_object(handler, t, handler_name);
-
- Py_DECREF(t);
-}
-
-static void python_process_stat(struct perf_stat_config *config,
- struct evsel *counter, u64 tstamp)
-{
- struct perf_thread_map *threads = counter->core.threads;
- struct perf_cpu_map *cpus = counter->core.cpus;
-
- for (int thread = 0; thread < perf_thread_map__nr(threads); thread++) {
- unsigned int idx;
- struct perf_cpu cpu;
-
- perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
- process_stat(counter, cpu,
- perf_thread_map__pid(threads, thread), tstamp,
- perf_counts(counter->counts, idx, thread));
- }
- }
-}
-
-static void python_process_stat_interval(u64 tstamp)
-{
- PyObject *handler, *t;
- static const char handler_name[] = "stat__interval";
- int n = 0;
-
- t = PyTuple_New(MAX_FIELDS);
- if (!t)
- Py_FatalError("couldn't create Python tuple");
-
- handler = get_handler(handler_name);
- if (!handler) {
- pr_debug("can't find python handler %s\n", handler_name);
- return;
- }
-
- tuple_set_u64(t, n++, tstamp);
-
- if (_PyTuple_Resize(&t, n) == -1)
- Py_FatalError("error resizing Python tuple");
-
- call_object(handler, t, handler_name);
-
- Py_DECREF(t);
-}
-
-static int perf_script_context_init(void)
-{
- PyObject *perf_script_context;
- PyObject *perf_trace_context;
- PyObject *dict;
- int ret;
-
- perf_trace_context = PyImport_AddModule("perf_trace_context");
- if (!perf_trace_context)
- return -1;
- dict = PyModule_GetDict(perf_trace_context);
- if (!dict)
- return -1;
-
- perf_script_context = _PyCapsule_New(scripting_context, NULL, NULL);
- if (!perf_script_context)
- return -1;
-
- ret = PyDict_SetItemString(dict, "perf_script_context", perf_script_context);
- if (!ret)
- ret = PyDict_SetItemString(main_dict, "perf_script_context", perf_script_context);
- Py_DECREF(perf_script_context);
- return ret;
-}
-
-static int run_start_sub(void)
-{
- main_module = PyImport_AddModule("__main__");
- if (main_module == NULL)
- return -1;
- Py_INCREF(main_module);
-
- main_dict = PyModule_GetDict(main_module);
- if (main_dict == NULL)
- goto error;
- Py_INCREF(main_dict);
-
- if (perf_script_context_init())
- goto error;
-
- try_call_object("trace_begin", NULL);
-
- return 0;
-
-error:
- Py_XDECREF(main_dict);
- Py_XDECREF(main_module);
- return -1;
-}
-
-#define SET_TABLE_HANDLER_(name, handler_name, table_name) do { \
- tables->handler_name = get_handler(#table_name); \
- if (tables->handler_name) \
- tables->dbe.export_ ## name = python_export_ ## name; \
-} while (0)
-
-#define SET_TABLE_HANDLER(name) \
- SET_TABLE_HANDLER_(name, name ## _handler, name ## _table)
-
-static void set_table_handlers(struct tables *tables)
-{
- const char *perf_db_export_mode = "perf_db_export_mode";
- const char *perf_db_export_calls = "perf_db_export_calls";
- const char *perf_db_export_callchains = "perf_db_export_callchains";
- PyObject *db_export_mode, *db_export_calls, *db_export_callchains;
- bool export_calls = false;
- bool export_callchains = false;
- int ret;
-
- memset(tables, 0, sizeof(struct tables));
- if (db_export__init(&tables->dbe))
- Py_FatalError("failed to initialize export");
-
- db_export_mode = PyDict_GetItemString(main_dict, perf_db_export_mode);
- if (!db_export_mode)
- return;
-
- ret = PyObject_IsTrue(db_export_mode);
- if (ret == -1)
- handler_call_die(perf_db_export_mode);
- if (!ret)
- return;
-
- /* handle export calls */
- tables->dbe.crp = NULL;
- db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls);
- if (db_export_calls) {
- ret = PyObject_IsTrue(db_export_calls);
- if (ret == -1)
- handler_call_die(perf_db_export_calls);
- export_calls = !!ret;
- }
-
- if (export_calls) {
- tables->dbe.crp =
- call_return_processor__new(python_process_call_return,
- &tables->dbe);
- if (!tables->dbe.crp)
- Py_FatalError("failed to create calls processor");
- }
-
- /* handle export callchains */
- tables->dbe.cpr = NULL;
- db_export_callchains = PyDict_GetItemString(main_dict,
- perf_db_export_callchains);
- if (db_export_callchains) {
- ret = PyObject_IsTrue(db_export_callchains);
- if (ret == -1)
- handler_call_die(perf_db_export_callchains);
- export_callchains = !!ret;
- }
-
- if (export_callchains) {
- /*
- * Attempt to use the call path root from the call return
- * processor, if the call return processor is in use. Otherwise,
- * we allocate a new call path root. This prevents exporting
- * duplicate call path ids when both are in use simultaneously.
- */
- if (tables->dbe.crp)
- tables->dbe.cpr = tables->dbe.crp->cpr;
- else
- tables->dbe.cpr = call_path_root__new();
-
- if (!tables->dbe.cpr)
- Py_FatalError("failed to create call path root");
- }
-
- tables->db_export_mode = true;
- /*
- * Reserve per symbol space for symbol->db_id via symbol__priv()
- */
- symbol_conf.priv_size = sizeof(u64);
-
- SET_TABLE_HANDLER(evsel);
- SET_TABLE_HANDLER(machine);
- SET_TABLE_HANDLER(thread);
- SET_TABLE_HANDLER(comm);
- SET_TABLE_HANDLER(comm_thread);
- SET_TABLE_HANDLER(dso);
- SET_TABLE_HANDLER(symbol);
- SET_TABLE_HANDLER(branch_type);
- SET_TABLE_HANDLER(sample);
- SET_TABLE_HANDLER(call_path);
- SET_TABLE_HANDLER(call_return);
- SET_TABLE_HANDLER(context_switch);
-
- /*
- * Synthesized events are samples but with architecture-specific data
- * stored in sample->raw_data. They are exported via
- * python_export_sample() and consequently do not need a separate export
- * callback.
- */
- tables->synth_handler = get_handler("synth_data");
-}
-
-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);
-}
-
-
-/*
- * Start trace script
- */
-static int python_start_script(const char *script, int argc, const char **argv,
- struct perf_session *session)
-{
- struct tables *tables = &tables_global;
- wchar_t **command_line;
- char buf[PATH_MAX];
- int i, err = 0;
- FILE *fp;
-
- scripting_context->session = session;
- command_line = malloc((argc + 1) * sizeof(wchar_t *));
- if (!command_line)
- return -1;
-
- command_line[0] = Py_DecodeLocale(script, NULL);
- for (i = 1; i < argc + 1; i++)
- command_line[i] = Py_DecodeLocale(argv[i - 1], NULL);
- PyImport_AppendInittab("perf_trace_context", PyInit_perf_trace_context);
- Py_Initialize();
-
- PySys_SetArgv(argc + 1, command_line);
-
- fp = fopen(script, "r");
- if (!fp) {
- sprintf(buf, "Can't open python script \"%s\"", script);
- perror(buf);
- err = -1;
- goto error;
- }
-
- err = PyRun_SimpleFile(fp, script);
- if (err) {
- fprintf(stderr, "Error running python script %s\n", script);
- goto error;
- }
-
- err = run_start_sub();
- if (err) {
- fprintf(stderr, "Error starting python script %s\n", script);
- goto error;
- }
-
- set_table_handlers(tables);
-
- if (tables->db_export_mode) {
- err = db_export__branch_types(&tables->dbe);
- if (err)
- goto error;
- }
-
- _free_command_line(command_line, argc + 1);
-
- return err;
-error:
- Py_Finalize();
- _free_command_line(command_line, argc + 1);
-
- return err;
-}
-
-static int python_flush_script(void)
-{
- return 0;
-}
-
-/*
- * Stop trace script
- */
-static int python_stop_script(void)
-{
- struct tables *tables = &tables_global;
-
- try_call_object("trace_end", NULL);
-
- db_export__exit(&tables->dbe);
-
- Py_XDECREF(main_dict);
- Py_XDECREF(main_module);
- Py_Finalize();
-
- return 0;
-}
-
-#ifdef HAVE_LIBTRACEEVENT
-static int python_generate_script(struct tep_handle *pevent, const char *outfile)
-{
- int i, not_first, count, nr_events;
- struct tep_event **all_events;
- struct tep_event *event = NULL;
- struct tep_format_field *f;
- char fname[PATH_MAX];
- FILE *ofp;
-
- sprintf(fname, "%s.py", outfile);
- ofp = fopen(fname, "w");
- if (ofp == NULL) {
- fprintf(stderr, "couldn't open %s\n", fname);
- return -1;
- }
- fprintf(ofp, "# perf script event handlers, "
- "generated by perf script -g python\n");
-
- fprintf(ofp, "# Licensed under the terms of the GNU GPL"
- " License version 2\n\n");
-
- fprintf(ofp, "# The common_* event handler fields are the most useful "
- "fields common to\n");
-
- fprintf(ofp, "# all events. They don't necessarily correspond to "
- "the 'common_*' fields\n");
-
- fprintf(ofp, "# in the format files. Those fields not available as "
- "handler params can\n");
-
- fprintf(ofp, "# be retrieved using Python functions of the form "
- "common_*(context).\n");
-
- fprintf(ofp, "# See the perf-script-python Documentation for the list "
- "of available functions.\n\n");
-
- fprintf(ofp, "from __future__ import print_function\n\n");
- fprintf(ofp, "import os\n");
- fprintf(ofp, "import sys\n\n");
-
- fprintf(ofp, "sys.path.append(os.environ['PERF_EXEC_PATH'] + \\\n");
- fprintf(ofp, "\t'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')\n");
- fprintf(ofp, "\nfrom perf_trace_context import *\n");
- fprintf(ofp, "from Core import *\n\n\n");
-
- fprintf(ofp, "def trace_begin():\n");
- fprintf(ofp, "\tprint(\"in trace_begin\")\n\n");
-
- fprintf(ofp, "def trace_end():\n");
- fprintf(ofp, "\tprint(\"in trace_end\")\n\n");
-
- nr_events = tep_get_events_count(pevent);
- all_events = tep_list_events(pevent, TEP_EVENT_SORT_ID);
-
- for (i = 0; all_events && i < nr_events; i++) {
- event = all_events[i];
- fprintf(ofp, "def %s__%s(", event->system, event->name);
- fprintf(ofp, "event_name, ");
- fprintf(ofp, "context, ");
- fprintf(ofp, "common_cpu,\n");
- fprintf(ofp, "\tcommon_secs, ");
- fprintf(ofp, "common_nsecs, ");
- fprintf(ofp, "common_pid, ");
- fprintf(ofp, "common_comm,\n\t");
- fprintf(ofp, "common_callchain, ");
-
- not_first = 0;
- count = 0;
-
- for (f = event->format.fields; f; f = f->next) {
- if (not_first++)
- fprintf(ofp, ", ");
- if (++count % 5 == 0)
- fprintf(ofp, "\n\t");
-
- fprintf(ofp, "%s", f->name);
- }
- if (not_first++)
- fprintf(ofp, ", ");
- if (++count % 5 == 0)
- fprintf(ofp, "\n\t\t");
- fprintf(ofp, "perf_sample_dict");
-
- fprintf(ofp, "):\n");
-
- fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
- "common_secs, common_nsecs,\n\t\t\t"
- "common_pid, common_comm)\n\n");
-
- fprintf(ofp, "\t\tprint(\"");
-
- not_first = 0;
- count = 0;
-
- for (f = event->format.fields; f; f = f->next) {
- if (not_first++)
- fprintf(ofp, ", ");
- if (count && count % 3 == 0) {
- fprintf(ofp, "\" \\\n\t\t\"");
- }
- count++;
-
- fprintf(ofp, "%s=", f->name);
- if (f->flags & TEP_FIELD_IS_STRING ||
- f->flags & TEP_FIELD_IS_FLAG ||
- f->flags & TEP_FIELD_IS_ARRAY ||
- f->flags & TEP_FIELD_IS_SYMBOLIC)
- fprintf(ofp, "%%s");
- else if (f->flags & TEP_FIELD_IS_SIGNED)
- fprintf(ofp, "%%d");
- else
- fprintf(ofp, "%%u");
- }
-
- fprintf(ofp, "\" %% \\\n\t\t(");
-
- not_first = 0;
- count = 0;
-
- for (f = event->format.fields; f; f = f->next) {
- if (not_first++)
- fprintf(ofp, ", ");
-
- if (++count % 5 == 0)
- fprintf(ofp, "\n\t\t");
-
- if (f->flags & TEP_FIELD_IS_FLAG) {
- if ((count - 1) % 5 != 0) {
- fprintf(ofp, "\n\t\t");
- count = 4;
- }
- fprintf(ofp, "flag_str(\"");
- fprintf(ofp, "%s__%s\", ", event->system,
- event->name);
- fprintf(ofp, "\"%s\", %s)", f->name,
- f->name);
- } else if (f->flags & TEP_FIELD_IS_SYMBOLIC) {
- if ((count - 1) % 5 != 0) {
- fprintf(ofp, "\n\t\t");
- count = 4;
- }
- fprintf(ofp, "symbol_str(\"");
- fprintf(ofp, "%s__%s\", ", event->system,
- event->name);
- fprintf(ofp, "\"%s\", %s)", f->name,
- f->name);
- } else
- fprintf(ofp, "%s", f->name);
- }
-
- fprintf(ofp, "))\n\n");
-
- fprintf(ofp, "\t\tprint('Sample: {'+"
- "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}')\n\n");
-
- fprintf(ofp, "\t\tfor node in common_callchain:");
- fprintf(ofp, "\n\t\t\tif 'sym' in node:");
- fprintf(ofp, "\n\t\t\t\tprint(\"\t[%%x] %%s%%s%%s%%s\" %% (");
- fprintf(ofp, "\n\t\t\t\t\tnode['ip'], node['sym']['name'],");
- fprintf(ofp, "\n\t\t\t\t\t\"+0x{:x}\".format(node['sym_off']) if 'sym_off' in node else \"\",");
- fprintf(ofp, "\n\t\t\t\t\t\" ({})\".format(node['dso']) if 'dso' in node else \"\",");
- fprintf(ofp, "\n\t\t\t\t\t\" \" + node['sym_srcline'] if 'sym_srcline' in node else \"\"))");
- fprintf(ofp, "\n\t\t\telse:");
- fprintf(ofp, "\n\t\t\t\tprint(\"\t[%%x]\" %% (node['ip']))\n\n");
- fprintf(ofp, "\t\tprint()\n\n");
-
- }
-
- fprintf(ofp, "def trace_unhandled(event_name, context, "
- "event_fields_dict, perf_sample_dict):\n");
-
- fprintf(ofp, "\t\tprint(get_dict_as_string(event_fields_dict))\n");
- fprintf(ofp, "\t\tprint('Sample: {'+"
- "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}')\n\n");
-
- fprintf(ofp, "def print_header("
- "event_name, cpu, secs, nsecs, pid, comm):\n"
- "\tprint(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
- "(event_name, cpu, secs, nsecs, pid, comm), end=\"\")\n\n");
-
- fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
- "\treturn delimiter.join"
- "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
-
- fclose(ofp);
-
- fprintf(stderr, "generated Python script: %s\n", fname);
-
- return 0;
-}
-#else
-static int python_generate_script(struct tep_handle *pevent __maybe_unused,
- const char *outfile __maybe_unused)
-{
- fprintf(stderr, "Generating Python perf-script is not supported."
- " Install libtraceevent and rebuild perf to enable it.\n"
- "For example:\n # apt install libtraceevent-dev (ubuntu)"
- "\n # yum install libtraceevent-devel (Fedora)"
- "\n etc.\n");
- return -1;
-}
-#endif
-
-struct scripting_ops python_scripting_ops = {
- .name = "Python",
- .dirname = "python",
- .start_script = python_start_script,
- .flush_script = python_flush_script,
- .stop_script = python_stop_script,
- .process_event = python_process_event,
- .process_switch = python_process_switch,
- .process_auxtrace_error = python_process_auxtrace_error,
- .process_stat = python_process_stat,
- .process_stat_interval = python_process_stat_interval,
- .process_throttle = python_process_throttle,
- .generate_script = python_generate_script,
-};
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index a82472419611..0a0a50d9e1e1 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -138,9 +138,7 @@ static void process_event_unsupported(union perf_event *event __maybe_unused,
struct addr_location *al __maybe_unused,
struct addr_location *addr_al __maybe_unused)
{
-}
-
-static void print_python_unsupported_msg(void)
+} static void print_python_unsupported_msg(void)
{
fprintf(stderr, "Python scripting not supported."
" Install libpython and rebuild perf to enable it.\n"
@@ -192,20 +190,10 @@ static void register_python_scripting(struct scripting_ops *scripting_ops)
}
}

-#ifndef HAVE_LIBPYTHON_SUPPORT
void setup_python_scripting(void)
{
register_python_scripting(&python_scripting_unsupported_ops);
}
-#else
-extern struct scripting_ops python_scripting_ops;
-
-void setup_python_scripting(void)
-{
- register_python_scripting(&python_scripting_ops);
-}
-#endif
-

static const struct {
--
2.54.0.545.g6539524ca2-goog