perf/core improvements and fixes
. Remove several cases of needless global variables, on most builtins. . Look up thread using tid instead of pid in 'perf sched'. . Move global variables into a perf_kvm struct, from David Ahern. . Hists refactorings, preparatory for improved 'diff' command, from Jiri Olsa. . Hists refactorings, preparatory for event group viewieng work, from Namhyung Kim. . Remove double negation on optional feature macro definitions, from Namhyung Kim. . Bash auto completion improvements, now we can auto complete the tools long options, tracepoint event names, etc, from Namhyung Kim. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iQIcBAABAgAGBQJQbb7ZAAoJENZQFvNTUqpAaQoP/Ah1x/1OANf72mfM+kmk1TsS 9b/nMTbziOIpZF3YX2rpBfh5olxzqSER78Gzhlh1hL5JD1TKXeuViwH/bhsmkGvi ZqZIa5ByoTF7bRlIvMfLGHyPyVgDssmbFFunQlKiQ+xUxAfJiXrdPZ7nyIU6+zHT X+gysLE10581O6YasRbb1upZMRtobJw7VTZafEfakSWCpke8zQJyRdAV3/yA30Q5 4hWTgPhc54Z0jfLxOOi974RllTnHqmFkwACWWC12dZt/zhV/ujWo7fqmYpPiRwjN 2a/EzgivnvQLAY83EGLenkCXE/Jk0FNtUE+4awX/mrE9J6KUaGgWWJl5OHojtNaE nYuuyMqGiV6YUD24YTWYdEJAZry2EfzM6xsTZmmSIZjFkGmpB5qAsWljuH6t52c3 VqoiaDkIcmwMpJG4f5zZ3xMRC1QGbqHGFJc39pxHQHwALQVpsIuwiTaz0EI6V1Jy fQkROlpA4pI57aY6cezsCMmIPsCfFQYke6zXylrmTWUdp2KL2IvtGDpo4GRI118h J3S+RyW5iyhtmjdsoiemJnehJ6m9pWYD1Urwn9HU1UMSpO0nIxw7oWOTsnV/Fy/6 gaIa2CNic+/aZ/v8s0NtX8ZNuB5cQKzGwKMFrkaRUgOJDx0lU6WoVYeaaqCVwOiD zuzkgAAWjlBdMJFJfepH =emth -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: * Remove several cases of needless global variables, on most builtins. * Look up thread using tid instead of pid in 'perf sched'. * Move global variables into a perf_kvm struct, from David Ahern. * Hists refactorings, preparatory for improved 'diff' command, from Jiri Olsa. * Hists refactorings, preparatory for event group viewieng work, from Namhyung Kim. * Remove double negation on optional feature macro definitions, from Namhyung Kim. * Bash auto completion improvements, now we can auto complete the tools long options, tracepoint event names, etc, from Namhyung Kim. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
		
				commit
				
					
						c942ee2e62
					
				
			
		
					 46 changed files with 1215 additions and 1197 deletions
				
			
		| 
						 | 
					@ -45,6 +45,8 @@ include config/utilities.mak
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf
 | 
					# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf
 | 
				
			||||||
# backtrace post unwind.
 | 
					# backtrace post unwind.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Define NO_BACKTRACE if you do not want stack backtrace debug feature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
 | 
					$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
 | 
				
			||||||
	@$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
 | 
						@$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
 | 
				
			||||||
| 
						 | 
					@ -185,7 +187,7 @@ strip-libs = $(filter-out -l%,$(1))
 | 
				
			||||||
PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
 | 
					PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
 | 
				
			||||||
PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
 | 
					PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
 | 
					$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
 | 
				
			||||||
	$(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
 | 
						$(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
 | 
				
			||||||
	  --quiet build_ext; \
 | 
						  --quiet build_ext; \
 | 
				
			||||||
	mkdir -p $(OUTPUT)python && \
 | 
						mkdir -p $(OUTPUT)python && \
 | 
				
			||||||
| 
						 | 
					@ -446,20 +448,6 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
 | 
					PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Files needed for the python binding, perf.so
 | 
					 | 
				
			||||||
# pyrf is just an internal name needed for all those wrappers.
 | 
					 | 
				
			||||||
# This has to be in sync with what is in the 'sources' variable in
 | 
					 | 
				
			||||||
# tools/perf/util/setup.py
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PYRF_OBJS += $(OUTPUT)util/cpumap.o
 | 
					 | 
				
			||||||
PYRF_OBJS += $(OUTPUT)util/ctype.o
 | 
					 | 
				
			||||||
PYRF_OBJS += $(OUTPUT)util/evlist.o
 | 
					 | 
				
			||||||
PYRF_OBJS += $(OUTPUT)util/evsel.o
 | 
					 | 
				
			||||||
PYRF_OBJS += $(OUTPUT)util/python.o
 | 
					 | 
				
			||||||
PYRF_OBJS += $(OUTPUT)util/thread_map.o
 | 
					 | 
				
			||||||
PYRF_OBJS += $(OUTPUT)util/util.o
 | 
					 | 
				
			||||||
PYRF_OBJS += $(OUTPUT)util/xyarray.o
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Platform specific tweaks
 | 
					# Platform specific tweaks
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					@ -486,7 +474,13 @@ ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
 | 
				
			||||||
		NO_DWARF := 1
 | 
							NO_DWARF := 1
 | 
				
			||||||
		NO_DEMANGLE := 1
 | 
							NO_DEMANGLE := 1
 | 
				
			||||||
	endif
 | 
						endif
 | 
				
			||||||
endif
 | 
					else
 | 
				
			||||||
 | 
						FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
 | 
				
			||||||
 | 
						ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
 | 
				
			||||||
 | 
							msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
 | 
				
			||||||
 | 
							NO_DWARF := 1
 | 
				
			||||||
 | 
						endif # Dwarf support
 | 
				
			||||||
 | 
					endif # SOURCE_LIBELF
 | 
				
			||||||
endif # NO_LIBELF
 | 
					endif # NO_LIBELF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifndef NO_LIBUNWIND
 | 
					ifndef NO_LIBUNWIND
 | 
				
			||||||
| 
						 | 
					@ -511,8 +505,6 @@ ifneq ($(OUTPUT),)
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifdef NO_LIBELF
 | 
					ifdef NO_LIBELF
 | 
				
			||||||
BASIC_CFLAGS += -DNO_LIBELF_SUPPORT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
 | 
					EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Remove ELF/DWARF dependent codes
 | 
					# Remove ELF/DWARF dependent codes
 | 
				
			||||||
| 
						 | 
					@ -527,17 +519,12 @@ BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
 | 
				
			||||||
LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
 | 
					LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
else # NO_LIBELF
 | 
					else # NO_LIBELF
 | 
				
			||||||
 | 
					BASIC_CFLAGS += -DLIBELF_SUPPORT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
 | 
					ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
 | 
				
			||||||
	BASIC_CFLAGS += -DLIBELF_NO_MMAP
 | 
						BASIC_CFLAGS += -DLIBELF_MMAP
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
 | 
					 | 
				
			||||||
ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
 | 
					 | 
				
			||||||
	msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
 | 
					 | 
				
			||||||
	NO_DWARF := 1
 | 
					 | 
				
			||||||
endif # Dwarf support
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ifndef NO_DWARF
 | 
					ifndef NO_DWARF
 | 
				
			||||||
ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
 | 
					ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
 | 
				
			||||||
	msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
 | 
						msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
 | 
				
			||||||
| 
						 | 
					@ -550,38 +537,33 @@ endif # PERF_HAVE_DWARF_REGS
 | 
				
			||||||
endif # NO_DWARF
 | 
					endif # NO_DWARF
 | 
				
			||||||
endif # NO_LIBELF
 | 
					endif # NO_LIBELF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifdef NO_LIBUNWIND
 | 
					ifndef NO_LIBUNWIND
 | 
				
			||||||
	BASIC_CFLAGS += -DNO_LIBUNWIND_SUPPORT
 | 
						BASIC_CFLAGS += -DLIBUNWIND_SUPPORT
 | 
				
			||||||
else
 | 
					 | 
				
			||||||
	EXTLIBS += $(LIBUNWIND_LIBS)
 | 
						EXTLIBS += $(LIBUNWIND_LIBS)
 | 
				
			||||||
	BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS)
 | 
						BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS)
 | 
				
			||||||
	BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS)
 | 
						BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS)
 | 
				
			||||||
	LIB_OBJS += $(OUTPUT)util/unwind.o
 | 
						LIB_OBJS += $(OUTPUT)util/unwind.o
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifdef NO_LIBAUDIT
 | 
					ifndef NO_LIBAUDIT
 | 
				
			||||||
	BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
 | 
					 | 
				
			||||||
else
 | 
					 | 
				
			||||||
	FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
 | 
						FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
 | 
				
			||||||
	ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y)
 | 
						ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y)
 | 
				
			||||||
		msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
 | 
							msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
 | 
				
			||||||
		BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
 | 
					 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
 | 
							BASIC_CFLAGS += -DLIBAUDIT_SUPPORT
 | 
				
			||||||
		BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
 | 
							BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
 | 
				
			||||||
		EXTLIBS += -laudit
 | 
							EXTLIBS += -laudit
 | 
				
			||||||
	endif
 | 
						endif
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifdef NO_NEWT
 | 
					ifndef NO_NEWT
 | 
				
			||||||
	BASIC_CFLAGS += -DNO_NEWT_SUPPORT
 | 
					 | 
				
			||||||
else
 | 
					 | 
				
			||||||
	FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt
 | 
						FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt
 | 
				
			||||||
	ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT)),y)
 | 
						ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT)),y)
 | 
				
			||||||
		msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev);
 | 
							msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev);
 | 
				
			||||||
		BASIC_CFLAGS += -DNO_NEWT_SUPPORT
 | 
					 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		# Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
 | 
							# Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
 | 
				
			||||||
		BASIC_CFLAGS += -I/usr/include/slang
 | 
							BASIC_CFLAGS += -I/usr/include/slang
 | 
				
			||||||
 | 
							BASIC_CFLAGS += -DNEWT_SUPPORT
 | 
				
			||||||
		EXTLIBS += -lnewt -lslang
 | 
							EXTLIBS += -lnewt -lslang
 | 
				
			||||||
		LIB_OBJS += $(OUTPUT)ui/setup.o
 | 
							LIB_OBJS += $(OUTPUT)ui/setup.o
 | 
				
			||||||
		LIB_OBJS += $(OUTPUT)ui/browser.o
 | 
							LIB_OBJS += $(OUTPUT)ui/browser.o
 | 
				
			||||||
| 
						 | 
					@ -603,17 +585,15 @@ else
 | 
				
			||||||
	endif
 | 
						endif
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifdef NO_GTK2
 | 
					ifndef NO_GTK2
 | 
				
			||||||
	BASIC_CFLAGS += -DNO_GTK2_SUPPORT
 | 
					 | 
				
			||||||
else
 | 
					 | 
				
			||||||
	FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
 | 
						FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
 | 
				
			||||||
	ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y)
 | 
						ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y)
 | 
				
			||||||
		msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
 | 
							msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
 | 
				
			||||||
		BASIC_CFLAGS += -DNO_GTK2_SUPPORT
 | 
					 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
 | 
							ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
 | 
				
			||||||
			BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
 | 
								BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
 | 
				
			||||||
		endif
 | 
							endif
 | 
				
			||||||
 | 
							BASIC_CFLAGS += -DGTK2_SUPPORT
 | 
				
			||||||
		BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
 | 
							BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
 | 
				
			||||||
		EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
 | 
							EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
 | 
				
			||||||
		LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
 | 
							LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
 | 
				
			||||||
| 
						 | 
					@ -621,7 +601,7 @@ else
 | 
				
			||||||
		LIB_OBJS += $(OUTPUT)ui/gtk/util.o
 | 
							LIB_OBJS += $(OUTPUT)ui/gtk/util.o
 | 
				
			||||||
		LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
 | 
							LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
 | 
				
			||||||
		# Make sure that it'd be included only once.
 | 
							# Make sure that it'd be included only once.
 | 
				
			||||||
		ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
 | 
							ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
 | 
				
			||||||
			LIB_OBJS += $(OUTPUT)ui/setup.o
 | 
								LIB_OBJS += $(OUTPUT)ui/setup.o
 | 
				
			||||||
			LIB_OBJS += $(OUTPUT)ui/util.o
 | 
								LIB_OBJS += $(OUTPUT)ui/util.o
 | 
				
			||||||
		endif
 | 
							endif
 | 
				
			||||||
| 
						 | 
					@ -762,23 +742,18 @@ ifeq ($(NO_PERF_REGS),0)
 | 
				
			||||||
	ifeq ($(ARCH),x86)
 | 
						ifeq ($(ARCH),x86)
 | 
				
			||||||
		LIB_H += arch/x86/include/perf_regs.h
 | 
							LIB_H += arch/x86/include/perf_regs.h
 | 
				
			||||||
	endif
 | 
						endif
 | 
				
			||||||
else
 | 
						BASIC_CFLAGS += -DHAVE_PERF_REGS
 | 
				
			||||||
	BASIC_CFLAGS += -DNO_PERF_REGS
 | 
					 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifdef NO_STRLCPY
 | 
					ifndef NO_STRLCPY
 | 
				
			||||||
	BASIC_CFLAGS += -DNO_STRLCPY
 | 
						ifeq ($(call try-cc,$(SOURCE_STRLCPY),),y)
 | 
				
			||||||
else
 | 
							BASIC_CFLAGS += -DHAVE_STRLCPY
 | 
				
			||||||
	ifneq ($(call try-cc,$(SOURCE_STRLCPY),),y)
 | 
					 | 
				
			||||||
		BASIC_CFLAGS += -DNO_STRLCPY
 | 
					 | 
				
			||||||
	endif
 | 
						endif
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifdef NO_BACKTRACE
 | 
					ifndef NO_BACKTRACE
 | 
				
			||||||
       BASIC_CFLAGS += -DNO_BACKTRACE
 | 
					       ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
 | 
				
			||||||
else
 | 
					               BASIC_CFLAGS += -DBACKTRACE_SUPPORT
 | 
				
			||||||
       ifneq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
 | 
					 | 
				
			||||||
               BASIC_CFLAGS += -DNO_BACKTRACE
 | 
					 | 
				
			||||||
       endif
 | 
					       endif
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,23 +1,59 @@
 | 
				
			||||||
# perf completion
 | 
					# perf completion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function_exists()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						declare -F $1 > /dev/null
 | 
				
			||||||
 | 
						return $?
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function_exists __ltrim_colon_completions ||
 | 
				
			||||||
 | 
					__ltrim_colon_completions()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
 | 
				
			||||||
 | 
							# Remove colon-word prefix from COMPREPLY items
 | 
				
			||||||
 | 
							local colon_word=${1%${1##*:}}
 | 
				
			||||||
 | 
							local i=${#COMPREPLY[*]}
 | 
				
			||||||
 | 
							while [[ $((--i)) -ge 0 ]]; do
 | 
				
			||||||
 | 
								COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
 | 
				
			||||||
 | 
							done
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
have perf &&
 | 
					have perf &&
 | 
				
			||||||
_perf()
 | 
					_perf()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	local cur cmd
 | 
						local cur prev cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	COMPREPLY=()
 | 
						COMPREPLY=()
 | 
				
			||||||
	_get_comp_words_by_ref cur prev
 | 
						if function_exists _get_comp_words_by_ref; then
 | 
				
			||||||
 | 
							_get_comp_words_by_ref -n : cur prev
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							cur=$(_get_cword :)
 | 
				
			||||||
 | 
							prev=${COMP_WORDS[COMP_CWORD-1]}
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd=${COMP_WORDS[0]}
 | 
						cmd=${COMP_WORDS[0]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# List perf subcommands
 | 
						# List perf subcommands or long options
 | 
				
			||||||
	if [ $COMP_CWORD -eq 1 ]; then
 | 
						if [ $COMP_CWORD -eq 1 ]; then
 | 
				
			||||||
 | 
							if [[ $cur == --* ]]; then
 | 
				
			||||||
 | 
								COMPREPLY=( $( compgen -W '--help --version \
 | 
				
			||||||
 | 
								--exec-path --html-path --paginate --no-pager \
 | 
				
			||||||
 | 
								--perf-dir --work-tree --debugfs-dir' -- "$cur" ) )
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
			cmds=$($cmd --list-cmds)
 | 
								cmds=$($cmd --list-cmds)
 | 
				
			||||||
			COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
 | 
								COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
	# List possible events for -e option
 | 
						# List possible events for -e option
 | 
				
			||||||
	elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then
 | 
						elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then
 | 
				
			||||||
		cmds=$($cmd list --raw-dump)
 | 
							evts=$($cmd list --raw-dump)
 | 
				
			||||||
		COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
 | 
							COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
 | 
				
			||||||
 | 
							__ltrim_colon_completions $cur
 | 
				
			||||||
 | 
						# List long option names
 | 
				
			||||||
 | 
						elif [[ $cur == --* ]];  then
 | 
				
			||||||
 | 
							subcmd=${COMP_WORDS[1]}
 | 
				
			||||||
 | 
							opts=$($cmd $subcmd --list-opts)
 | 
				
			||||||
 | 
							COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
 | 
				
			||||||
	# Fall down to list regular files
 | 
						# Fall down to list regular files
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		_filedir
 | 
							_filedir
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,22 +15,6 @@
 | 
				
			||||||
#include "util/strlist.h"
 | 
					#include "util/strlist.h"
 | 
				
			||||||
#include "util/symbol.h"
 | 
					#include "util/symbol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char const *add_name_list_str, *remove_name_list_str;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char * const buildid_cache_usage[] = {
 | 
					 | 
				
			||||||
	"perf buildid-cache [<options>]",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct option buildid_cache_options[] = {
 | 
					 | 
				
			||||||
	OPT_STRING('a', "add", &add_name_list_str,
 | 
					 | 
				
			||||||
		   "file list", "file(s) to add"),
 | 
					 | 
				
			||||||
	OPT_STRING('r', "remove", &remove_name_list_str, "file list",
 | 
					 | 
				
			||||||
		    "file(s) to remove"),
 | 
					 | 
				
			||||||
	OPT_INCR('v', "verbose", &verbose, "be more verbose"),
 | 
					 | 
				
			||||||
	OPT_END()
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int build_id_cache__add_file(const char *filename, const char *debugdir)
 | 
					static int build_id_cache__add_file(const char *filename, const char *debugdir)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 | 
						char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 | 
				
			||||||
| 
						 | 
					@ -51,8 +35,8 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int build_id_cache__remove_file(const char *filename __maybe_unused,
 | 
					static int build_id_cache__remove_file(const char *filename,
 | 
				
			||||||
				       const char *debugdir __maybe_unused)
 | 
									       const char *debugdir)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u8 build_id[BUILD_ID_SIZE];
 | 
						u8 build_id[BUILD_ID_SIZE];
 | 
				
			||||||
	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 | 
						char sbuild_id[BUILD_ID_SIZE * 2 + 1];
 | 
				
			||||||
| 
						 | 
					@ -73,11 +57,34 @@ static int build_id_cache__remove_file(const char *filename __maybe_unused,
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __cmd_buildid_cache(void)
 | 
					int cmd_buildid_cache(int argc, const char **argv,
 | 
				
			||||||
 | 
							      const char *prefix __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct strlist *list;
 | 
						struct strlist *list;
 | 
				
			||||||
	struct str_node *pos;
 | 
						struct str_node *pos;
 | 
				
			||||||
	char debugdir[PATH_MAX];
 | 
						char debugdir[PATH_MAX];
 | 
				
			||||||
 | 
						char const *add_name_list_str = NULL,
 | 
				
			||||||
 | 
							   *remove_name_list_str = NULL;
 | 
				
			||||||
 | 
						const struct option buildid_cache_options[] = {
 | 
				
			||||||
 | 
						OPT_STRING('a', "add", &add_name_list_str,
 | 
				
			||||||
 | 
							   "file list", "file(s) to add"),
 | 
				
			||||||
 | 
						OPT_STRING('r', "remove", &remove_name_list_str, "file list",
 | 
				
			||||||
 | 
							    "file(s) to remove"),
 | 
				
			||||||
 | 
						OPT_INCR('v', "verbose", &verbose, "be more verbose"),
 | 
				
			||||||
 | 
						OPT_END()
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const char * const buildid_cache_usage[] = {
 | 
				
			||||||
 | 
							"perf buildid-cache [<options>]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						argc = parse_options(argc, argv, buildid_cache_options,
 | 
				
			||||||
 | 
								     buildid_cache_usage, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (symbol__init() < 0)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setup_pager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
 | 
						snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,16 +126,3 @@ static int __cmd_buildid_cache(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
int cmd_buildid_cache(int argc, const char **argv,
 | 
					 | 
				
			||||||
		      const char *prefix __maybe_unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	argc = parse_options(argc, argv, buildid_cache_options,
 | 
					 | 
				
			||||||
			     buildid_cache_usage, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (symbol__init() < 0)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	setup_pager();
 | 
					 | 
				
			||||||
	return __cmd_buildid_cache();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,27 +16,6 @@
 | 
				
			||||||
#include "util/session.h"
 | 
					#include "util/session.h"
 | 
				
			||||||
#include "util/symbol.h"
 | 
					#include "util/symbol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *input_name;
 | 
					 | 
				
			||||||
static bool force;
 | 
					 | 
				
			||||||
static bool show_kernel;
 | 
					 | 
				
			||||||
static bool with_hits;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char * const buildid_list_usage[] = {
 | 
					 | 
				
			||||||
	"perf buildid-list [<options>]",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct option options[] = {
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
 | 
					 | 
				
			||||||
	OPT_STRING('i', "input", &input_name, "file",
 | 
					 | 
				
			||||||
		    "input file name"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
 | 
					 | 
				
			||||||
	OPT_INCR('v', "verbose", &verbose,
 | 
					 | 
				
			||||||
		    "be more verbose"),
 | 
					 | 
				
			||||||
	OPT_END()
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int sysfs__fprintf_build_id(FILE *fp)
 | 
					static int sysfs__fprintf_build_id(FILE *fp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u8 kallsyms_build_id[BUILD_ID_SIZE];
 | 
						u8 kallsyms_build_id[BUILD_ID_SIZE];
 | 
				
			||||||
| 
						 | 
					@ -65,7 +44,8 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
 | 
				
			||||||
	return fprintf(fp, "%s\n", sbuild_id);
 | 
						return fprintf(fp, "%s\n", sbuild_id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int perf_session__list_build_ids(void)
 | 
					static int perf_session__list_build_ids(const char *input_name,
 | 
				
			||||||
 | 
										bool force, bool with_hits)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct perf_session *session;
 | 
						struct perf_session *session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,18 +75,31 @@ out:
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __cmd_buildid_list(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (show_kernel)
 | 
					 | 
				
			||||||
		return sysfs__fprintf_build_id(stdout);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return perf_session__list_build_ids();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int cmd_buildid_list(int argc, const char **argv,
 | 
					int cmd_buildid_list(int argc, const char **argv,
 | 
				
			||||||
		     const char *prefix __maybe_unused)
 | 
							     const char *prefix __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						bool show_kernel = false;
 | 
				
			||||||
 | 
						bool with_hits = false;
 | 
				
			||||||
 | 
						bool force = false;
 | 
				
			||||||
 | 
						const char *input_name = NULL;
 | 
				
			||||||
 | 
						const struct option options[] = {
 | 
				
			||||||
 | 
						OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
 | 
				
			||||||
 | 
						OPT_STRING('i', "input", &input_name, "file", "input file name"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
 | 
				
			||||||
 | 
						OPT_INCR('v', "verbose", &verbose, "be more verbose"),
 | 
				
			||||||
 | 
						OPT_END()
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const char * const buildid_list_usage[] = {
 | 
				
			||||||
 | 
							"perf buildid-list [<options>]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	argc = parse_options(argc, argv, options, buildid_list_usage, 0);
 | 
						argc = parse_options(argc, argv, options, buildid_list_usage, 0);
 | 
				
			||||||
	setup_pager();
 | 
						setup_pager();
 | 
				
			||||||
	return __cmd_buildid_list();
 | 
					
 | 
				
			||||||
 | 
						if (show_kernel)
 | 
				
			||||||
 | 
							return sysfs__fprintf_build_id(stdout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return perf_session__list_build_ids(input_name, force, with_hits);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,7 +70,7 @@ static struct perf_tool tool = {
 | 
				
			||||||
	.ordering_requires_timestamps = true,
 | 
						.ordering_requires_timestamps = true,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
 | 
					static void insert_hist_entry_by_name(struct rb_root *root,
 | 
				
			||||||
				      struct hist_entry *he)
 | 
									      struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rb_node **p = &root->rb_node;
 | 
						struct rb_node **p = &root->rb_node;
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,7 @@ static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
 | 
				
			||||||
	rb_insert_color(&he->rb_node, root);
 | 
						rb_insert_color(&he->rb_node, root);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void hists__resort_entries(struct hists *self)
 | 
					static void hists__name_resort(struct hists *self, bool sort)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long position = 1;
 | 
						unsigned long position = 1;
 | 
				
			||||||
	struct rb_root tmp = RB_ROOT;
 | 
						struct rb_root tmp = RB_ROOT;
 | 
				
			||||||
| 
						 | 
					@ -100,11 +100,15 @@ static void hists__resort_entries(struct hists *self)
 | 
				
			||||||
		struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);
 | 
							struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		next = rb_next(&n->rb_node);
 | 
							next = rb_next(&n->rb_node);
 | 
				
			||||||
		rb_erase(&n->rb_node, &self->entries);
 | 
					 | 
				
			||||||
		n->position = position++;
 | 
							n->position = position++;
 | 
				
			||||||
		perf_session__insert_hist_entry_by_name(&tmp, n);
 | 
					
 | 
				
			||||||
 | 
							if (sort) {
 | 
				
			||||||
 | 
								rb_erase(&n->rb_node, &self->entries);
 | 
				
			||||||
 | 
								insert_hist_entry_by_name(&tmp, n);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sort)
 | 
				
			||||||
		self->entries = tmp;
 | 
							self->entries = tmp;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -150,6 +154,24 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct perf_evsel *evsel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(evsel, &evlist->entries, node) {
 | 
				
			||||||
 | 
							struct hists *hists = &evsel->hists;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							hists__output_resort(hists);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * The hists__name_resort only sets possition
 | 
				
			||||||
 | 
							 * if name is false.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (name || ((!name) && show_displacement))
 | 
				
			||||||
 | 
								hists__name_resort(hists, name);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __cmd_diff(void)
 | 
					static int __cmd_diff(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret, i;
 | 
						int ret, i;
 | 
				
			||||||
| 
						 | 
					@ -176,15 +198,8 @@ static int __cmd_diff(void)
 | 
				
			||||||
	evlist_old = older->evlist;
 | 
						evlist_old = older->evlist;
 | 
				
			||||||
	evlist_new = newer->evlist;
 | 
						evlist_new = newer->evlist;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry(evsel, &evlist_new->entries, node)
 | 
						perf_evlist__resort_hists(evlist_old, true);
 | 
				
			||||||
		hists__output_resort(&evsel->hists);
 | 
						perf_evlist__resort_hists(evlist_new, false);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	list_for_each_entry(evsel, &evlist_old->entries, node) {
 | 
					 | 
				
			||||||
		hists__output_resort(&evsel->hists);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (show_displacement)
 | 
					 | 
				
			||||||
			hists__resort_entries(&evsel->hists);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry(evsel, &evlist_new->entries, node) {
 | 
						list_for_each_entry(evsel, &evlist_new->entries, node) {
 | 
				
			||||||
		struct perf_evsel *evsel_old;
 | 
							struct perf_evsel *evsel_old;
 | 
				
			||||||
| 
						 | 
					@ -199,8 +214,7 @@ static int __cmd_diff(void)
 | 
				
			||||||
		first = false;
 | 
							first = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		hists__match(&evsel_old->hists, &evsel->hists);
 | 
							hists__match(&evsel_old->hists, &evsel->hists);
 | 
				
			||||||
		hists__fprintf(&evsel->hists, &evsel_old->hists,
 | 
							hists__fprintf(&evsel->hists, true, 0, 0, stdout);
 | 
				
			||||||
			       show_displacement, true, 0, 0, stdout);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out_delete:
 | 
					out_delete:
 | 
				
			||||||
| 
						 | 
					@ -242,6 +256,21 @@ static const struct option options[] = {
 | 
				
			||||||
	OPT_END()
 | 
						OPT_END()
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ui_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						perf_hpp__init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* No overhead column. */
 | 
				
			||||||
 | 
						perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Display baseline/delta/displacement columns. */
 | 
				
			||||||
 | 
						perf_hpp__column_enable(PERF_HPP__BASELINE, true);
 | 
				
			||||||
 | 
						perf_hpp__column_enable(PERF_HPP__DELTA, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (show_displacement)
 | 
				
			||||||
 | 
							perf_hpp__column_enable(PERF_HPP__DISPL, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
					int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	sort_order = diff__default_sort_order;
 | 
						sort_order = diff__default_sort_order;
 | 
				
			||||||
| 
						 | 
					@ -264,7 +293,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
	if (symbol__init() < 0)
 | 
						if (symbol__init() < 0)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	perf_hpp__init(true, show_displacement);
 | 
						ui_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setup_sorting(diff_usage, options);
 | 
						setup_sorting(diff_usage, options);
 | 
				
			||||||
	setup_pager();
 | 
						setup_pager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,24 +108,21 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const evlist_usage[] = {
 | 
					 | 
				
			||||||
	"perf evlist [<options>]",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
					int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct perf_attr_details details = { .verbose = false, };
 | 
						struct perf_attr_details details = { .verbose = false, };
 | 
				
			||||||
	const char *input_name = NULL;
 | 
						const char *input_name = NULL;
 | 
				
			||||||
	const struct option options[] = {
 | 
						const struct option options[] = {
 | 
				
			||||||
		OPT_STRING('i', "input", &input_name, "file",
 | 
						OPT_STRING('i', "input", &input_name, "file", "Input file name"),
 | 
				
			||||||
			    "Input file name"),
 | 
						OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"),
 | 
				
			||||||
		OPT_BOOLEAN('F', "freq", &details.freq,
 | 
					 | 
				
			||||||
			    "Show the sample frequency"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('v', "verbose", &details.verbose,
 | 
						OPT_BOOLEAN('v', "verbose", &details.verbose,
 | 
				
			||||||
		    "Show all event attr details"),
 | 
							    "Show all event attr details"),
 | 
				
			||||||
	OPT_END()
 | 
						OPT_END()
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						const char * const evlist_usage[] = {
 | 
				
			||||||
 | 
							"perf evlist [<options>]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	argc = parse_options(argc, argv, options, evlist_usage, 0);
 | 
						argc = parse_options(argc, argv, options, evlist_usage, 0);
 | 
				
			||||||
	if (argc)
 | 
						if (argc)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,23 +30,6 @@ enum help_format {
 | 
				
			||||||
	HELP_FORMAT_WEB,
 | 
						HELP_FORMAT_WEB,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool show_all = false;
 | 
					 | 
				
			||||||
static enum help_format help_format = HELP_FORMAT_NONE;
 | 
					 | 
				
			||||||
static struct option builtin_help_options[] = {
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
 | 
					 | 
				
			||||||
	OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
 | 
					 | 
				
			||||||
	OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
 | 
					 | 
				
			||||||
			HELP_FORMAT_WEB),
 | 
					 | 
				
			||||||
	OPT_SET_UINT('i', "info", &help_format, "show info page",
 | 
					 | 
				
			||||||
			HELP_FORMAT_INFO),
 | 
					 | 
				
			||||||
	OPT_END(),
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char * const builtin_help_usage[] = {
 | 
					 | 
				
			||||||
	"perf help [--all] [--man|--web|--info] [command]",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static enum help_format parse_help_format(const char *format)
 | 
					static enum help_format parse_help_format(const char *format)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!strcmp(format, "man"))
 | 
						if (!strcmp(format, "man"))
 | 
				
			||||||
| 
						 | 
					@ -258,11 +241,13 @@ static int add_man_viewer_info(const char *var, const char *value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int perf_help_config(const char *var, const char *value, void *cb)
 | 
					static int perf_help_config(const char *var, const char *value, void *cb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						enum help_format *help_formatp = cb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!strcmp(var, "help.format")) {
 | 
						if (!strcmp(var, "help.format")) {
 | 
				
			||||||
		if (!value)
 | 
							if (!value)
 | 
				
			||||||
			return config_error_nonbool(var);
 | 
								return config_error_nonbool(var);
 | 
				
			||||||
		help_format = parse_help_format(value);
 | 
							*help_formatp = parse_help_format(value);
 | 
				
			||||||
		if (help_format == HELP_FORMAT_NONE)
 | 
							if (*help_formatp == HELP_FORMAT_NONE)
 | 
				
			||||||
			return -1;
 | 
								return -1;
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -428,12 +413,27 @@ static int show_html_page(const char *perf_cmd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
					int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						bool show_all = false;
 | 
				
			||||||
 | 
						enum help_format help_format = HELP_FORMAT_NONE;
 | 
				
			||||||
 | 
						struct option builtin_help_options[] = {
 | 
				
			||||||
 | 
						OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
 | 
				
			||||||
 | 
						OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
 | 
				
			||||||
 | 
						OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
 | 
				
			||||||
 | 
								HELP_FORMAT_WEB),
 | 
				
			||||||
 | 
						OPT_SET_UINT('i', "info", &help_format, "show info page",
 | 
				
			||||||
 | 
								HELP_FORMAT_INFO),
 | 
				
			||||||
 | 
						OPT_END(),
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const char * const builtin_help_usage[] = {
 | 
				
			||||||
 | 
							"perf help [--all] [--man|--web|--info] [command]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	const char *alias;
 | 
						const char *alias;
 | 
				
			||||||
	int rc = 0;
 | 
						int rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	load_command_list("perf-", &main_cmds, &other_cmds);
 | 
						load_command_list("perf-", &main_cmds, &other_cmds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	perf_config(perf_help_config, NULL);
 | 
						perf_config(perf_help_config, &help_format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	argc = parse_options(argc, argv, builtin_help_options,
 | 
						argc = parse_options(argc, argv, builtin_help_options,
 | 
				
			||||||
			builtin_help_usage, 0);
 | 
								builtin_help_usage, 0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,8 +14,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "util/parse-options.h"
 | 
					#include "util/parse-options.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char		const *input_name = "-";
 | 
					struct perf_inject {
 | 
				
			||||||
static bool		inject_build_ids;
 | 
						struct perf_tool tool;
 | 
				
			||||||
 | 
						bool		 build_ids;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused,
 | 
					static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused,
 | 
				
			||||||
				    union perf_event *event,
 | 
									    union perf_event *event,
 | 
				
			||||||
| 
						 | 
					@ -194,7 +196,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
 | 
				
			||||||
				 * account this as unresolved.
 | 
									 * account this as unresolved.
 | 
				
			||||||
				 */
 | 
									 */
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
#ifndef NO_LIBELF_SUPPORT
 | 
					#ifdef LIBELF_SUPPORT
 | 
				
			||||||
				pr_warning("no symbols found in %s, maybe "
 | 
									pr_warning("no symbols found in %s, maybe "
 | 
				
			||||||
					   "install a debug package?\n",
 | 
										   "install a debug package?\n",
 | 
				
			||||||
					   al.map->dso->long_name);
 | 
										   al.map->dso->long_name);
 | 
				
			||||||
| 
						 | 
					@ -208,7 +210,42 @@ repipe:
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct perf_tool perf_inject = {
 | 
					extern volatile int session_done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void sig_handler(int sig __maybe_unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						session_done = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __cmd_inject(struct perf_inject *inject)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct perf_session *session;
 | 
				
			||||||
 | 
						int ret = -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						signal(SIGINT, sig_handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (inject->build_ids) {
 | 
				
			||||||
 | 
							inject->tool.sample	  = perf_event__inject_buildid;
 | 
				
			||||||
 | 
							inject->tool.mmap	  = perf_event__repipe_mmap;
 | 
				
			||||||
 | 
							inject->tool.fork	  = perf_event__repipe_task;
 | 
				
			||||||
 | 
							inject->tool.tracing_data = perf_event__repipe_tracing_data;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session = perf_session__new("-", O_RDONLY, false, true, &inject->tool);
 | 
				
			||||||
 | 
						if (session == NULL)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = perf_session__process_events(session, &inject->tool);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						perf_session__delete(session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct perf_inject inject = {
 | 
				
			||||||
 | 
							.tool = {
 | 
				
			||||||
			.sample		= perf_event__repipe_sample,
 | 
								.sample		= perf_event__repipe_sample,
 | 
				
			||||||
			.mmap		= perf_event__repipe,
 | 
								.mmap		= perf_event__repipe,
 | 
				
			||||||
			.comm		= perf_event__repipe,
 | 
								.comm		= perf_event__repipe,
 | 
				
			||||||
| 
						 | 
					@ -222,65 +259,30 @@ struct perf_tool perf_inject = {
 | 
				
			||||||
			.event_type	= perf_event__repipe_event_type_synth,
 | 
								.event_type	= perf_event__repipe_event_type_synth,
 | 
				
			||||||
			.tracing_data	= perf_event__repipe_tracing_data_synth,
 | 
								.tracing_data	= perf_event__repipe_tracing_data_synth,
 | 
				
			||||||
			.build_id	= perf_event__repipe_op2_synth,
 | 
								.build_id	= perf_event__repipe_op2_synth,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						const struct option options[] = {
 | 
				
			||||||
extern volatile int session_done;
 | 
							OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
 | 
				
			||||||
 | 
					 | 
				
			||||||
static void sig_handler(int sig __maybe_unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	session_done = 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __cmd_inject(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct perf_session *session;
 | 
					 | 
				
			||||||
	int ret = -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	signal(SIGINT, sig_handler);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (inject_build_ids) {
 | 
					 | 
				
			||||||
		perf_inject.sample	 = perf_event__inject_buildid;
 | 
					 | 
				
			||||||
		perf_inject.mmap	 = perf_event__repipe_mmap;
 | 
					 | 
				
			||||||
		perf_inject.fork	 = perf_event__repipe_task;
 | 
					 | 
				
			||||||
		perf_inject.tracing_data = perf_event__repipe_tracing_data;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject);
 | 
					 | 
				
			||||||
	if (session == NULL)
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = perf_session__process_events(session, &perf_inject);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	perf_session__delete(session);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char * const report_usage[] = {
 | 
					 | 
				
			||||||
	"perf inject [<options>]",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct option options[] = {
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('b', "build-ids", &inject_build_ids,
 | 
					 | 
				
			||||||
			    "Inject build-ids into the output stream"),
 | 
								    "Inject build-ids into the output stream"),
 | 
				
			||||||
		OPT_INCR('v', "verbose", &verbose,
 | 
							OPT_INCR('v', "verbose", &verbose,
 | 
				
			||||||
			 "be more verbose (show build ids, etc)"),
 | 
								 "be more verbose (show build ids, etc)"),
 | 
				
			||||||
		OPT_END()
 | 
							OPT_END()
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						const char * const inject_usage[] = {
 | 
				
			||||||
 | 
							"perf inject [<options>]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
						argc = parse_options(argc, argv, options, inject_usage, 0);
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	argc = parse_options(argc, argv, options, report_usage, 0);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Any (unrecognized) arguments left?
 | 
						 * Any (unrecognized) arguments left?
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (argc)
 | 
						if (argc)
 | 
				
			||||||
		usage_with_options(report_usage, options);
 | 
							usage_with_options(inject_usage, options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (symbol__init() < 0)
 | 
						if (symbol__init() < 0)
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return __cmd_inject();
 | 
						return __cmd_inject(&inject);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,8 +21,6 @@
 | 
				
			||||||
struct alloc_stat;
 | 
					struct alloc_stat;
 | 
				
			||||||
typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
 | 
					typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char		*input_name;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int			alloc_flag;
 | 
					static int			alloc_flag;
 | 
				
			||||||
static int			caller_flag;
 | 
					static int			caller_flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,8 +29,6 @@ static int			caller_lines = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool			raw_ip;
 | 
					static bool			raw_ip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char			default_sort_order[] = "frag,hit,bytes";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int			*cpunode_map;
 | 
					static int			*cpunode_map;
 | 
				
			||||||
static int			max_cpu_num;
 | 
					static int			max_cpu_num;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -481,7 +477,7 @@ static void sort_result(void)
 | 
				
			||||||
	__sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
 | 
						__sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __cmd_kmem(void)
 | 
					static int __cmd_kmem(const char *input_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int err = -EINVAL;
 | 
						int err = -EINVAL;
 | 
				
			||||||
	struct perf_session *session;
 | 
						struct perf_session *session;
 | 
				
			||||||
| 
						 | 
					@ -520,11 +516,6 @@ out_delete:
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const kmem_usage[] = {
 | 
					 | 
				
			||||||
	"perf kmem [<options>] {record|stat}",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r)
 | 
					static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (l->ptr < r->ptr)
 | 
						if (l->ptr < r->ptr)
 | 
				
			||||||
| 
						 | 
					@ -720,31 +711,10 @@ static int parse_line_opt(const struct option *opt __maybe_unused,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct option kmem_options[] = {
 | 
					static int __cmd_record(int argc, const char **argv)
 | 
				
			||||||
	OPT_STRING('i', "input", &input_name, "file",
 | 
					{
 | 
				
			||||||
		   "input file name"),
 | 
						const char * const record_args[] = {
 | 
				
			||||||
	OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
 | 
						"record", "-a", "-R", "-f", "-c", "1",
 | 
				
			||||||
			   "show per-callsite statistics",
 | 
					 | 
				
			||||||
			   parse_caller_opt),
 | 
					 | 
				
			||||||
	OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
 | 
					 | 
				
			||||||
			   "show per-allocation statistics",
 | 
					 | 
				
			||||||
			   parse_alloc_opt),
 | 
					 | 
				
			||||||
	OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
 | 
					 | 
				
			||||||
		     "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
 | 
					 | 
				
			||||||
		     parse_sort_opt),
 | 
					 | 
				
			||||||
	OPT_CALLBACK('l', "line", NULL, "num",
 | 
					 | 
				
			||||||
		     "show n lines",
 | 
					 | 
				
			||||||
		     parse_line_opt),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
 | 
					 | 
				
			||||||
	OPT_END()
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char *record_args[] = {
 | 
					 | 
				
			||||||
	"record",
 | 
					 | 
				
			||||||
	"-a",
 | 
					 | 
				
			||||||
	"-R",
 | 
					 | 
				
			||||||
	"-f",
 | 
					 | 
				
			||||||
	"-c", "1",
 | 
					 | 
				
			||||||
	"-e", "kmem:kmalloc",
 | 
						"-e", "kmem:kmalloc",
 | 
				
			||||||
	"-e", "kmem:kmalloc_node",
 | 
						"-e", "kmem:kmalloc_node",
 | 
				
			||||||
	"-e", "kmem:kfree",
 | 
						"-e", "kmem:kfree",
 | 
				
			||||||
| 
						 | 
					@ -752,9 +722,6 @@ static const char *record_args[] = {
 | 
				
			||||||
	"-e", "kmem:kmem_cache_alloc_node",
 | 
						"-e", "kmem:kmem_cache_alloc_node",
 | 
				
			||||||
	"-e", "kmem:kmem_cache_free",
 | 
						"-e", "kmem:kmem_cache_free",
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __cmd_record(int argc, const char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned int rec_argc, i, j;
 | 
						unsigned int rec_argc, i, j;
 | 
				
			||||||
	const char **rec_argv;
 | 
						const char **rec_argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -775,6 +742,25 @@ static int __cmd_record(int argc, const char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
					int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						const char * const default_sort_order = "frag,hit,bytes";
 | 
				
			||||||
 | 
						const char *input_name = NULL;
 | 
				
			||||||
 | 
						const struct option kmem_options[] = {
 | 
				
			||||||
 | 
						OPT_STRING('i', "input", &input_name, "file", "input file name"),
 | 
				
			||||||
 | 
						OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
 | 
				
			||||||
 | 
								   "show per-callsite statistics", parse_caller_opt),
 | 
				
			||||||
 | 
						OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
 | 
				
			||||||
 | 
								   "show per-allocation statistics", parse_alloc_opt),
 | 
				
			||||||
 | 
						OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
 | 
				
			||||||
 | 
							     "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
 | 
				
			||||||
 | 
							     parse_sort_opt),
 | 
				
			||||||
 | 
						OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
 | 
				
			||||||
 | 
						OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
 | 
				
			||||||
 | 
						OPT_END()
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const char * const kmem_usage[] = {
 | 
				
			||||||
 | 
							"perf kmem [<options>] {record|stat}",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	argc = parse_options(argc, argv, kmem_options, kmem_usage, 0);
 | 
						argc = parse_options(argc, argv, kmem_options, kmem_usage, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!argc)
 | 
						if (!argc)
 | 
				
			||||||
| 
						 | 
					@ -793,7 +779,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
		if (list_empty(&alloc_sort))
 | 
							if (list_empty(&alloc_sort))
 | 
				
			||||||
			setup_sorting(&alloc_sort, default_sort_order);
 | 
								setup_sorting(&alloc_sort, default_sort_order);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return __cmd_kmem();
 | 
							return __cmd_kmem(input_name);
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		usage_with_options(kmem_usage, kmem_options);
 | 
							usage_with_options(kmem_usage, kmem_options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,16 +32,76 @@ struct event_key {
 | 
				
			||||||
	int info;
 | 
						int info;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct kvm_event_stats {
 | 
				
			||||||
 | 
						u64 time;
 | 
				
			||||||
 | 
						struct stats stats;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct kvm_event {
 | 
				
			||||||
 | 
						struct list_head hash_entry;
 | 
				
			||||||
 | 
						struct rb_node rb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct event_key key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct kvm_event_stats total;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#define DEFAULT_VCPU_NUM 8
 | 
				
			||||||
 | 
						int max_vcpu;
 | 
				
			||||||
 | 
						struct kvm_event_stats *vcpu;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct kvm_event_key {
 | 
				
			||||||
 | 
						const char *name;
 | 
				
			||||||
 | 
						key_cmp_fun key;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct perf_kvm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct kvm_events_ops {
 | 
					struct kvm_events_ops {
 | 
				
			||||||
	bool (*is_begin_event)(struct perf_evsel *evsel,
 | 
						bool (*is_begin_event)(struct perf_evsel *evsel,
 | 
				
			||||||
			       struct perf_sample *sample,
 | 
								       struct perf_sample *sample,
 | 
				
			||||||
			       struct event_key *key);
 | 
								       struct event_key *key);
 | 
				
			||||||
	bool (*is_end_event)(struct perf_evsel *evsel,
 | 
						bool (*is_end_event)(struct perf_evsel *evsel,
 | 
				
			||||||
			     struct perf_sample *sample, struct event_key *key);
 | 
								     struct perf_sample *sample, struct event_key *key);
 | 
				
			||||||
	void (*decode_key)(struct event_key *key, char decode[20]);
 | 
						void (*decode_key)(struct perf_kvm *kvm, struct event_key *key,
 | 
				
			||||||
 | 
								   char decode[20]);
 | 
				
			||||||
	const char *name;
 | 
						const char *name;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct exit_reasons_table {
 | 
				
			||||||
 | 
						unsigned long exit_code;
 | 
				
			||||||
 | 
						const char *reason;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EVENTS_BITS		12
 | 
				
			||||||
 | 
					#define EVENTS_CACHE_SIZE	(1UL << EVENTS_BITS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct perf_kvm {
 | 
				
			||||||
 | 
						struct perf_tool    tool;
 | 
				
			||||||
 | 
						struct perf_session *session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *file_name;
 | 
				
			||||||
 | 
						const char *report_event;
 | 
				
			||||||
 | 
						const char *sort_key;
 | 
				
			||||||
 | 
						int trace_vcpu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct exit_reasons_table *exit_reasons;
 | 
				
			||||||
 | 
						int exit_reasons_size;
 | 
				
			||||||
 | 
						const char *exit_reasons_isa;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct kvm_events_ops *events_ops;
 | 
				
			||||||
 | 
						key_cmp_fun compare;
 | 
				
			||||||
 | 
						struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
 | 
				
			||||||
 | 
						u64 total_time;
 | 
				
			||||||
 | 
						u64 total_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct rb_root result;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void exit_event_get_key(struct perf_evsel *evsel,
 | 
					static void exit_event_get_key(struct perf_evsel *evsel,
 | 
				
			||||||
			       struct perf_sample *sample,
 | 
								       struct perf_sample *sample,
 | 
				
			||||||
			       struct event_key *key)
 | 
								       struct event_key *key)
 | 
				
			||||||
| 
						 | 
					@ -78,45 +138,35 @@ static bool exit_event_end(struct perf_evsel *evsel,
 | 
				
			||||||
	return kvm_entry_event(evsel);
 | 
						return kvm_entry_event(evsel);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct exit_reasons_table {
 | 
					static struct exit_reasons_table vmx_exit_reasons[] = {
 | 
				
			||||||
	unsigned long exit_code;
 | 
					 | 
				
			||||||
	const char *reason;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct exit_reasons_table vmx_exit_reasons[] = {
 | 
					 | 
				
			||||||
	VMX_EXIT_REASONS
 | 
						VMX_EXIT_REASONS
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct exit_reasons_table svm_exit_reasons[] = {
 | 
					static struct exit_reasons_table svm_exit_reasons[] = {
 | 
				
			||||||
	SVM_EXIT_REASONS
 | 
						SVM_EXIT_REASONS
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int cpu_isa;
 | 
					static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code)
 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char *get_exit_reason(u64 exit_code)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int table_size = ARRAY_SIZE(svm_exit_reasons);
 | 
						int i = kvm->exit_reasons_size;
 | 
				
			||||||
	struct exit_reasons_table *table = svm_exit_reasons;
 | 
						struct exit_reasons_table *tbl = kvm->exit_reasons;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cpu_isa == 1) {
 | 
						while (i--) {
 | 
				
			||||||
		table = vmx_exit_reasons;
 | 
							if (tbl->exit_code == exit_code)
 | 
				
			||||||
		table_size = ARRAY_SIZE(vmx_exit_reasons);
 | 
								return tbl->reason;
 | 
				
			||||||
	}
 | 
							tbl++;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (table_size--) {
 | 
					 | 
				
			||||||
		if (table->exit_code == exit_code)
 | 
					 | 
				
			||||||
			return table->reason;
 | 
					 | 
				
			||||||
		table++;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pr_err("unknown kvm exit code:%lld on %s\n",
 | 
						pr_err("unknown kvm exit code:%lld on %s\n",
 | 
				
			||||||
		(unsigned long long)exit_code, cpu_isa ? "VMX" : "SVM");
 | 
							(unsigned long long)exit_code, kvm->exit_reasons_isa);
 | 
				
			||||||
	return "UNKNOWN";
 | 
						return "UNKNOWN";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void exit_event_decode_key(struct event_key *key, char decode[20])
 | 
					static void exit_event_decode_key(struct perf_kvm *kvm,
 | 
				
			||||||
 | 
									  struct event_key *key,
 | 
				
			||||||
 | 
									  char decode[20])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *exit_reason = get_exit_reason(key->key);
 | 
						const char *exit_reason = get_exit_reason(kvm, key->key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	scnprintf(decode, 20, "%s", exit_reason);
 | 
						scnprintf(decode, 20, "%s", exit_reason);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -178,7 +228,9 @@ static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void mmio_event_decode_key(struct event_key *key, char decode[20])
 | 
					static void mmio_event_decode_key(struct perf_kvm *kvm __maybe_unused,
 | 
				
			||||||
 | 
									  struct event_key *key,
 | 
				
			||||||
 | 
									  char decode[20])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key,
 | 
						scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key,
 | 
				
			||||||
				key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
 | 
									key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
 | 
				
			||||||
| 
						 | 
					@ -219,7 +271,9 @@ static bool ioport_event_end(struct perf_evsel *evsel,
 | 
				
			||||||
	return kvm_entry_event(evsel);
 | 
						return kvm_entry_event(evsel);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ioport_event_decode_key(struct event_key *key, char decode[20])
 | 
					static void ioport_event_decode_key(struct perf_kvm *kvm __maybe_unused,
 | 
				
			||||||
 | 
									    struct event_key *key,
 | 
				
			||||||
 | 
									    char decode[20])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key,
 | 
						scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key,
 | 
				
			||||||
				key->info ? "POUT" : "PIN");
 | 
									key->info ? "POUT" : "PIN");
 | 
				
			||||||
| 
						 | 
					@ -232,64 +286,37 @@ static struct kvm_events_ops ioport_events = {
 | 
				
			||||||
	.name = "IO Port Access"
 | 
						.name = "IO Port Access"
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *report_event = "vmexit";
 | 
					static bool register_kvm_events_ops(struct perf_kvm *kvm)
 | 
				
			||||||
struct kvm_events_ops *events_ops;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool register_kvm_events_ops(void)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	bool ret = true;
 | 
						bool ret = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!strcmp(report_event, "vmexit"))
 | 
						if (!strcmp(kvm->report_event, "vmexit"))
 | 
				
			||||||
		events_ops = &exit_events;
 | 
							kvm->events_ops = &exit_events;
 | 
				
			||||||
	else if (!strcmp(report_event, "mmio"))
 | 
						else if (!strcmp(kvm->report_event, "mmio"))
 | 
				
			||||||
		events_ops = &mmio_events;
 | 
							kvm->events_ops = &mmio_events;
 | 
				
			||||||
	else if (!strcmp(report_event, "ioport"))
 | 
						else if (!strcmp(kvm->report_event, "ioport"))
 | 
				
			||||||
		events_ops = &ioport_events;
 | 
							kvm->events_ops = &ioport_events;
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		pr_err("Unknown report event:%s\n", report_event);
 | 
							pr_err("Unknown report event:%s\n", kvm->report_event);
 | 
				
			||||||
		ret = false;
 | 
							ret = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct kvm_event_stats {
 | 
					 | 
				
			||||||
	u64 time;
 | 
					 | 
				
			||||||
	struct stats stats;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct kvm_event {
 | 
					 | 
				
			||||||
	struct list_head hash_entry;
 | 
					 | 
				
			||||||
	struct rb_node rb;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct event_key key;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct kvm_event_stats total;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	#define DEFAULT_VCPU_NUM 8
 | 
					 | 
				
			||||||
	int max_vcpu;
 | 
					 | 
				
			||||||
	struct kvm_event_stats *vcpu;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct vcpu_event_record {
 | 
					struct vcpu_event_record {
 | 
				
			||||||
	int vcpu_id;
 | 
						int vcpu_id;
 | 
				
			||||||
	u64 start_time;
 | 
						u64 start_time;
 | 
				
			||||||
	struct kvm_event *last_event;
 | 
						struct kvm_event *last_event;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EVENTS_BITS			12
 | 
					 | 
				
			||||||
#define EVENTS_CACHE_SIZE	(1UL << EVENTS_BITS)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u64 total_time;
 | 
					static void init_kvm_event_record(struct perf_kvm *kvm)
 | 
				
			||||||
static u64 total_count;
 | 
					 | 
				
			||||||
static struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void init_kvm_event_record(void)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
 | 
						for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
 | 
				
			||||||
		INIT_LIST_HEAD(&kvm_events_cache[i]);
 | 
							INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int kvm_events_hash_fn(u64 key)
 | 
					static int kvm_events_hash_fn(u64 key)
 | 
				
			||||||
| 
						 | 
					@ -333,14 +360,15 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
 | 
				
			||||||
	return event;
 | 
						return event;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct kvm_event *find_create_kvm_event(struct event_key *key)
 | 
					static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
 | 
				
			||||||
 | 
										       struct event_key *key)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct kvm_event *event;
 | 
						struct kvm_event *event;
 | 
				
			||||||
	struct list_head *head;
 | 
						struct list_head *head;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BUG_ON(key->key == INVALID_KEY);
 | 
						BUG_ON(key->key == INVALID_KEY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	head = &kvm_events_cache[kvm_events_hash_fn(key->key)];
 | 
						head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
 | 
				
			||||||
	list_for_each_entry(event, head, hash_entry)
 | 
						list_for_each_entry(event, head, hash_entry)
 | 
				
			||||||
		if (event->key.key == key->key && event->key.info == key->info)
 | 
							if (event->key.key == key->key && event->key.info == key->info)
 | 
				
			||||||
			return event;
 | 
								return event;
 | 
				
			||||||
| 
						 | 
					@ -353,13 +381,14 @@ static struct kvm_event *find_create_kvm_event(struct event_key *key)
 | 
				
			||||||
	return event;
 | 
						return event;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_begin_event(struct vcpu_event_record *vcpu_record,
 | 
					static bool handle_begin_event(struct perf_kvm *kvm,
 | 
				
			||||||
 | 
								       struct vcpu_event_record *vcpu_record,
 | 
				
			||||||
			       struct event_key *key, u64 timestamp)
 | 
								       struct event_key *key, u64 timestamp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct kvm_event *event = NULL;
 | 
						struct kvm_event *event = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (key->key != INVALID_KEY)
 | 
						if (key->key != INVALID_KEY)
 | 
				
			||||||
		event = find_create_kvm_event(key);
 | 
							event = find_create_kvm_event(kvm, key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vcpu_record->last_event = event;
 | 
						vcpu_record->last_event = event;
 | 
				
			||||||
	vcpu_record->start_time = timestamp;
 | 
						vcpu_record->start_time = timestamp;
 | 
				
			||||||
| 
						 | 
					@ -396,8 +425,10 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_end_event(struct vcpu_event_record *vcpu_record,
 | 
					static bool handle_end_event(struct perf_kvm *kvm,
 | 
				
			||||||
			     struct event_key *key, u64 timestamp)
 | 
								     struct vcpu_event_record *vcpu_record,
 | 
				
			||||||
 | 
								     struct event_key *key,
 | 
				
			||||||
 | 
								     u64 timestamp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct kvm_event *event;
 | 
						struct kvm_event *event;
 | 
				
			||||||
	u64 time_begin, time_diff;
 | 
						u64 time_begin, time_diff;
 | 
				
			||||||
| 
						 | 
					@ -419,7 +450,7 @@ static bool handle_end_event(struct vcpu_event_record *vcpu_record,
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!event)
 | 
						if (!event)
 | 
				
			||||||
		event = find_create_kvm_event(key);
 | 
							event = find_create_kvm_event(kvm, key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!event)
 | 
						if (!event)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
| 
						 | 
					@ -455,7 +486,9 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
 | 
				
			||||||
	return thread->priv;
 | 
						return thread->priv;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel,
 | 
					static bool handle_kvm_event(struct perf_kvm *kvm,
 | 
				
			||||||
 | 
								     struct thread *thread,
 | 
				
			||||||
 | 
								     struct perf_evsel *evsel,
 | 
				
			||||||
			     struct perf_sample *sample)
 | 
								     struct perf_sample *sample)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct vcpu_event_record *vcpu_record;
 | 
						struct vcpu_event_record *vcpu_record;
 | 
				
			||||||
| 
						 | 
					@ -465,22 +498,15 @@ static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel,
 | 
				
			||||||
	if (!vcpu_record)
 | 
						if (!vcpu_record)
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (events_ops->is_begin_event(evsel, sample, &key))
 | 
						if (kvm->events_ops->is_begin_event(evsel, sample, &key))
 | 
				
			||||||
		return handle_begin_event(vcpu_record, &key, sample->time);
 | 
							return handle_begin_event(kvm, vcpu_record, &key, sample->time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (events_ops->is_end_event(evsel, sample, &key))
 | 
						if (kvm->events_ops->is_end_event(evsel, sample, &key))
 | 
				
			||||||
		return handle_end_event(vcpu_record, &key, sample->time);
 | 
							return handle_end_event(kvm, vcpu_record, &key, sample->time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
 | 
					 | 
				
			||||||
struct kvm_event_key {
 | 
					 | 
				
			||||||
	const char *name;
 | 
					 | 
				
			||||||
	key_cmp_fun key;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int trace_vcpu = -1;
 | 
					 | 
				
			||||||
#define GET_EVENT_KEY(func, field)					\
 | 
					#define GET_EVENT_KEY(func, field)					\
 | 
				
			||||||
static u64 get_event_ ##func(struct kvm_event *event, int vcpu)		\
 | 
					static u64 get_event_ ##func(struct kvm_event *event, int vcpu)		\
 | 
				
			||||||
{									\
 | 
					{									\
 | 
				
			||||||
| 
						 | 
					@ -515,29 +541,25 @@ static struct kvm_event_key keys[] = {
 | 
				
			||||||
	{ NULL, NULL }
 | 
						{ NULL, NULL }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *sort_key = "sample";
 | 
					static bool select_key(struct perf_kvm *kvm)
 | 
				
			||||||
static key_cmp_fun compare;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool select_key(void)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; keys[i].name; i++) {
 | 
						for (i = 0; keys[i].name; i++) {
 | 
				
			||||||
		if (!strcmp(keys[i].name, sort_key)) {
 | 
							if (!strcmp(keys[i].name, kvm->sort_key)) {
 | 
				
			||||||
			compare = keys[i].key;
 | 
								kvm->compare = keys[i].key;
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pr_err("Unknown compare key:%s\n", sort_key);
 | 
						pr_err("Unknown compare key:%s\n", kvm->sort_key);
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct rb_root result;
 | 
					static void insert_to_result(struct rb_root *result, struct kvm_event *event,
 | 
				
			||||||
static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger,
 | 
								     key_cmp_fun bigger, int vcpu)
 | 
				
			||||||
			     int vcpu)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rb_node **rb = &result.rb_node;
 | 
						struct rb_node **rb = &result->rb_node;
 | 
				
			||||||
	struct rb_node *parent = NULL;
 | 
						struct rb_node *parent = NULL;
 | 
				
			||||||
	struct kvm_event *p;
 | 
						struct kvm_event *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -552,13 +574,15 @@ static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rb_link_node(&event->rb, parent, rb);
 | 
						rb_link_node(&event->rb, parent, rb);
 | 
				
			||||||
	rb_insert_color(&event->rb, &result);
 | 
						rb_insert_color(&event->rb, result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void update_total_count(struct kvm_event *event, int vcpu)
 | 
					static void update_total_count(struct perf_kvm *kvm, struct kvm_event *event)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	total_count += get_event_count(event, vcpu);
 | 
						int vcpu = kvm->trace_vcpu;
 | 
				
			||||||
	total_time += get_event_time(event, vcpu);
 | 
					
 | 
				
			||||||
 | 
						kvm->total_count += get_event_count(event, vcpu);
 | 
				
			||||||
 | 
						kvm->total_time += get_event_time(event, vcpu);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool event_is_valid(struct kvm_event *event, int vcpu)
 | 
					static bool event_is_valid(struct kvm_event *event, int vcpu)
 | 
				
			||||||
| 
						 | 
					@ -566,28 +590,30 @@ static bool event_is_valid(struct kvm_event *event, int vcpu)
 | 
				
			||||||
	return !!get_event_count(event, vcpu);
 | 
						return !!get_event_count(event, vcpu);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sort_result(int vcpu)
 | 
					static void sort_result(struct perf_kvm *kvm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
 | 
						int vcpu = kvm->trace_vcpu;
 | 
				
			||||||
	struct kvm_event *event;
 | 
						struct kvm_event *event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < EVENTS_CACHE_SIZE; i++)
 | 
						for (i = 0; i < EVENTS_CACHE_SIZE; i++)
 | 
				
			||||||
		list_for_each_entry(event, &kvm_events_cache[i], hash_entry)
 | 
							list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry)
 | 
				
			||||||
			if (event_is_valid(event, vcpu)) {
 | 
								if (event_is_valid(event, vcpu)) {
 | 
				
			||||||
				update_total_count(event, vcpu);
 | 
									update_total_count(kvm, event);
 | 
				
			||||||
				insert_to_result(event, compare, vcpu);
 | 
									insert_to_result(&kvm->result, event,
 | 
				
			||||||
 | 
											 kvm->compare, vcpu);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* returns left most element of result, and erase it */
 | 
					/* returns left most element of result, and erase it */
 | 
				
			||||||
static struct kvm_event *pop_from_result(void)
 | 
					static struct kvm_event *pop_from_result(struct rb_root *result)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rb_node *node = rb_first(&result);
 | 
						struct rb_node *node = rb_first(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!node)
 | 
						if (!node)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rb_erase(node, &result);
 | 
						rb_erase(node, result);
 | 
				
			||||||
	return container_of(node, struct kvm_event, rb);
 | 
						return container_of(node, struct kvm_event, rb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -601,14 +627,15 @@ static void print_vcpu_info(int vcpu)
 | 
				
			||||||
		pr_info("VCPU %d:\n\n", vcpu);
 | 
							pr_info("VCPU %d:\n\n", vcpu);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void print_result(int vcpu)
 | 
					static void print_result(struct perf_kvm *kvm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char decode[20];
 | 
						char decode[20];
 | 
				
			||||||
	struct kvm_event *event;
 | 
						struct kvm_event *event;
 | 
				
			||||||
 | 
						int vcpu = kvm->trace_vcpu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pr_info("\n\n");
 | 
						pr_info("\n\n");
 | 
				
			||||||
	print_vcpu_info(vcpu);
 | 
						print_vcpu_info(vcpu);
 | 
				
			||||||
	pr_info("%20s ", events_ops->name);
 | 
						pr_info("%20s ", kvm->events_ops->name);
 | 
				
			||||||
	pr_info("%10s ", "Samples");
 | 
						pr_info("%10s ", "Samples");
 | 
				
			||||||
	pr_info("%9s ", "Samples%");
 | 
						pr_info("%9s ", "Samples%");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -616,33 +643,34 @@ static void print_result(int vcpu)
 | 
				
			||||||
	pr_info("%16s ", "Avg time");
 | 
						pr_info("%16s ", "Avg time");
 | 
				
			||||||
	pr_info("\n\n");
 | 
						pr_info("\n\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((event = pop_from_result())) {
 | 
						while ((event = pop_from_result(&kvm->result))) {
 | 
				
			||||||
		u64 ecount, etime;
 | 
							u64 ecount, etime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ecount = get_event_count(event, vcpu);
 | 
							ecount = get_event_count(event, vcpu);
 | 
				
			||||||
		etime = get_event_time(event, vcpu);
 | 
							etime = get_event_time(event, vcpu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		events_ops->decode_key(&event->key, decode);
 | 
							kvm->events_ops->decode_key(kvm, &event->key, decode);
 | 
				
			||||||
		pr_info("%20s ", decode);
 | 
							pr_info("%20s ", decode);
 | 
				
			||||||
		pr_info("%10llu ", (unsigned long long)ecount);
 | 
							pr_info("%10llu ", (unsigned long long)ecount);
 | 
				
			||||||
		pr_info("%8.2f%% ", (double)ecount / total_count * 100);
 | 
							pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
 | 
				
			||||||
		pr_info("%8.2f%% ", (double)etime / total_time * 100);
 | 
							pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
 | 
				
			||||||
		pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
 | 
							pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
 | 
				
			||||||
			kvm_event_rel_stddev(vcpu, event));
 | 
								kvm_event_rel_stddev(vcpu, event));
 | 
				
			||||||
		pr_info("\n");
 | 
							pr_info("\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
 | 
						pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
 | 
				
			||||||
		(unsigned long long)total_count, total_time / 1e3);
 | 
							(unsigned long long)kvm->total_count, kvm->total_time / 1e3);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int process_sample_event(struct perf_tool *tool __maybe_unused,
 | 
					static int process_sample_event(struct perf_tool *tool,
 | 
				
			||||||
				union perf_event *event,
 | 
									union perf_event *event,
 | 
				
			||||||
				struct perf_sample *sample,
 | 
									struct perf_sample *sample,
 | 
				
			||||||
				struct perf_evsel *evsel,
 | 
									struct perf_evsel *evsel,
 | 
				
			||||||
				struct machine *machine)
 | 
									struct machine *machine)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct thread *thread = machine__findnew_thread(machine, sample->tid);
 | 
						struct thread *thread = machine__findnew_thread(machine, sample->tid);
 | 
				
			||||||
 | 
						struct perf_kvm *kvm = container_of(tool, struct perf_kvm, tool);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (thread == NULL) {
 | 
						if (thread == NULL) {
 | 
				
			||||||
		pr_debug("problem processing %d event, skipping it.\n",
 | 
							pr_debug("problem processing %d event, skipping it.\n",
 | 
				
			||||||
| 
						 | 
					@ -650,18 +678,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!handle_kvm_event(thread, evsel, sample))
 | 
						if (!handle_kvm_event(kvm, thread, evsel, sample))
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct perf_tool eops = {
 | 
					 | 
				
			||||||
	.sample			= process_sample_event,
 | 
					 | 
				
			||||||
	.comm			= perf_event__process_comm,
 | 
					 | 
				
			||||||
	.ordered_samples	= true,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int get_cpu_isa(struct perf_session *session)
 | 
					static int get_cpu_isa(struct perf_session *session)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *cpuid = session->header.env.cpuid;
 | 
						char *cpuid = session->header.env.cpuid;
 | 
				
			||||||
| 
						 | 
					@ -679,34 +701,43 @@ static int get_cpu_isa(struct perf_session *session)
 | 
				
			||||||
	return isa;
 | 
						return isa;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *file_name;
 | 
					static int read_events(struct perf_kvm *kvm)
 | 
				
			||||||
 | 
					 | 
				
			||||||
static int read_events(void)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct perf_session *kvm_session;
 | 
					 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kvm_session = perf_session__new(file_name, O_RDONLY, 0, false, &eops);
 | 
						struct perf_tool eops = {
 | 
				
			||||||
	if (!kvm_session) {
 | 
							.sample			= process_sample_event,
 | 
				
			||||||
 | 
							.comm			= perf_event__process_comm,
 | 
				
			||||||
 | 
							.ordered_samples	= true,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kvm->tool = eops;
 | 
				
			||||||
 | 
						kvm->session = perf_session__new(kvm->file_name, O_RDONLY, 0, false,
 | 
				
			||||||
 | 
										 &kvm->tool);
 | 
				
			||||||
 | 
						if (!kvm->session) {
 | 
				
			||||||
		pr_err("Initializing perf session failed\n");
 | 
							pr_err("Initializing perf session failed\n");
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!perf_session__has_traces(kvm_session, "kvm record"))
 | 
						if (!perf_session__has_traces(kvm->session, "kvm record"))
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
 | 
						 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
 | 
				
			||||||
	 * traced in the old kernel.
 | 
						 * traced in the old kernel.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	ret = get_cpu_isa(kvm_session);
 | 
						ret = get_cpu_isa(kvm->session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cpu_isa = ret;
 | 
						if (ret == 1) {
 | 
				
			||||||
 | 
							kvm->exit_reasons = vmx_exit_reasons;
 | 
				
			||||||
 | 
							kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
 | 
				
			||||||
 | 
							kvm->exit_reasons_isa = "VMX";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return perf_session__process_events(kvm_session, &eops);
 | 
						return perf_session__process_events(kvm->session, &kvm->tool);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool verify_vcpu(int vcpu)
 | 
					static bool verify_vcpu(int vcpu)
 | 
				
			||||||
| 
						 | 
					@ -719,28 +750,30 @@ static bool verify_vcpu(int vcpu)
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int kvm_events_report_vcpu(int vcpu)
 | 
					static int kvm_events_report_vcpu(struct perf_kvm *kvm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret = -EINVAL;
 | 
						int ret = -EINVAL;
 | 
				
			||||||
 | 
						int vcpu = kvm->trace_vcpu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!verify_vcpu(vcpu))
 | 
						if (!verify_vcpu(vcpu))
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!select_key())
 | 
						if (!select_key(kvm))
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!register_kvm_events_ops())
 | 
						if (!register_kvm_events_ops(kvm))
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_kvm_event_record();
 | 
						init_kvm_event_record(kvm);
 | 
				
			||||||
	setup_pager();
 | 
						setup_pager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = read_events();
 | 
						ret = read_events(kvm);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		goto exit;
 | 
							goto exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sort_result(vcpu);
 | 
						sort_result(kvm);
 | 
				
			||||||
	print_result(vcpu);
 | 
						print_result(kvm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exit:
 | 
					exit:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -765,7 +798,7 @@ static const char * const record_args[] = {
 | 
				
			||||||
		_p;			\
 | 
							_p;			\
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int kvm_events_record(int argc, const char **argv)
 | 
					static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int rec_argc, i, j;
 | 
						unsigned int rec_argc, i, j;
 | 
				
			||||||
	const char **rec_argv;
 | 
						const char **rec_argv;
 | 
				
			||||||
| 
						 | 
					@ -780,7 +813,7 @@ static int kvm_events_record(int argc, const char **argv)
 | 
				
			||||||
		rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
 | 
							rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
 | 
						rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
 | 
				
			||||||
	rec_argv[i++] = STRDUP_FAIL_EXIT(file_name);
 | 
						rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (j = 1; j < (unsigned int)argc; j++, i++)
 | 
						for (j = 1; j < (unsigned int)argc; j++, i++)
 | 
				
			||||||
		rec_argv[i] = argv[j];
 | 
							rec_argv[i] = argv[j];
 | 
				
			||||||
| 
						 | 
					@ -788,24 +821,24 @@ static int kvm_events_record(int argc, const char **argv)
 | 
				
			||||||
	return cmd_record(i, rec_argv, NULL);
 | 
						return cmd_record(i, rec_argv, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const kvm_events_report_usage[] = {
 | 
					static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv)
 | 
				
			||||||
	"perf kvm stat report [<options>]",
 | 
					{
 | 
				
			||||||
	NULL
 | 
						const struct option kvm_events_report_options[] = {
 | 
				
			||||||
};
 | 
							OPT_STRING(0, "event", &kvm->report_event, "report event",
 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct option kvm_events_report_options[] = {
 | 
					 | 
				
			||||||
	OPT_STRING(0, "event", &report_event, "report event",
 | 
					 | 
				
			||||||
			    "event for reporting: vmexit, mmio, ioport"),
 | 
								    "event for reporting: vmexit, mmio, ioport"),
 | 
				
			||||||
	OPT_INTEGER(0, "vcpu", &trace_vcpu,
 | 
							OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
 | 
				
			||||||
			    "vcpu id to report"),
 | 
								    "vcpu id to report"),
 | 
				
			||||||
	OPT_STRING('k', "key", &sort_key, "sort-key",
 | 
							OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
 | 
				
			||||||
			    "key for sorting: sample(sort by samples number)"
 | 
								    "key for sorting: sample(sort by samples number)"
 | 
				
			||||||
			    " time (sort by avg time)"),
 | 
								    " time (sort by avg time)"),
 | 
				
			||||||
		OPT_END()
 | 
							OPT_END()
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int kvm_events_report(int argc, const char **argv)
 | 
						const char * const kvm_events_report_usage[] = {
 | 
				
			||||||
{
 | 
							"perf kvm stat report [<options>]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	symbol__init();
 | 
						symbol__init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (argc) {
 | 
						if (argc) {
 | 
				
			||||||
| 
						 | 
					@ -817,7 +850,7 @@ static int kvm_events_report(int argc, const char **argv)
 | 
				
			||||||
					   kvm_events_report_options);
 | 
										   kvm_events_report_options);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return kvm_events_report_vcpu(trace_vcpu);
 | 
						return kvm_events_report_vcpu(kvm);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void print_kvm_stat_usage(void)
 | 
					static void print_kvm_stat_usage(void)
 | 
				
			||||||
| 
						 | 
					@ -831,7 +864,7 @@ static void print_kvm_stat_usage(void)
 | 
				
			||||||
	printf("\nOtherwise, it is the alias of 'perf stat':\n");
 | 
						printf("\nOtherwise, it is the alias of 'perf stat':\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int kvm_cmd_stat(int argc, const char **argv)
 | 
					static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (argc == 1) {
 | 
						if (argc == 1) {
 | 
				
			||||||
		print_kvm_stat_usage();
 | 
							print_kvm_stat_usage();
 | 
				
			||||||
| 
						 | 
					@ -839,26 +872,85 @@ static int kvm_cmd_stat(int argc, const char **argv)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!strncmp(argv[1], "rec", 3))
 | 
						if (!strncmp(argv[1], "rec", 3))
 | 
				
			||||||
		return kvm_events_record(argc - 1, argv + 1);
 | 
							return kvm_events_record(kvm, argc - 1, argv + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!strncmp(argv[1], "rep", 3))
 | 
						if (!strncmp(argv[1], "rep", 3))
 | 
				
			||||||
		return kvm_events_report(argc - 1 , argv + 1);
 | 
							return kvm_events_report(kvm, argc - 1 , argv + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
perf_stat:
 | 
					perf_stat:
 | 
				
			||||||
	return cmd_stat(argc, argv, NULL);
 | 
						return cmd_stat(argc, argv, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char			name_buffer[256];
 | 
					static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rec_argc, i = 0, j;
 | 
				
			||||||
 | 
						const char **rec_argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const kvm_usage[] = {
 | 
						rec_argc = argc + 2;
 | 
				
			||||||
	"perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
 | 
						rec_argv = calloc(rec_argc + 1, sizeof(char *));
 | 
				
			||||||
	NULL
 | 
						rec_argv[i++] = strdup("record");
 | 
				
			||||||
 | 
						rec_argv[i++] = strdup("-o");
 | 
				
			||||||
 | 
						rec_argv[i++] = strdup(kvm->file_name);
 | 
				
			||||||
 | 
						for (j = 1; j < argc; j++, i++)
 | 
				
			||||||
 | 
							rec_argv[i] = argv[j];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BUG_ON(i != rec_argc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cmd_record(i, rec_argv, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rec_argc, i = 0, j;
 | 
				
			||||||
 | 
						const char **rec_argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rec_argc = argc + 2;
 | 
				
			||||||
 | 
						rec_argv = calloc(rec_argc + 1, sizeof(char *));
 | 
				
			||||||
 | 
						rec_argv[i++] = strdup("report");
 | 
				
			||||||
 | 
						rec_argv[i++] = strdup("-i");
 | 
				
			||||||
 | 
						rec_argv[i++] = strdup(kvm->file_name);
 | 
				
			||||||
 | 
						for (j = 1; j < argc; j++, i++)
 | 
				
			||||||
 | 
							rec_argv[i] = argv[j];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BUG_ON(i != rec_argc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cmd_report(i, rec_argv, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rec_argc, i = 0, j;
 | 
				
			||||||
 | 
						const char **rec_argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rec_argc = argc + 2;
 | 
				
			||||||
 | 
						rec_argv = calloc(rec_argc + 1, sizeof(char *));
 | 
				
			||||||
 | 
						rec_argv[i++] = strdup("buildid-list");
 | 
				
			||||||
 | 
						rec_argv[i++] = strdup("-i");
 | 
				
			||||||
 | 
						rec_argv[i++] = strdup(kvm->file_name);
 | 
				
			||||||
 | 
						for (j = 1; j < argc; j++, i++)
 | 
				
			||||||
 | 
							rec_argv[i] = argv[j];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BUG_ON(i != rec_argc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cmd_buildid_list(i, rec_argv, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct perf_kvm kvm = {
 | 
				
			||||||
 | 
							.trace_vcpu	= -1,
 | 
				
			||||||
 | 
							.report_event	= "vmexit",
 | 
				
			||||||
 | 
							.sort_key	= "sample",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.exit_reasons = svm_exit_reasons,
 | 
				
			||||||
 | 
							.exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
 | 
				
			||||||
 | 
							.exit_reasons_isa = "SVM",
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct option kvm_options[] = {
 | 
						const struct option kvm_options[] = {
 | 
				
			||||||
	OPT_STRING('i', "input", &file_name, "file",
 | 
							OPT_STRING('i', "input", &kvm.file_name, "file",
 | 
				
			||||||
			   "Input file name"),
 | 
								   "Input file name"),
 | 
				
			||||||
	OPT_STRING('o', "output", &file_name, "file",
 | 
							OPT_STRING('o', "output", &kvm.file_name, "file",
 | 
				
			||||||
			   "Output file name"),
 | 
								   "Output file name"),
 | 
				
			||||||
		OPT_BOOLEAN(0, "guest", &perf_guest,
 | 
							OPT_BOOLEAN(0, "guest", &perf_guest,
 | 
				
			||||||
			    "Collect guest os data"),
 | 
								    "Collect guest os data"),
 | 
				
			||||||
| 
						 | 
					@ -876,62 +968,12 @@ static const struct option kvm_options[] = {
 | 
				
			||||||
		OPT_END()
 | 
							OPT_END()
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __cmd_record(int argc, const char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int rec_argc, i = 0, j;
 | 
					 | 
				
			||||||
	const char **rec_argv;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rec_argc = argc + 2;
 | 
						const char * const kvm_usage[] = {
 | 
				
			||||||
	rec_argv = calloc(rec_argc + 1, sizeof(char *));
 | 
							"perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
 | 
				
			||||||
	rec_argv[i++] = strdup("record");
 | 
							NULL
 | 
				
			||||||
	rec_argv[i++] = strdup("-o");
 | 
						};
 | 
				
			||||||
	rec_argv[i++] = strdup(file_name);
 | 
					 | 
				
			||||||
	for (j = 1; j < argc; j++, i++)
 | 
					 | 
				
			||||||
		rec_argv[i] = argv[j];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BUG_ON(i != rec_argc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cmd_record(i, rec_argv, NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __cmd_report(int argc, const char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int rec_argc, i = 0, j;
 | 
					 | 
				
			||||||
	const char **rec_argv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rec_argc = argc + 2;
 | 
					 | 
				
			||||||
	rec_argv = calloc(rec_argc + 1, sizeof(char *));
 | 
					 | 
				
			||||||
	rec_argv[i++] = strdup("report");
 | 
					 | 
				
			||||||
	rec_argv[i++] = strdup("-i");
 | 
					 | 
				
			||||||
	rec_argv[i++] = strdup(file_name);
 | 
					 | 
				
			||||||
	for (j = 1; j < argc; j++, i++)
 | 
					 | 
				
			||||||
		rec_argv[i] = argv[j];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	BUG_ON(i != rec_argc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cmd_report(i, rec_argv, NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __cmd_buildid_list(int argc, const char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int rec_argc, i = 0, j;
 | 
					 | 
				
			||||||
	const char **rec_argv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rec_argc = argc + 2;
 | 
					 | 
				
			||||||
	rec_argv = calloc(rec_argc + 1, sizeof(char *));
 | 
					 | 
				
			||||||
	rec_argv[i++] = strdup("buildid-list");
 | 
					 | 
				
			||||||
	rec_argv[i++] = strdup("-i");
 | 
					 | 
				
			||||||
	rec_argv[i++] = strdup(file_name);
 | 
					 | 
				
			||||||
	for (j = 1; j < argc; j++, i++)
 | 
					 | 
				
			||||||
		rec_argv[i] = argv[j];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	BUG_ON(i != rec_argc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cmd_buildid_list(i, rec_argv, NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	perf_host  = 0;
 | 
						perf_host  = 0;
 | 
				
			||||||
	perf_guest = 1;
 | 
						perf_guest = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -943,28 +985,32 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
	if (!perf_host)
 | 
						if (!perf_host)
 | 
				
			||||||
		perf_guest = 1;
 | 
							perf_guest = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!file_name) {
 | 
						if (!kvm.file_name) {
 | 
				
			||||||
		if (perf_host && !perf_guest)
 | 
							if (perf_host && !perf_guest)
 | 
				
			||||||
			sprintf(name_buffer, "perf.data.host");
 | 
								kvm.file_name = strdup("perf.data.host");
 | 
				
			||||||
		else if (!perf_host && perf_guest)
 | 
							else if (!perf_host && perf_guest)
 | 
				
			||||||
			sprintf(name_buffer, "perf.data.guest");
 | 
								kvm.file_name = strdup("perf.data.guest");
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			sprintf(name_buffer, "perf.data.kvm");
 | 
								kvm.file_name = strdup("perf.data.kvm");
 | 
				
			||||||
		file_name = name_buffer;
 | 
					
 | 
				
			||||||
 | 
							if (!kvm.file_name) {
 | 
				
			||||||
 | 
								pr_err("Failed to allocate memory for filename\n");
 | 
				
			||||||
 | 
								return -ENOMEM;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!strncmp(argv[0], "rec", 3))
 | 
						if (!strncmp(argv[0], "rec", 3))
 | 
				
			||||||
		return __cmd_record(argc, argv);
 | 
							return __cmd_record(&kvm, argc, argv);
 | 
				
			||||||
	else if (!strncmp(argv[0], "rep", 3))
 | 
						else if (!strncmp(argv[0], "rep", 3))
 | 
				
			||||||
		return __cmd_report(argc, argv);
 | 
							return __cmd_report(&kvm, argc, argv);
 | 
				
			||||||
	else if (!strncmp(argv[0], "diff", 4))
 | 
						else if (!strncmp(argv[0], "diff", 4))
 | 
				
			||||||
		return cmd_diff(argc, argv, NULL);
 | 
							return cmd_diff(argc, argv, NULL);
 | 
				
			||||||
	else if (!strncmp(argv[0], "top", 3))
 | 
						else if (!strncmp(argv[0], "top", 3))
 | 
				
			||||||
		return cmd_top(argc, argv, NULL);
 | 
							return cmd_top(argc, argv, NULL);
 | 
				
			||||||
	else if (!strncmp(argv[0], "buildid-list", 12))
 | 
						else if (!strncmp(argv[0], "buildid-list", 12))
 | 
				
			||||||
		return __cmd_buildid_list(argc, argv);
 | 
							return __cmd_buildid_list(&kvm, argc, argv);
 | 
				
			||||||
	else if (!strncmp(argv[0], "stat", 4))
 | 
						else if (!strncmp(argv[0], "stat", 4))
 | 
				
			||||||
		return kvm_cmd_stat(argc, argv);
 | 
							return kvm_cmd_stat(&kvm, argc, argv);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		usage_with_options(kvm_usage, kvm_options);
 | 
							usage_with_options(kvm_usage, kvm_options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -823,12 +823,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct perf_tool eops = {
 | 
					 | 
				
			||||||
	.sample			= process_sample_event,
 | 
					 | 
				
			||||||
	.comm			= perf_event__process_comm,
 | 
					 | 
				
			||||||
	.ordered_samples	= true,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct perf_evsel_str_handler lock_tracepoints[] = {
 | 
					static const struct perf_evsel_str_handler lock_tracepoints[] = {
 | 
				
			||||||
	{ "lock:lock_acquire",	 perf_evsel__process_lock_acquire,   }, /* CONFIG_LOCKDEP */
 | 
						{ "lock:lock_acquire",	 perf_evsel__process_lock_acquire,   }, /* CONFIG_LOCKDEP */
 | 
				
			||||||
	{ "lock:lock_acquired",	 perf_evsel__process_lock_acquired,  }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
 | 
						{ "lock:lock_acquired",	 perf_evsel__process_lock_acquired,  }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
 | 
				
			||||||
| 
						 | 
					@ -838,6 +832,11 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int read_events(void)
 | 
					static int read_events(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct perf_tool eops = {
 | 
				
			||||||
 | 
							.sample		 = process_sample_event,
 | 
				
			||||||
 | 
							.comm		 = perf_event__process_comm,
 | 
				
			||||||
 | 
							.ordered_samples = true,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
 | 
						session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
 | 
				
			||||||
	if (!session) {
 | 
						if (!session) {
 | 
				
			||||||
		pr_err("Initializing perf session failed\n");
 | 
							pr_err("Initializing perf session failed\n");
 | 
				
			||||||
| 
						 | 
					@ -878,53 +877,11 @@ static int __cmd_report(void)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const report_usage[] = {
 | 
					 | 
				
			||||||
	"perf lock report [<options>]",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct option report_options[] = {
 | 
					 | 
				
			||||||
	OPT_STRING('k', "key", &sort_key, "acquired",
 | 
					 | 
				
			||||||
		    "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
 | 
					 | 
				
			||||||
	/* TODO: type */
 | 
					 | 
				
			||||||
	OPT_END()
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char * const info_usage[] = {
 | 
					 | 
				
			||||||
	"perf lock info [<options>]",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct option info_options[] = {
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('t', "threads", &info_threads,
 | 
					 | 
				
			||||||
		    "dump thread list in perf.data"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('m', "map", &info_map,
 | 
					 | 
				
			||||||
		    "map of lock instances (address:name table)"),
 | 
					 | 
				
			||||||
	OPT_END()
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char * const lock_usage[] = {
 | 
					 | 
				
			||||||
	"perf lock [<options>] {record|report|script|info}",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct option lock_options[] = {
 | 
					 | 
				
			||||||
	OPT_STRING('i', "input", &input_name, "file", "input file name"),
 | 
					 | 
				
			||||||
	OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
 | 
					 | 
				
			||||||
	OPT_END()
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char *record_args[] = {
 | 
					 | 
				
			||||||
	"record",
 | 
					 | 
				
			||||||
	"-R",
 | 
					 | 
				
			||||||
	"-f",
 | 
					 | 
				
			||||||
	"-m", "1024",
 | 
					 | 
				
			||||||
	"-c", "1",
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __cmd_record(int argc, const char **argv)
 | 
					static int __cmd_record(int argc, const char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						const char *record_args[] = {
 | 
				
			||||||
 | 
							"record", "-R", "-f", "-m", "1024", "-c", "1",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	unsigned int rec_argc, i, j;
 | 
						unsigned int rec_argc, i, j;
 | 
				
			||||||
	const char **rec_argv;
 | 
						const char **rec_argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -963,6 +920,37 @@ static int __cmd_record(int argc, const char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
					int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						const struct option info_options[] = {
 | 
				
			||||||
 | 
						OPT_BOOLEAN('t', "threads", &info_threads,
 | 
				
			||||||
 | 
							    "dump thread list in perf.data"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('m', "map", &info_map,
 | 
				
			||||||
 | 
							    "map of lock instances (address:name table)"),
 | 
				
			||||||
 | 
						OPT_END()
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const struct option lock_options[] = {
 | 
				
			||||||
 | 
						OPT_STRING('i', "input", &input_name, "file", "input file name"),
 | 
				
			||||||
 | 
						OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
 | 
				
			||||||
 | 
						OPT_END()
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const struct option report_options[] = {
 | 
				
			||||||
 | 
						OPT_STRING('k', "key", &sort_key, "acquired",
 | 
				
			||||||
 | 
							    "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
 | 
				
			||||||
 | 
						/* TODO: type */
 | 
				
			||||||
 | 
						OPT_END()
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const char * const info_usage[] = {
 | 
				
			||||||
 | 
							"perf lock info [<options>]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const char * const lock_usage[] = {
 | 
				
			||||||
 | 
							"perf lock [<options>] {record|report|script|info}",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const char * const report_usage[] = {
 | 
				
			||||||
 | 
							"perf lock report [<options>]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
	int rc = 0;
 | 
						int rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -250,7 +250,9 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const probe_usage[] = {
 | 
					int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char * const probe_usage[] = {
 | 
				
			||||||
		"perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
 | 
							"perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
 | 
				
			||||||
		"perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
 | 
							"perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
 | 
				
			||||||
		"perf probe [<options>] --del '[GROUP:]EVENT' ...",
 | 
							"perf probe [<options>] --del '[GROUP:]EVENT' ...",
 | 
				
			||||||
| 
						 | 
					@ -261,8 +263,7 @@ static const char * const probe_usage[] = {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		NULL
 | 
							NULL
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
						const struct option options[] = {
 | 
				
			||||||
static const struct option options[] = {
 | 
					 | 
				
			||||||
	OPT_INCR('v', "verbose", &verbose,
 | 
						OPT_INCR('v', "verbose", &verbose,
 | 
				
			||||||
		    "be more verbose (show parsed arguments, etc)"),
 | 
							    "be more verbose (show parsed arguments, etc)"),
 | 
				
			||||||
	OPT_BOOLEAN('l', "list", ¶ms.list_events,
 | 
						OPT_BOOLEAN('l', "list", ¶ms.list_events,
 | 
				
			||||||
| 
						 | 
					@ -326,9 +327,6 @@ static const struct option options[] = {
 | 
				
			||||||
			"target executable name or path", opt_set_target),
 | 
								"target executable name or path", opt_set_target),
 | 
				
			||||||
	OPT_END()
 | 
						OPT_END()
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					 | 
				
			||||||
int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	argc = parse_options(argc, argv, options, probe_usage,
 | 
						argc = parse_options(argc, argv, options, probe_usage,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,15 +31,6 @@
 | 
				
			||||||
#include <sched.h>
 | 
					#include <sched.h>
 | 
				
			||||||
#include <sys/mman.h>
 | 
					#include <sys/mman.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef NO_LIBUNWIND_SUPPORT
 | 
					 | 
				
			||||||
static char callchain_help[] = CALLCHAIN_HELP "[fp]";
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
static unsigned long default_stack_dump_size = 8192;
 | 
					 | 
				
			||||||
static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum write_mode_t {
 | 
					enum write_mode_t {
 | 
				
			||||||
	WRITE_FORCE,
 | 
						WRITE_FORCE,
 | 
				
			||||||
	WRITE_APPEND
 | 
						WRITE_APPEND
 | 
				
			||||||
| 
						 | 
					@ -800,7 +791,7 @@ error:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef NO_LIBUNWIND_SUPPORT
 | 
					#ifdef LIBUNWIND_SUPPORT
 | 
				
			||||||
static int get_stack_size(char *str, unsigned long *_size)
 | 
					static int get_stack_size(char *str, unsigned long *_size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *endptr;
 | 
						char *endptr;
 | 
				
			||||||
| 
						 | 
					@ -826,7 +817,7 @@ static int get_stack_size(char *str, unsigned long *_size)
 | 
				
			||||||
	       max_size, str);
 | 
						       max_size, str);
 | 
				
			||||||
	return -1;
 | 
						return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* !NO_LIBUNWIND_SUPPORT */
 | 
					#endif /* LIBUNWIND_SUPPORT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
 | 
					parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
 | 
				
			||||||
| 
						 | 
					@ -865,9 +856,11 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
 | 
				
			||||||
				       "needed for -g fp\n");
 | 
									       "needed for -g fp\n");
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef NO_LIBUNWIND_SUPPORT
 | 
					#ifdef LIBUNWIND_SUPPORT
 | 
				
			||||||
		/* Dwarf style */
 | 
							/* Dwarf style */
 | 
				
			||||||
		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
 | 
							} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
 | 
				
			||||||
 | 
								const unsigned long default_stack_dump_size = 8192;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ret = 0;
 | 
								ret = 0;
 | 
				
			||||||
			rec->opts.call_graph = CALLCHAIN_DWARF;
 | 
								rec->opts.call_graph = CALLCHAIN_DWARF;
 | 
				
			||||||
			rec->opts.stack_dump_size = default_stack_dump_size;
 | 
								rec->opts.stack_dump_size = default_stack_dump_size;
 | 
				
			||||||
| 
						 | 
					@ -883,7 +876,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
 | 
				
			||||||
			if (!ret)
 | 
								if (!ret)
 | 
				
			||||||
				pr_debug("callchain: stack dump size %d\n",
 | 
									pr_debug("callchain: stack dump size %d\n",
 | 
				
			||||||
					 rec->opts.stack_dump_size);
 | 
										 rec->opts.stack_dump_size);
 | 
				
			||||||
#endif /* !NO_LIBUNWIND_SUPPORT */
 | 
					#endif /* LIBUNWIND_SUPPORT */
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			pr_err("callchain: Unknown -g option "
 | 
								pr_err("callchain: Unknown -g option "
 | 
				
			||||||
			       "value: %s\n", arg);
 | 
								       "value: %s\n", arg);
 | 
				
			||||||
| 
						 | 
					@ -930,6 +923,14 @@ static struct perf_record record = {
 | 
				
			||||||
	.file_new   = true,
 | 
						.file_new   = true,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef LIBUNWIND_SUPPORT
 | 
				
			||||||
 | 
					static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static const char callchain_help[] = CALLCHAIN_HELP "[fp]";
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
 | 
					 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
 | 
				
			||||||
 * with it and switch to use the library functions in perf_evlist that came
 | 
					 * with it and switch to use the library functions in perf_evlist that came
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -320,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
 | 
				
			||||||
		const char *evname = perf_evsel__name(pos);
 | 
							const char *evname = perf_evsel__name(pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		hists__fprintf_nr_sample_events(hists, evname, stdout);
 | 
							hists__fprintf_nr_sample_events(hists, evname, stdout);
 | 
				
			||||||
		hists__fprintf(hists, NULL, false, true, 0, 0, stdout);
 | 
							hists__fprintf(hists, true, 0, 0, stdout);
 | 
				
			||||||
		fprintf(stdout, "\n\n");
 | 
							fprintf(stdout, "\n\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
		setup_browser(true);
 | 
							setup_browser(true);
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		use_browser = 0;
 | 
							use_browser = 0;
 | 
				
			||||||
		perf_hpp__init(false, false);
 | 
							perf_hpp__init();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setup_sorting(report_usage, options);
 | 
						setup_sorting(report_usage, options);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1426,7 +1426,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
 | 
				
			||||||
						 struct perf_evsel *evsel,
 | 
											 struct perf_evsel *evsel,
 | 
				
			||||||
						 struct machine *machine)
 | 
											 struct machine *machine)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct thread *thread = machine__findnew_thread(machine, sample->pid);
 | 
						struct thread *thread = machine__findnew_thread(machine, sample->tid);
 | 
				
			||||||
	int err = 0;
 | 
						int err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (thread == NULL) {
 | 
						if (thread == NULL) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,6 @@ static u64			last_timestamp;
 | 
				
			||||||
static u64			nr_unordered;
 | 
					static u64			nr_unordered;
 | 
				
			||||||
extern const struct option	record_options[];
 | 
					extern const struct option	record_options[];
 | 
				
			||||||
static bool			no_callchain;
 | 
					static bool			no_callchain;
 | 
				
			||||||
static bool			show_full_info;
 | 
					 | 
				
			||||||
static bool			system_wide;
 | 
					static bool			system_wide;
 | 
				
			||||||
static const char		*cpu_list;
 | 
					static const char		*cpu_list;
 | 
				
			||||||
static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 | 
					static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 | 
				
			||||||
| 
						 | 
					@ -473,8 +472,6 @@ static int cleanup_scripting(void)
 | 
				
			||||||
	return scripting_ops->stop_script();
 | 
						return scripting_ops->stop_script();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *input_name;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int process_sample_event(struct perf_tool *tool __maybe_unused,
 | 
					static int process_sample_event(struct perf_tool *tool __maybe_unused,
 | 
				
			||||||
				union perf_event *event,
 | 
									union perf_event *event,
 | 
				
			||||||
				struct perf_sample *sample,
 | 
									struct perf_sample *sample,
 | 
				
			||||||
| 
						 | 
					@ -1156,62 +1153,6 @@ out:
 | 
				
			||||||
	return n_args;
 | 
						return n_args;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const script_usage[] = {
 | 
					 | 
				
			||||||
	"perf script [<options>]",
 | 
					 | 
				
			||||||
	"perf script [<options>] record <script> [<record-options>] <command>",
 | 
					 | 
				
			||||||
	"perf script [<options>] report <script> [script-args]",
 | 
					 | 
				
			||||||
	"perf script [<options>] <script> [<record-options>] <command>",
 | 
					 | 
				
			||||||
	"perf script [<options>] <top-script> [script-args]",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct option options[] = {
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
 | 
					 | 
				
			||||||
		    "dump raw trace in ASCII"),
 | 
					 | 
				
			||||||
	OPT_INCR('v', "verbose", &verbose,
 | 
					 | 
				
			||||||
		    "be more verbose (show symbol address, etc)"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('L', "Latency", &latency_format,
 | 
					 | 
				
			||||||
		    "show latency attributes (irqs/preemption disabled, etc)"),
 | 
					 | 
				
			||||||
	OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
 | 
					 | 
				
			||||||
			   list_available_scripts),
 | 
					 | 
				
			||||||
	OPT_CALLBACK('s', "script", NULL, "name",
 | 
					 | 
				
			||||||
		     "script file name (lang:script name, script name, or *)",
 | 
					 | 
				
			||||||
		     parse_scriptname),
 | 
					 | 
				
			||||||
	OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
 | 
					 | 
				
			||||||
		   "generate perf-script.xx script in specified language"),
 | 
					 | 
				
			||||||
	OPT_STRING('i', "input", &input_name, "file",
 | 
					 | 
				
			||||||
		    "input file name"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('d', "debug-mode", &debug_mode,
 | 
					 | 
				
			||||||
		   "do various checks like samples ordering and lost events"),
 | 
					 | 
				
			||||||
	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 | 
					 | 
				
			||||||
		   "file", "vmlinux pathname"),
 | 
					 | 
				
			||||||
	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
 | 
					 | 
				
			||||||
		   "file", "kallsyms pathname"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
 | 
					 | 
				
			||||||
		    "When printing symbols do not display call chain"),
 | 
					 | 
				
			||||||
	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 | 
					 | 
				
			||||||
		    "Look for files with symbols relative to this directory"),
 | 
					 | 
				
			||||||
	OPT_CALLBACK('f', "fields", NULL, "str",
 | 
					 | 
				
			||||||
		     "comma separated output fields prepend with 'type:'. "
 | 
					 | 
				
			||||||
		     "Valid types: hw,sw,trace,raw. "
 | 
					 | 
				
			||||||
		     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
 | 
					 | 
				
			||||||
		     "addr,symoff",
 | 
					 | 
				
			||||||
		     parse_output_fields),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('a', "all-cpus", &system_wide,
 | 
					 | 
				
			||||||
		     "system-wide collection from all CPUs"),
 | 
					 | 
				
			||||||
	OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
 | 
					 | 
				
			||||||
		   "only consider these symbols"),
 | 
					 | 
				
			||||||
	OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
 | 
					 | 
				
			||||||
	OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
 | 
					 | 
				
			||||||
		   "only display events for these comms"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('I', "show-info", &show_full_info,
 | 
					 | 
				
			||||||
		    "display extended information from perf.data file"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
 | 
					 | 
				
			||||||
		    "Show the path of [kernel.kallsyms]"),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	OPT_END()
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int have_cmd(int argc, const char **argv)
 | 
					static int have_cmd(int argc, const char **argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char **__argv = malloc(sizeof(const char *) * argc);
 | 
						char **__argv = malloc(sizeof(const char *) * argc);
 | 
				
			||||||
| 
						 | 
					@ -1233,12 +1174,65 @@ static int have_cmd(int argc, const char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
					int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						bool show_full_info = false;
 | 
				
			||||||
 | 
						const char *input_name = NULL;
 | 
				
			||||||
	char *rec_script_path = NULL;
 | 
						char *rec_script_path = NULL;
 | 
				
			||||||
	char *rep_script_path = NULL;
 | 
						char *rep_script_path = NULL;
 | 
				
			||||||
	struct perf_session *session;
 | 
						struct perf_session *session;
 | 
				
			||||||
	char *script_path = NULL;
 | 
						char *script_path = NULL;
 | 
				
			||||||
	const char **__argv;
 | 
						const char **__argv;
 | 
				
			||||||
	int i, j, err;
 | 
						int i, j, err;
 | 
				
			||||||
 | 
						const struct option options[] = {
 | 
				
			||||||
 | 
						OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
 | 
				
			||||||
 | 
							    "dump raw trace in ASCII"),
 | 
				
			||||||
 | 
						OPT_INCR('v', "verbose", &verbose,
 | 
				
			||||||
 | 
							 "be more verbose (show symbol address, etc)"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('L', "Latency", &latency_format,
 | 
				
			||||||
 | 
							    "show latency attributes (irqs/preemption disabled, etc)"),
 | 
				
			||||||
 | 
						OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
 | 
				
			||||||
 | 
								   list_available_scripts),
 | 
				
			||||||
 | 
						OPT_CALLBACK('s', "script", NULL, "name",
 | 
				
			||||||
 | 
							     "script file name (lang:script name, script name, or *)",
 | 
				
			||||||
 | 
							     parse_scriptname),
 | 
				
			||||||
 | 
						OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
 | 
				
			||||||
 | 
							   "generate perf-script.xx script in specified language"),
 | 
				
			||||||
 | 
						OPT_STRING('i', "input", &input_name, "file", "input file name"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('d', "debug-mode", &debug_mode,
 | 
				
			||||||
 | 
							   "do various checks like samples ordering and lost events"),
 | 
				
			||||||
 | 
						OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 | 
				
			||||||
 | 
							   "file", "vmlinux pathname"),
 | 
				
			||||||
 | 
						OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
 | 
				
			||||||
 | 
							   "file", "kallsyms pathname"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
 | 
				
			||||||
 | 
							    "When printing symbols do not display call chain"),
 | 
				
			||||||
 | 
						OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
 | 
				
			||||||
 | 
							    "Look for files with symbols relative to this directory"),
 | 
				
			||||||
 | 
						OPT_CALLBACK('f', "fields", NULL, "str",
 | 
				
			||||||
 | 
							     "comma separated output fields prepend with 'type:'. "
 | 
				
			||||||
 | 
							     "Valid types: hw,sw,trace,raw. "
 | 
				
			||||||
 | 
							     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
 | 
				
			||||||
 | 
							     "addr,symoff", parse_output_fields),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('a', "all-cpus", &system_wide,
 | 
				
			||||||
 | 
							    "system-wide collection from all CPUs"),
 | 
				
			||||||
 | 
						OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
 | 
				
			||||||
 | 
							   "only consider these symbols"),
 | 
				
			||||||
 | 
						OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
 | 
				
			||||||
 | 
						OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
 | 
				
			||||||
 | 
							   "only display events for these comms"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('I', "show-info", &show_full_info,
 | 
				
			||||||
 | 
							    "display extended information from perf.data file"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
 | 
				
			||||||
 | 
							    "Show the path of [kernel.kallsyms]"),
 | 
				
			||||||
 | 
						OPT_END()
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const char * const script_usage[] = {
 | 
				
			||||||
 | 
							"perf script [<options>]",
 | 
				
			||||||
 | 
							"perf script [<options>] record <script> [<record-options>] <command>",
 | 
				
			||||||
 | 
							"perf script [<options>] report <script> [script-args]",
 | 
				
			||||||
 | 
							"perf script [<options>] <script> [<record-options>] <command>",
 | 
				
			||||||
 | 
							"perf script [<options>] <top-script> [script-args]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setup_scripting();
 | 
						setup_scripting();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,122 +64,12 @@
 | 
				
			||||||
#define CNTR_NOT_SUPPORTED	"<not supported>"
 | 
					#define CNTR_NOT_SUPPORTED	"<not supported>"
 | 
				
			||||||
#define CNTR_NOT_COUNTED	"<not counted>"
 | 
					#define CNTR_NOT_COUNTED	"<not counted>"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct perf_event_attr default_attrs[] = {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK		},
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES	},
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS		},
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS		},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES		},
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND	},
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND	},
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS		},
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS	},
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES		},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Detailed stats (-d), covering the L1 and last level data caches:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static struct perf_event_attr detailed_attrs[] = {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_LL			<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_LL			<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static struct perf_event_attr very_detailed_attrs[] = {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_L1I		<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_L1I		<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_DTLB		<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_DTLB		<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_ITLB		<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_ITLB		<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Very, very detailed stats (-d -d -d), adding prefetch events:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static struct perf_event_attr very_very_detailed_attrs[] = {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_PREFETCH	<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  { .type = PERF_TYPE_HW_CACHE,
 | 
					 | 
				
			||||||
    .config =
 | 
					 | 
				
			||||||
	 PERF_COUNT_HW_CACHE_L1D		<<  0  |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_OP_PREFETCH	<<  8) |
 | 
					 | 
				
			||||||
	(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct perf_evlist	*evsel_list;
 | 
					static struct perf_evlist	*evsel_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct perf_target	target = {
 | 
					static struct perf_target	target = {
 | 
				
			||||||
	.uid	= UINT_MAX,
 | 
						.uid	= UINT_MAX,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int			run_idx				=  0;
 | 
					 | 
				
			||||||
static int			run_count			=  1;
 | 
					static int			run_count			=  1;
 | 
				
			||||||
static bool			no_inherit			= false;
 | 
					static bool			no_inherit			= false;
 | 
				
			||||||
static bool			scale				=  true;
 | 
					static bool			scale				=  true;
 | 
				
			||||||
| 
						 | 
					@ -187,15 +77,12 @@ static bool			no_aggr				= false;
 | 
				
			||||||
static pid_t			child_pid			= -1;
 | 
					static pid_t			child_pid			= -1;
 | 
				
			||||||
static bool			null_run			=  false;
 | 
					static bool			null_run			=  false;
 | 
				
			||||||
static int			detailed_run			=  0;
 | 
					static int			detailed_run			=  0;
 | 
				
			||||||
static bool			sync_run			=  false;
 | 
					 | 
				
			||||||
static bool			big_num				=  true;
 | 
					static bool			big_num				=  true;
 | 
				
			||||||
static int			big_num_opt			=  -1;
 | 
					static int			big_num_opt			=  -1;
 | 
				
			||||||
static const char		*csv_sep			= NULL;
 | 
					static const char		*csv_sep			= NULL;
 | 
				
			||||||
static bool			csv_output			= false;
 | 
					static bool			csv_output			= false;
 | 
				
			||||||
static bool			group				= false;
 | 
					static bool			group				= false;
 | 
				
			||||||
static const char		*output_name			= NULL;
 | 
					 | 
				
			||||||
static FILE			*output				= NULL;
 | 
					static FILE			*output				= NULL;
 | 
				
			||||||
static int			output_fd;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static volatile int done = 0;
 | 
					static volatile int done = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1028,11 +915,6 @@ static void sig_atexit(void)
 | 
				
			||||||
	kill(getpid(), signr);
 | 
						kill(getpid(), signr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const stat_usage[] = {
 | 
					 | 
				
			||||||
	"perf stat [<options>] [<command>]",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int stat__set_big_num(const struct option *opt __maybe_unused,
 | 
					static int stat__set_big_num(const struct option *opt __maybe_unused,
 | 
				
			||||||
			     const char *s __maybe_unused, int unset)
 | 
								     const char *s __maybe_unused, int unset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1040,62 +922,119 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool append_file;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct option options[] = {
 | 
					 | 
				
			||||||
	OPT_CALLBACK('e', "event", &evsel_list, "event",
 | 
					 | 
				
			||||||
		     "event selector. use 'perf list' to list available events",
 | 
					 | 
				
			||||||
		     parse_events_option),
 | 
					 | 
				
			||||||
	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
 | 
					 | 
				
			||||||
		     "event filter", parse_filter),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
 | 
					 | 
				
			||||||
		    "child tasks do not inherit counters"),
 | 
					 | 
				
			||||||
	OPT_STRING('p', "pid", &target.pid, "pid",
 | 
					 | 
				
			||||||
		   "stat events on existing process id"),
 | 
					 | 
				
			||||||
	OPT_STRING('t', "tid", &target.tid, "tid",
 | 
					 | 
				
			||||||
		   "stat events on existing thread id"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
 | 
					 | 
				
			||||||
		    "system-wide collection from all CPUs"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('g', "group", &group,
 | 
					 | 
				
			||||||
		    "put the counters into a counter group"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('c', "scale", &scale,
 | 
					 | 
				
			||||||
		    "scale/normalize counters"),
 | 
					 | 
				
			||||||
	OPT_INCR('v', "verbose", &verbose,
 | 
					 | 
				
			||||||
		    "be more verbose (show counter open errors, etc)"),
 | 
					 | 
				
			||||||
	OPT_INTEGER('r', "repeat", &run_count,
 | 
					 | 
				
			||||||
		    "repeat command and print average + stddev (max: 100)"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('n', "null", &null_run,
 | 
					 | 
				
			||||||
		    "null run - dont start any counters"),
 | 
					 | 
				
			||||||
	OPT_INCR('d', "detailed", &detailed_run,
 | 
					 | 
				
			||||||
		    "detailed run - start a lot of events"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('S', "sync", &sync_run,
 | 
					 | 
				
			||||||
		    "call sync() before starting a run"),
 | 
					 | 
				
			||||||
	OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 
 | 
					 | 
				
			||||||
			   "print large numbers with thousands\' separators",
 | 
					 | 
				
			||||||
			   stat__set_big_num),
 | 
					 | 
				
			||||||
	OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
 | 
					 | 
				
			||||||
		    "list of cpus to monitor in system-wide"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN('A', "no-aggr", &no_aggr,
 | 
					 | 
				
			||||||
		    "disable CPU count aggregation"),
 | 
					 | 
				
			||||||
	OPT_STRING('x', "field-separator", &csv_sep, "separator",
 | 
					 | 
				
			||||||
		   "print counts with custom separator"),
 | 
					 | 
				
			||||||
	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
 | 
					 | 
				
			||||||
		     "monitor event in cgroup name only",
 | 
					 | 
				
			||||||
		     parse_cgroups),
 | 
					 | 
				
			||||||
	OPT_STRING('o', "output", &output_name, "file",
 | 
					 | 
				
			||||||
		    "output file name"),
 | 
					 | 
				
			||||||
	OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
 | 
					 | 
				
			||||||
	OPT_INTEGER(0, "log-fd", &output_fd,
 | 
					 | 
				
			||||||
		    "log output to fd, instead of stderr"),
 | 
					 | 
				
			||||||
	OPT_END()
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Add default attributes, if there were no attributes specified or
 | 
					 * Add default attributes, if there were no attributes specified or
 | 
				
			||||||
 * if -d/--detailed, -d -d or -d -d -d is used:
 | 
					 * if -d/--detailed, -d -d or -d -d -d is used:
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int add_default_attributes(void)
 | 
					static int add_default_attributes(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct perf_event_attr default_attrs[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK		},
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES	},
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS		},
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS		},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES		},
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND	},
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND	},
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS		},
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS	},
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES		},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Detailed stats (-d), covering the L1 and last level data caches:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						struct perf_event_attr detailed_attrs[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_L1D		<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_L1D		<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_LL			<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_LL			<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						struct perf_event_attr very_detailed_attrs[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_L1I		<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_L1I		<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_DTLB		<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_DTLB		<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_ITLB		<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_ITLB		<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_READ		<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Very, very detailed stats (-d -d -d), adding prefetch events:
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
						struct perf_event_attr very_very_detailed_attrs[] = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_L1D		<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_PREFETCH	<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_ACCESS	<< 16)				},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  { .type = PERF_TYPE_HW_CACHE,
 | 
				
			||||||
 | 
					    .config =
 | 
				
			||||||
 | 
						 PERF_COUNT_HW_CACHE_L1D		<<  0  |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_OP_PREFETCH	<<  8) |
 | 
				
			||||||
 | 
						(PERF_COUNT_HW_CACHE_RESULT_MISS	<< 16)				},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Set attrs if no event is selected and !null_run: */
 | 
						/* Set attrs if no event is selected and !null_run: */
 | 
				
			||||||
	if (null_run)
 | 
						if (null_run)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -1130,8 +1069,59 @@ static int add_default_attributes(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
					int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						bool append_file = false,
 | 
				
			||||||
 | 
						     sync_run = false;
 | 
				
			||||||
 | 
						int output_fd = 0;
 | 
				
			||||||
 | 
						const char *output_name	= NULL;
 | 
				
			||||||
 | 
						const struct option options[] = {
 | 
				
			||||||
 | 
						OPT_CALLBACK('e', "event", &evsel_list, "event",
 | 
				
			||||||
 | 
							     "event selector. use 'perf list' to list available events",
 | 
				
			||||||
 | 
							     parse_events_option),
 | 
				
			||||||
 | 
						OPT_CALLBACK(0, "filter", &evsel_list, "filter",
 | 
				
			||||||
 | 
							     "event filter", parse_filter),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('i', "no-inherit", &no_inherit,
 | 
				
			||||||
 | 
							    "child tasks do not inherit counters"),
 | 
				
			||||||
 | 
						OPT_STRING('p', "pid", &target.pid, "pid",
 | 
				
			||||||
 | 
							   "stat events on existing process id"),
 | 
				
			||||||
 | 
						OPT_STRING('t', "tid", &target.tid, "tid",
 | 
				
			||||||
 | 
							   "stat events on existing thread id"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
 | 
				
			||||||
 | 
							    "system-wide collection from all CPUs"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('g', "group", &group,
 | 
				
			||||||
 | 
							    "put the counters into a counter group"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('c', "scale", &scale, "scale/normalize counters"),
 | 
				
			||||||
 | 
						OPT_INCR('v', "verbose", &verbose,
 | 
				
			||||||
 | 
							    "be more verbose (show counter open errors, etc)"),
 | 
				
			||||||
 | 
						OPT_INTEGER('r', "repeat", &run_count,
 | 
				
			||||||
 | 
							    "repeat command and print average + stddev (max: 100)"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('n', "null", &null_run,
 | 
				
			||||||
 | 
							    "null run - dont start any counters"),
 | 
				
			||||||
 | 
						OPT_INCR('d', "detailed", &detailed_run,
 | 
				
			||||||
 | 
							    "detailed run - start a lot of events"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('S', "sync", &sync_run,
 | 
				
			||||||
 | 
							    "call sync() before starting a run"),
 | 
				
			||||||
 | 
						OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 
 | 
				
			||||||
 | 
								   "print large numbers with thousands\' separators",
 | 
				
			||||||
 | 
								   stat__set_big_num),
 | 
				
			||||||
 | 
						OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
 | 
				
			||||||
 | 
							    "list of cpus to monitor in system-wide"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('A', "no-aggr", &no_aggr, "disable CPU count aggregation"),
 | 
				
			||||||
 | 
						OPT_STRING('x', "field-separator", &csv_sep, "separator",
 | 
				
			||||||
 | 
							   "print counts with custom separator"),
 | 
				
			||||||
 | 
						OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
 | 
				
			||||||
 | 
							     "monitor event in cgroup name only", parse_cgroups),
 | 
				
			||||||
 | 
						OPT_STRING('o', "output", &output_name, "file", "output file name"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
 | 
				
			||||||
 | 
						OPT_INTEGER(0, "log-fd", &output_fd,
 | 
				
			||||||
 | 
							    "log output to fd, instead of stderr"),
 | 
				
			||||||
 | 
						OPT_END()
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						const char * const stat_usage[] = {
 | 
				
			||||||
 | 
							"perf stat [<options>] [<command>]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	struct perf_evsel *pos;
 | 
						struct perf_evsel *pos;
 | 
				
			||||||
	int status = -ENOMEM;
 | 
						int status = -ENOMEM, run_idx;
 | 
				
			||||||
	const char *mode;
 | 
						const char *mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setlocale(LC_ALL, "");
 | 
						setlocale(LC_ALL, "");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,9 +38,6 @@
 | 
				
			||||||
#define PWR_EVENT_EXIT -1
 | 
					#define PWR_EVENT_EXIT -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char	*input_name;
 | 
					 | 
				
			||||||
static const char	*output_name = "output.svg";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static unsigned int	numcpus;
 | 
					static unsigned int	numcpus;
 | 
				
			||||||
static u64		min_freq;	/* Lowest CPU frequency seen */
 | 
					static u64		min_freq;	/* Lowest CPU frequency seen */
 | 
				
			||||||
static u64		max_freq;	/* Highest CPU frequency seen */
 | 
					static u64		max_freq;	/* Highest CPU frequency seen */
 | 
				
			||||||
| 
						 | 
					@ -968,16 +965,15 @@ static void write_svg_file(const char *filename)
 | 
				
			||||||
	svg_close();
 | 
						svg_close();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct perf_tool perf_timechart = {
 | 
					static int __cmd_timechart(const char *input_name, const char *output_name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct perf_tool perf_timechart = {
 | 
				
			||||||
		.comm		 = process_comm_event,
 | 
							.comm		 = process_comm_event,
 | 
				
			||||||
		.fork		 = process_fork_event,
 | 
							.fork		 = process_fork_event,
 | 
				
			||||||
		.exit		 = process_exit_event,
 | 
							.exit		 = process_exit_event,
 | 
				
			||||||
		.sample		 = process_sample_event,
 | 
							.sample		 = process_sample_event,
 | 
				
			||||||
		.ordered_samples = true,
 | 
							.ordered_samples = true,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __cmd_timechart(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct perf_session *session = perf_session__new(input_name, O_RDONLY,
 | 
						struct perf_session *session = perf_session__new(input_name, O_RDONLY,
 | 
				
			||||||
							 0, false, &perf_timechart);
 | 
												 0, false, &perf_timechart);
 | 
				
			||||||
	int ret = -EINVAL;
 | 
						int ret = -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -1005,18 +1001,11 @@ out_delete:
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const timechart_usage[] = {
 | 
					static int __cmd_record(int argc, const char **argv)
 | 
				
			||||||
	"perf timechart [<options>] {record}",
 | 
					{
 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef SUPPORT_OLD_POWER_EVENTS
 | 
					#ifdef SUPPORT_OLD_POWER_EVENTS
 | 
				
			||||||
static const char * const record_old_args[] = {
 | 
						const char * const record_old_args[] = {
 | 
				
			||||||
	"record",
 | 
							"record", "-a", "-R", "-f", "-c", "1",
 | 
				
			||||||
	"-a",
 | 
					 | 
				
			||||||
	"-R",
 | 
					 | 
				
			||||||
	"-f",
 | 
					 | 
				
			||||||
	"-c", "1",
 | 
					 | 
				
			||||||
		"-e", "power:power_start",
 | 
							"-e", "power:power_start",
 | 
				
			||||||
		"-e", "power:power_end",
 | 
							"-e", "power:power_end",
 | 
				
			||||||
		"-e", "power:power_frequency",
 | 
							"-e", "power:power_frequency",
 | 
				
			||||||
| 
						 | 
					@ -1024,21 +1013,13 @@ static const char * const record_old_args[] = {
 | 
				
			||||||
		"-e", "sched:sched_switch",
 | 
							"-e", "sched:sched_switch",
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
						const char * const record_new_args[] = {
 | 
				
			||||||
static const char * const record_new_args[] = {
 | 
							"record", "-a", "-R", "-f", "-c", "1",
 | 
				
			||||||
	"record",
 | 
					 | 
				
			||||||
	"-a",
 | 
					 | 
				
			||||||
	"-R",
 | 
					 | 
				
			||||||
	"-f",
 | 
					 | 
				
			||||||
	"-c", "1",
 | 
					 | 
				
			||||||
		"-e", "power:cpu_frequency",
 | 
							"-e", "power:cpu_frequency",
 | 
				
			||||||
		"-e", "power:cpu_idle",
 | 
							"-e", "power:cpu_idle",
 | 
				
			||||||
		"-e", "sched:sched_wakeup",
 | 
							"-e", "sched:sched_wakeup",
 | 
				
			||||||
		"-e", "sched:sched_switch",
 | 
							"-e", "sched:sched_switch",
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __cmd_record(int argc, const char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned int rec_argc, i, j;
 | 
						unsigned int rec_argc, i, j;
 | 
				
			||||||
	const char **rec_argv;
 | 
						const char **rec_argv;
 | 
				
			||||||
	const char * const *record_args = record_new_args;
 | 
						const char * const *record_args = record_new_args;
 | 
				
			||||||
| 
						 | 
					@ -1077,15 +1058,16 @@ parse_process(const struct option *opt __maybe_unused, const char *arg,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct option options[] = {
 | 
					int cmd_timechart(int argc, const char **argv,
 | 
				
			||||||
	OPT_STRING('i', "input", &input_name, "file",
 | 
							  const char *prefix __maybe_unused)
 | 
				
			||||||
		    "input file name"),
 | 
					{
 | 
				
			||||||
	OPT_STRING('o', "output", &output_name, "file",
 | 
						const char *input_name;
 | 
				
			||||||
		    "output file name"),
 | 
						const char *output_name = "output.svg";
 | 
				
			||||||
	OPT_INTEGER('w', "width", &svg_page_width,
 | 
						const struct option options[] = {
 | 
				
			||||||
		    "page width"),
 | 
						OPT_STRING('i', "input", &input_name, "file", "input file name"),
 | 
				
			||||||
	OPT_BOOLEAN('P', "power-only", &power_only,
 | 
						OPT_STRING('o', "output", &output_name, "file", "output file name"),
 | 
				
			||||||
		    "output power data only"),
 | 
						OPT_INTEGER('w', "width", &svg_page_width, "page width"),
 | 
				
			||||||
 | 
						OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"),
 | 
				
			||||||
	OPT_CALLBACK('p', "process", NULL, "process",
 | 
						OPT_CALLBACK('p', "process", NULL, "process",
 | 
				
			||||||
		      "process selector. Pass a pid or process name.",
 | 
							      "process selector. Pass a pid or process name.",
 | 
				
			||||||
		       parse_process),
 | 
							       parse_process),
 | 
				
			||||||
| 
						 | 
					@ -1093,11 +1075,11 @@ static const struct option options[] = {
 | 
				
			||||||
		    "Look for files with symbols relative to this directory"),
 | 
							    "Look for files with symbols relative to this directory"),
 | 
				
			||||||
	OPT_END()
 | 
						OPT_END()
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						const char * const timechart_usage[] = {
 | 
				
			||||||
 | 
							"perf timechart [<options>] {record}",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
int cmd_timechart(int argc, const char **argv,
 | 
					 | 
				
			||||||
		  const char *prefix __maybe_unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	argc = parse_options(argc, argv, options, timechart_usage,
 | 
						argc = parse_options(argc, argv, options, timechart_usage,
 | 
				
			||||||
			PARSE_OPT_STOP_AT_NON_OPTION);
 | 
								PARSE_OPT_STOP_AT_NON_OPTION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1110,5 +1092,5 @@ int cmd_timechart(int argc, const char **argv,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setup_pager();
 | 
						setup_pager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return __cmd_timechart();
 | 
						return __cmd_timechart(input_name, output_name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -316,7 +316,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
 | 
				
			||||||
	hists__output_recalc_col_len(&top->sym_evsel->hists,
 | 
						hists__output_recalc_col_len(&top->sym_evsel->hists,
 | 
				
			||||||
				     top->winsize.ws_row - 3);
 | 
									     top->winsize.ws_row - 3);
 | 
				
			||||||
	putchar('\n');
 | 
						putchar('\n');
 | 
				
			||||||
	hists__fprintf(&top->sym_evsel->hists, NULL, false, false,
 | 
						hists__fprintf(&top->sym_evsel->hists, false,
 | 
				
			||||||
		       top->winsize.ws_row - 4 - printed, win_width, stdout);
 | 
							       top->winsize.ws_row - 4 - printed, win_width, stdout);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1159,11 +1159,6 @@ setup:
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char * const top_usage[] = {
 | 
					 | 
				
			||||||
	"perf top [<options>]",
 | 
					 | 
				
			||||||
	NULL
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
					int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct perf_evsel *pos;
 | 
						struct perf_evsel *pos;
 | 
				
			||||||
| 
						 | 
					@ -1250,6 +1245,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
 | 
				
			||||||
	OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"),
 | 
						OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"),
 | 
				
			||||||
	OPT_END()
 | 
						OPT_END()
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						const char * const top_usage[] = {
 | 
				
			||||||
 | 
							"perf top [<options>]",
 | 
				
			||||||
 | 
							NULL
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	top.evlist = perf_evlist__new(NULL, NULL);
 | 
						top.evlist = perf_evlist__new(NULL, NULL);
 | 
				
			||||||
	if (top.evlist == NULL)
 | 
						if (top.evlist == NULL)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,10 +114,85 @@ static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FIL
 | 
				
			||||||
	return printed;
 | 
						return printed;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
 | 
				
			||||||
 | 
									  struct perf_sample *sample);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct syscall *trace__syscall_info(struct trace *trace,
 | 
				
			||||||
 | 
										   struct perf_evsel *evsel,
 | 
				
			||||||
 | 
										   struct perf_sample *sample)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int id = perf_evsel__intval(evsel, sample, "id");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (id < 0) {
 | 
				
			||||||
 | 
							printf("Invalid syscall %d id, skipping...\n", id);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
 | 
				
			||||||
 | 
						    trace__read_syscall_info(trace, id))
 | 
				
			||||||
 | 
							goto out_cant_read;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
 | 
				
			||||||
 | 
							goto out_cant_read;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &trace->syscalls.table[id];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out_cant_read:
 | 
				
			||||||
 | 
						printf("Problems reading syscall %d information\n", id);
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
 | 
				
			||||||
 | 
								    struct perf_sample *sample)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						void *args;
 | 
				
			||||||
 | 
						struct syscall *sc = trace__syscall_info(trace, evsel, sample);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sc == NULL)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						args = perf_evsel__rawptr(evsel, sample, "args");
 | 
				
			||||||
 | 
						if (args == NULL) {
 | 
				
			||||||
 | 
							printf("Problems reading syscall arguments\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf("%s(", sc->name);
 | 
				
			||||||
 | 
						syscall__fprintf_args(sc, args, stdout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
 | 
				
			||||||
 | 
								   struct perf_sample *sample)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
						struct syscall *sc = trace__syscall_info(trace, evsel, sample);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sc == NULL)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = perf_evsel__intval(evsel, sample, "ret");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
 | 
				
			||||||
 | 
							char bf[256];
 | 
				
			||||||
 | 
							const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
 | 
				
			||||||
 | 
								   *e = audit_errno_to_name(-ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							printf(") = -1 %s %s", e, emsg);
 | 
				
			||||||
 | 
						} else if (ret == 0 && sc->fmt && sc->fmt->timeout)
 | 
				
			||||||
 | 
							printf(") = 0 Timeout");
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							printf(") = %d", ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						putchar('\n');
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int trace__run(struct trace *trace)
 | 
					static int trace__run(struct trace *trace)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
 | 
						struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
 | 
				
			||||||
	struct perf_evsel *evsel, *evsel_enter, *evsel_exit;
 | 
						struct perf_evsel *evsel;
 | 
				
			||||||
	int err = -1, i, nr_events = 0, before;
 | 
						int err = -1, i, nr_events = 0, before;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (evlist == NULL) {
 | 
						if (evlist == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -125,22 +200,12 @@ static int trace__run(struct trace *trace)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
 | 
						if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
 | 
				
			||||||
	if (evsel_enter == NULL) {
 | 
						    perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
 | 
				
			||||||
		printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n");
 | 
							printf("Couldn't read the raw_syscalls tracepoints information!\n");
 | 
				
			||||||
		goto out_delete_evlist;
 | 
							goto out_delete_evlist;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	perf_evlist__add(evlist, evsel_enter);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
 | 
					 | 
				
			||||||
	if (evsel_exit == NULL) {
 | 
					 | 
				
			||||||
		printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
 | 
					 | 
				
			||||||
		goto out_delete_evlist;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	perf_evlist__add(evlist, evsel_exit);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = perf_evlist__create_maps(evlist, &trace->opts.target);
 | 
						err = perf_evlist__create_maps(evlist, &trace->opts.target);
 | 
				
			||||||
	if (err < 0) {
 | 
						if (err < 0) {
 | 
				
			||||||
		printf("Problems parsing the target to trace, check your options!\n");
 | 
							printf("Problems parsing the target to trace, check your options!\n");
 | 
				
			||||||
| 
						 | 
					@ -170,9 +235,8 @@ again:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
 | 
							while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
 | 
				
			||||||
			const u32 type = event->header.type;
 | 
								const u32 type = event->header.type;
 | 
				
			||||||
			struct syscall *sc;
 | 
								tracepoint_handler handler;
 | 
				
			||||||
			struct perf_sample sample;
 | 
								struct perf_sample sample;
 | 
				
			||||||
			int id;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			++nr_events;
 | 
								++nr_events;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,45 +264,11 @@ again:
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			id = perf_evsel__intval(evsel, &sample, "id");
 | 
					 | 
				
			||||||
			if (id < 0) {
 | 
					 | 
				
			||||||
				printf("Invalid syscall %d id, skipping...\n", id);
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
 | 
					 | 
				
			||||||
			    trace__read_syscall_info(trace, id))
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			sc = &trace->syscalls.table[id];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
 | 
								if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
 | 
				
			||||||
				printf("%d ", sample.tid);
 | 
									printf("%d ", sample.tid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (evsel == evsel_enter) {
 | 
								handler = evsel->handler.func;
 | 
				
			||||||
				void *args = perf_evsel__rawptr(evsel, &sample, "args");
 | 
								handler(trace, evsel, &sample);
 | 
				
			||||||
 | 
					 | 
				
			||||||
				printf("%s(", sc->name);
 | 
					 | 
				
			||||||
				syscall__fprintf_args(sc, args, stdout);
 | 
					 | 
				
			||||||
			} else if (evsel == evsel_exit) {
 | 
					 | 
				
			||||||
				int ret = perf_evsel__intval(evsel, &sample, "ret");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
 | 
					 | 
				
			||||||
					char bf[256];
 | 
					 | 
				
			||||||
					const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
 | 
					 | 
				
			||||||
						   *e = audit_errno_to_name(-ret);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					printf(") = -1 %s %s", e, emsg);
 | 
					 | 
				
			||||||
				} else if (ret == 0 && sc->fmt && sc->fmt->timeout)
 | 
					 | 
				
			||||||
					printf(") = 0 Timeout");
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					printf(") = %d", ret);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				putchar('\n');
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,14 +48,14 @@ static struct cmd_struct commands[] = {
 | 
				
			||||||
	{ "version",	cmd_version,	0 },
 | 
						{ "version",	cmd_version,	0 },
 | 
				
			||||||
	{ "script",	cmd_script,	0 },
 | 
						{ "script",	cmd_script,	0 },
 | 
				
			||||||
	{ "sched",	cmd_sched,	0 },
 | 
						{ "sched",	cmd_sched,	0 },
 | 
				
			||||||
#ifndef NO_LIBELF_SUPPORT
 | 
					#ifdef LIBELF_SUPPORT
 | 
				
			||||||
	{ "probe",	cmd_probe,	0 },
 | 
						{ "probe",	cmd_probe,	0 },
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	{ "kmem",	cmd_kmem,	0 },
 | 
						{ "kmem",	cmd_kmem,	0 },
 | 
				
			||||||
	{ "lock",	cmd_lock,	0 },
 | 
						{ "lock",	cmd_lock,	0 },
 | 
				
			||||||
	{ "kvm",	cmd_kvm,	0 },
 | 
						{ "kvm",	cmd_kvm,	0 },
 | 
				
			||||||
	{ "test",	cmd_test,	0 },
 | 
						{ "test",	cmd_test,	0 },
 | 
				
			||||||
#ifndef NO_LIBAUDIT_SUPPORT
 | 
					#ifdef LIBAUDIT_SUPPORT
 | 
				
			||||||
	{ "trace",	cmd_trace,	0 },
 | 
						{ "trace",	cmd_trace,	0 },
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	{ "inject",	cmd_inject,	0 },
 | 
						{ "inject",	cmd_inject,	0 },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -569,7 +569,8 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
 | 
				
			||||||
static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp,	\
 | 
					static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp,	\
 | 
				
			||||||
					     struct hist_entry *he)	\
 | 
										     struct hist_entry *he)	\
 | 
				
			||||||
{									\
 | 
					{									\
 | 
				
			||||||
	double percent = 100.0 * he->_field / hpp->total_period;	\
 | 
						struct hists *hists = he->hists;				\
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat._field / hists->stats.total_period; \
 | 
				
			||||||
	*(double *)hpp->ptr = percent;					\
 | 
						*(double *)hpp->ptr = percent;					\
 | 
				
			||||||
	return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);	\
 | 
						return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent);	\
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -584,7 +585,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void hist_browser__init_hpp(void)
 | 
					void hist_browser__init_hpp(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	perf_hpp__init(false, false);
 | 
						perf_hpp__init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	perf_hpp__format[PERF_HPP__OVERHEAD].color =
 | 
						perf_hpp__format[PERF_HPP__OVERHEAD].color =
 | 
				
			||||||
				hist_browser__hpp_color_overhead;
 | 
									hist_browser__hpp_color_overhead;
 | 
				
			||||||
| 
						 | 
					@ -624,7 +625,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
 | 
				
			||||||
		struct perf_hpp hpp = {
 | 
							struct perf_hpp hpp = {
 | 
				
			||||||
			.buf		= s,
 | 
								.buf		= s,
 | 
				
			||||||
			.size		= sizeof(s),
 | 
								.size		= sizeof(s),
 | 
				
			||||||
			.total_period	= browser->hists->stats.total_period,
 | 
					 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ui_browser__gotorc(&browser->b, row, 0);
 | 
							ui_browser__gotorc(&browser->b, row, 0);
 | 
				
			||||||
| 
						 | 
					@ -982,7 +982,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
 | 
				
			||||||
		folded_sign = hist_entry__folded(he);
 | 
							folded_sign = hist_entry__folded(he);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists);
 | 
						hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists);
 | 
				
			||||||
	percent = (he->period * 100.0) / browser->hists->stats.total_period;
 | 
						percent = (he->stat.period * 100.0) / browser->hists->stats.total_period;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (symbol_conf.use_callchain)
 | 
						if (symbol_conf.use_callchain)
 | 
				
			||||||
		printed += fprintf(fp, "%c ", folded_sign);
 | 
							printed += fprintf(fp, "%c ", folded_sign);
 | 
				
			||||||
| 
						 | 
					@ -990,10 +990,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
 | 
				
			||||||
	printed += fprintf(fp, " %5.2f%%", percent);
 | 
						printed += fprintf(fp, " %5.2f%%", percent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (symbol_conf.show_nr_samples)
 | 
						if (symbol_conf.show_nr_samples)
 | 
				
			||||||
		printed += fprintf(fp, " %11u", he->nr_events);
 | 
							printed += fprintf(fp, " %11u", he->stat.nr_events);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (symbol_conf.show_total_period)
 | 
						if (symbol_conf.show_total_period)
 | 
				
			||||||
		printed += fprintf(fp, " %12" PRIu64, he->period);
 | 
							printed += fprintf(fp, " %12" PRIu64, he->stat.period);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printed += fprintf(fp, "%s\n", rtrim(s));
 | 
						printed += fprintf(fp, "%s\n", rtrim(s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,8 @@ static const char *perf_gtk__get_percent_color(double percent)
 | 
				
			||||||
static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp,			\
 | 
					static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp,			\
 | 
				
			||||||
					 struct hist_entry *he)			\
 | 
										 struct hist_entry *he)			\
 | 
				
			||||||
{										\
 | 
					{										\
 | 
				
			||||||
	double percent = 100.0 * he->_field / hpp->total_period;		\
 | 
						struct hists *hists = he->hists;					\
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat._field / hists->stats.total_period;	\
 | 
				
			||||||
	const char *markup;							\
 | 
						const char *markup;							\
 | 
				
			||||||
	int ret = 0;								\
 | 
						int ret = 0;								\
 | 
				
			||||||
										\
 | 
															\
 | 
				
			||||||
| 
						 | 
					@ -73,7 +74,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void perf_gtk__init_hpp(void)
 | 
					void perf_gtk__init_hpp(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	perf_hpp__init(false, false);
 | 
						perf_hpp__init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	perf_hpp__format[PERF_HPP__OVERHEAD].color =
 | 
						perf_hpp__format[PERF_HPP__OVERHEAD].color =
 | 
				
			||||||
				perf_gtk__hpp_color_overhead;
 | 
									perf_gtk__hpp_color_overhead;
 | 
				
			||||||
| 
						 | 
					@ -102,7 +103,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
 | 
				
			||||||
	struct perf_hpp hpp = {
 | 
						struct perf_hpp hpp = {
 | 
				
			||||||
		.buf		= s,
 | 
							.buf		= s,
 | 
				
			||||||
		.size		= sizeof(s),
 | 
							.size		= sizeof(s),
 | 
				
			||||||
		.total_period	= hists->stats.total_period,
 | 
					 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nr_cols = 0;
 | 
						nr_cols = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,7 +116,7 @@ struct perf_error_ops perf_gtk_eops = {
 | 
				
			||||||
 * FIXME: Functions below should be implemented properly.
 | 
					 * FIXME: Functions below should be implemented properly.
 | 
				
			||||||
 *        For now, just add stubs for NO_NEWT=1 build.
 | 
					 *        For now, just add stubs for NO_NEWT=1 build.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#ifdef NO_NEWT_SUPPORT
 | 
					#ifndef NEWT_SUPPORT
 | 
				
			||||||
void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused,
 | 
					void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused,
 | 
				
			||||||
			 const char *title __maybe_unused)
 | 
								 const char *title __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,25 +23,25 @@ void ui_helpline__puts(const char *msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern char ui_helpline__current[512];
 | 
					extern char ui_helpline__current[512];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef NO_NEWT_SUPPORT
 | 
					#ifdef NEWT_SUPPORT
 | 
				
			||||||
 | 
					extern char ui_helpline__last_msg[];
 | 
				
			||||||
 | 
					int ui_helpline__show_help(const char *format, va_list ap);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
static inline int ui_helpline__show_help(const char *format __maybe_unused,
 | 
					static inline int ui_helpline__show_help(const char *format __maybe_unused,
 | 
				
			||||||
					 va_list ap __maybe_unused)
 | 
										 va_list ap __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					#endif /* NEWT_SUPPORT */
 | 
				
			||||||
extern char ui_helpline__last_msg[];
 | 
					 | 
				
			||||||
int ui_helpline__show_help(const char *format, va_list ap);
 | 
					 | 
				
			||||||
#endif /* NO_NEWT_SUPPORT */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef NO_GTK2_SUPPORT
 | 
					#ifdef GTK2_SUPPORT
 | 
				
			||||||
 | 
					int perf_gtk__show_helpline(const char *format, va_list ap);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
 | 
					static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
 | 
				
			||||||
					  va_list ap __maybe_unused)
 | 
										  va_list ap __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					#endif /* GTK2_SUPPORT */
 | 
				
			||||||
int perf_gtk__show_helpline(const char *format, va_list ap);
 | 
					 | 
				
			||||||
#endif /* NO_GTK2_SUPPORT */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _PERF_UI_HELPLINE_H_ */
 | 
					#endif /* _PERF_UI_HELPLINE_H_ */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,7 @@
 | 
				
			||||||
/* hist period print (hpp) functions */
 | 
					/* hist period print (hpp) functions */
 | 
				
			||||||
static int hpp__header_overhead(struct perf_hpp *hpp)
 | 
					static int hpp__header_overhead(struct perf_hpp *hpp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *fmt = hpp->ptr ? "Baseline" : "Overhead";
 | 
						return scnprintf(hpp->buf, hpp->size, "Overhead");
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return scnprintf(hpp->buf, hpp->size, fmt);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
 | 
					static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
 | 
				
			||||||
| 
						 | 
					@ -20,38 +18,18 @@ static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
 | 
					static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	double percent = 100.0 * he->period / hpp->total_period;
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat.period / hists->stats.total_period;
 | 
				
			||||||
	if (hpp->ptr) {
 | 
					 | 
				
			||||||
		struct hists *old_hists = hpp->ptr;
 | 
					 | 
				
			||||||
		u64 total_period = old_hists->stats.total_period;
 | 
					 | 
				
			||||||
		u64 base_period = he->pair ? he->pair->period : 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (total_period)
 | 
					 | 
				
			||||||
			percent = 100.0 * base_period / total_period;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			percent = 0.0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
 | 
						return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
 | 
					static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	double percent = 100.0 * he->period / hpp->total_period;
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat.period / hists->stats.total_period;
 | 
				
			||||||
	const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
 | 
						const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (hpp->ptr) {
 | 
					 | 
				
			||||||
		struct hists *old_hists = hpp->ptr;
 | 
					 | 
				
			||||||
		u64 total_period = old_hists->stats.total_period;
 | 
					 | 
				
			||||||
		u64 base_period = he->pair ? he->pair->period : 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (total_period)
 | 
					 | 
				
			||||||
			percent = 100.0 * base_period / total_period;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			percent = 0.0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
						return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,13 +47,16 @@ static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
 | 
					static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	double percent = 100.0 * he->period_sys / hpp->total_period;
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
 | 
						return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
 | 
					static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	double percent = 100.0 * he->period_sys / hpp->total_period;
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
 | 
				
			||||||
	const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
 | 
						const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
						return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
				
			||||||
| 
						 | 
					@ -95,13 +76,16 @@ static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
 | 
					static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	double percent = 100.0 * he->period_us / hpp->total_period;
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
 | 
						return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
 | 
					static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	double percent = 100.0 * he->period_us / hpp->total_period;
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
 | 
				
			||||||
	const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
 | 
						const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
						return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
				
			||||||
| 
						 | 
					@ -120,14 +104,17 @@ static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
 | 
				
			||||||
static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
 | 
					static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
 | 
				
			||||||
					 struct hist_entry *he)
 | 
										 struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	double percent = 100.0 * he->period_guest_sys / hpp->total_period;
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
 | 
						return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
 | 
					static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
 | 
				
			||||||
					 struct hist_entry *he)
 | 
										 struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	double percent = 100.0 * he->period_guest_sys / hpp->total_period;
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
 | 
				
			||||||
	const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
 | 
						const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
						return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
				
			||||||
| 
						 | 
					@ -146,14 +133,58 @@ static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
 | 
				
			||||||
static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
 | 
					static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
 | 
				
			||||||
					struct hist_entry *he)
 | 
										struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	double percent = 100.0 * he->period_guest_us / hpp->total_period;
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
 | 
						return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
 | 
					static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
 | 
				
			||||||
					struct hist_entry *he)
 | 
										struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	double percent = 100.0 * he->period_guest_us / hpp->total_period;
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
 | 
						double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
 | 
				
			||||||
 | 
						const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int hpp__header_baseline(struct perf_hpp *hpp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return scnprintf(hpp->buf, hpp->size, "Baseline");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static double baseline_percent(struct hist_entry *he)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hist_entry *pair = he->pair;
 | 
				
			||||||
 | 
						struct hists *pair_hists = pair ? pair->hists : NULL;
 | 
				
			||||||
 | 
						double percent = 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (pair) {
 | 
				
			||||||
 | 
							u64 total_period = pair_hists->stats.total_period;
 | 
				
			||||||
 | 
							u64 base_period  = pair->stat.period;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							percent = 100.0 * base_period / total_period;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return percent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						double percent = baseline_percent(he);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						double percent = baseline_percent(he);
 | 
				
			||||||
	const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
 | 
						const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
						return scnprintf(hpp->buf, hpp->size, fmt, percent);
 | 
				
			||||||
| 
						 | 
					@ -175,7 +206,7 @@ static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
 | 
						const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events);
 | 
						return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__header_period(struct perf_hpp *hpp)
 | 
					static int hpp__header_period(struct perf_hpp *hpp)
 | 
				
			||||||
| 
						 | 
					@ -194,7 +225,7 @@ static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
 | 
						const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return scnprintf(hpp->buf, hpp->size, fmt, he->period);
 | 
						return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__header_delta(struct perf_hpp *hpp)
 | 
					static int hpp__header_delta(struct perf_hpp *hpp)
 | 
				
			||||||
| 
						 | 
					@ -211,20 +242,22 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
 | 
					static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hists *pair_hists = hpp->ptr;
 | 
						struct hist_entry *pair = he->pair;
 | 
				
			||||||
 | 
						struct hists *pair_hists = pair ? pair->hists : NULL;
 | 
				
			||||||
 | 
						struct hists *hists = he->hists;
 | 
				
			||||||
	u64 old_total, new_total;
 | 
						u64 old_total, new_total;
 | 
				
			||||||
	double old_percent = 0, new_percent = 0;
 | 
						double old_percent = 0, new_percent = 0;
 | 
				
			||||||
	double diff;
 | 
						double diff;
 | 
				
			||||||
	const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
 | 
						const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
 | 
				
			||||||
	char buf[32] = " ";
 | 
						char buf[32] = " ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	old_total = pair_hists->stats.total_period;
 | 
						old_total = pair_hists ? pair_hists->stats.total_period : 0;
 | 
				
			||||||
	if (old_total > 0 && he->pair)
 | 
						if (old_total > 0 && pair)
 | 
				
			||||||
		old_percent = 100.0 * he->pair->period / old_total;
 | 
							old_percent = 100.0 * pair->stat.period / old_total;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	new_total = hpp->total_period;
 | 
						new_total = hists->stats.total_period;
 | 
				
			||||||
	if (new_total > 0)
 | 
						if (new_total > 0)
 | 
				
			||||||
		new_percent = 100.0 * he->period / new_total;
 | 
							new_percent = 100.0 * he->stat.period / new_total;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diff = new_percent - old_percent;
 | 
						diff = new_percent - old_percent;
 | 
				
			||||||
	if (fabs(diff) >= 0.01)
 | 
						if (fabs(diff) >= 0.01)
 | 
				
			||||||
| 
						 | 
					@ -244,13 +277,15 @@ static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hpp__entry_displ(struct perf_hpp *hpp,
 | 
					static int hpp__entry_displ(struct perf_hpp *hpp,
 | 
				
			||||||
			    struct hist_entry *he __maybe_unused)
 | 
								    struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct hist_entry *pair = he->pair;
 | 
				
			||||||
 | 
						long displacement = pair ? pair->position - he->position : 0;
 | 
				
			||||||
	const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
 | 
						const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
 | 
				
			||||||
	char buf[32] = " ";
 | 
						char buf[32] = " ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (hpp->displacement)
 | 
						if (displacement)
 | 
				
			||||||
		scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement);
 | 
							scnprintf(buf, sizeof(buf), "%+4ld", displacement);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return scnprintf(hpp->buf, hpp->size, fmt, buf);
 | 
						return scnprintf(hpp->buf, hpp->size, fmt, buf);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -267,6 +302,7 @@ static int hpp__entry_displ(struct perf_hpp *hpp,
 | 
				
			||||||
	.entry	= hpp__entry_ ## _name
 | 
						.entry	= hpp__entry_ ## _name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct perf_hpp_fmt perf_hpp__format[] = {
 | 
					struct perf_hpp_fmt perf_hpp__format[] = {
 | 
				
			||||||
 | 
						{ .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
 | 
				
			||||||
	{ .cond = true,  HPP__COLOR_PRINT_FNS(overhead) },
 | 
						{ .cond = true,  HPP__COLOR_PRINT_FNS(overhead) },
 | 
				
			||||||
	{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
 | 
						{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
 | 
				
			||||||
	{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
 | 
						{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
 | 
				
			||||||
| 
						 | 
					@ -281,7 +317,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
 | 
				
			||||||
#undef HPP__COLOR_PRINT_FNS
 | 
					#undef HPP__COLOR_PRINT_FNS
 | 
				
			||||||
#undef HPP__PRINT_FNS
 | 
					#undef HPP__PRINT_FNS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void perf_hpp__init(bool need_pair, bool show_displacement)
 | 
					void perf_hpp__init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (symbol_conf.show_cpu_utilization) {
 | 
						if (symbol_conf.show_cpu_utilization) {
 | 
				
			||||||
		perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
 | 
							perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
 | 
				
			||||||
| 
						 | 
					@ -298,13 +334,12 @@ void perf_hpp__init(bool need_pair, bool show_displacement)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (symbol_conf.show_total_period)
 | 
						if (symbol_conf.show_total_period)
 | 
				
			||||||
		perf_hpp__format[PERF_HPP__PERIOD].cond = true;
 | 
							perf_hpp__format[PERF_HPP__PERIOD].cond = true;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (need_pair) {
 | 
					 | 
				
			||||||
		perf_hpp__format[PERF_HPP__DELTA].cond = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (show_displacement)
 | 
					 | 
				
			||||||
			perf_hpp__format[PERF_HPP__DISPL].cond = true;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void perf_hpp__column_enable(unsigned col, bool enable)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						BUG_ON(col >= PERF_HPP__MAX_INDEX);
 | 
				
			||||||
 | 
						perf_hpp__format[col].cond = enable;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void advance_hpp(struct perf_hpp *hpp, int inc)
 | 
					static inline void advance_hpp(struct perf_hpp *hpp, int inc)
 | 
				
			||||||
| 
						 | 
					@ -319,6 +354,7 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
 | 
				
			||||||
	const char *sep = symbol_conf.field_sep;
 | 
						const char *sep = symbol_conf.field_sep;
 | 
				
			||||||
	char *start = hpp->buf;
 | 
						char *start = hpp->buf;
 | 
				
			||||||
	int i, ret;
 | 
						int i, ret;
 | 
				
			||||||
 | 
						bool first = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (symbol_conf.exclude_other && !he->parent)
 | 
						if (symbol_conf.exclude_other && !he->parent)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -327,9 +363,10 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
 | 
				
			||||||
		if (!perf_hpp__format[i].cond)
 | 
							if (!perf_hpp__format[i].cond)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!sep || i > 0) {
 | 
							if (!sep || !first) {
 | 
				
			||||||
			ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: "  ");
 | 
								ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: "  ");
 | 
				
			||||||
			advance_hpp(hpp, ret);
 | 
								advance_hpp(hpp, ret);
 | 
				
			||||||
 | 
								first = false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (color && perf_hpp__format[i].color)
 | 
							if (color && perf_hpp__format[i].color)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ void setup_browser(bool fallback_to_pager)
 | 
				
			||||||
		if (fallback_to_pager)
 | 
							if (fallback_to_pager)
 | 
				
			||||||
			setup_pager();
 | 
								setup_pager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		perf_hpp__init(false, false);
 | 
							perf_hpp__init();
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -271,7 +271,7 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	switch (callchain_param.mode) {
 | 
						switch (callchain_param.mode) {
 | 
				
			||||||
	case CHAIN_GRAPH_REL:
 | 
						case CHAIN_GRAPH_REL:
 | 
				
			||||||
		return callchain__fprintf_graph(fp, &he->sorted_chain, he->period,
 | 
							return callchain__fprintf_graph(fp, &he->sorted_chain, he->stat.period,
 | 
				
			||||||
						left_margin);
 | 
											left_margin);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case CHAIN_GRAPH_ABS:
 | 
						case CHAIN_GRAPH_ABS:
 | 
				
			||||||
| 
						 | 
					@ -292,9 +292,10 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
 | 
					static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
 | 
				
			||||||
					    struct hists *hists,
 | 
										    struct hists *hists,
 | 
				
			||||||
					    u64 total_period, FILE *fp)
 | 
										    FILE *fp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int left_margin = 0;
 | 
						int left_margin = 0;
 | 
				
			||||||
 | 
						u64 total_period = hists->stats.total_period;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sort__first_dimension == SORT_COMM) {
 | 
						if (sort__first_dimension == SORT_COMM) {
 | 
				
			||||||
		struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
 | 
							struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
 | 
				
			||||||
| 
						 | 
					@ -307,17 +308,13 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hist_entry__fprintf(struct hist_entry *he, size_t size,
 | 
					static int hist_entry__fprintf(struct hist_entry *he, size_t size,
 | 
				
			||||||
			       struct hists *hists, struct hists *pair_hists,
 | 
								       struct hists *hists, FILE *fp)
 | 
				
			||||||
			       long displacement, u64 total_period, FILE *fp)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char bf[512];
 | 
						char bf[512];
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	struct perf_hpp hpp = {
 | 
						struct perf_hpp hpp = {
 | 
				
			||||||
		.buf		= bf,
 | 
							.buf		= bf,
 | 
				
			||||||
		.size		= size,
 | 
							.size		= size,
 | 
				
			||||||
		.total_period	= total_period,
 | 
					 | 
				
			||||||
		.displacement	= displacement,
 | 
					 | 
				
			||||||
		.ptr		= pair_hists,
 | 
					 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	bool color = !symbol_conf.field_sep;
 | 
						bool color = !symbol_conf.field_sep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -330,22 +327,17 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
 | 
				
			||||||
	ret = fprintf(fp, "%s\n", bf);
 | 
						ret = fprintf(fp, "%s\n", bf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (symbol_conf.use_callchain)
 | 
						if (symbol_conf.use_callchain)
 | 
				
			||||||
		ret += hist_entry__callchain_fprintf(he, hists,
 | 
							ret += hist_entry__callchain_fprintf(he, hists, fp);
 | 
				
			||||||
						     total_period, fp);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t hists__fprintf(struct hists *hists, struct hists *pair,
 | 
					size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 | 
				
			||||||
		      bool show_displacement, bool show_header, int max_rows,
 | 
					 | 
				
			||||||
		      int max_cols, FILE *fp)
 | 
							      int max_cols, FILE *fp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sort_entry *se;
 | 
						struct sort_entry *se;
 | 
				
			||||||
	struct rb_node *nd;
 | 
						struct rb_node *nd;
 | 
				
			||||||
	size_t ret = 0;
 | 
						size_t ret = 0;
 | 
				
			||||||
	u64 total_period;
 | 
					 | 
				
			||||||
	unsigned long position = 1;
 | 
					 | 
				
			||||||
	long displacement = 0;
 | 
					 | 
				
			||||||
	unsigned int width;
 | 
						unsigned int width;
 | 
				
			||||||
	const char *sep = symbol_conf.field_sep;
 | 
						const char *sep = symbol_conf.field_sep;
 | 
				
			||||||
	const char *col_width = symbol_conf.col_width_list_str;
 | 
						const char *col_width = symbol_conf.col_width_list_str;
 | 
				
			||||||
| 
						 | 
					@ -354,8 +346,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
 | 
				
			||||||
	struct perf_hpp dummy_hpp = {
 | 
						struct perf_hpp dummy_hpp = {
 | 
				
			||||||
		.buf	= bf,
 | 
							.buf	= bf,
 | 
				
			||||||
		.size	= sizeof(bf),
 | 
							.size	= sizeof(bf),
 | 
				
			||||||
		.ptr	= pair,
 | 
					 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						bool first = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_rem_hits();
 | 
						init_rem_hits();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -367,8 +359,10 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
 | 
				
			||||||
		if (!perf_hpp__format[idx].cond)
 | 
							if (!perf_hpp__format[idx].cond)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (idx)
 | 
							if (!first)
 | 
				
			||||||
			fprintf(fp, "%s", sep ?: "  ");
 | 
								fprintf(fp, "%s", sep ?: "  ");
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								first = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		perf_hpp__format[idx].header(&dummy_hpp);
 | 
							perf_hpp__format[idx].header(&dummy_hpp);
 | 
				
			||||||
		fprintf(fp, "%s", bf);
 | 
							fprintf(fp, "%s", bf);
 | 
				
			||||||
| 
						 | 
					@ -403,6 +397,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
 | 
				
			||||||
	if (sep)
 | 
						if (sep)
 | 
				
			||||||
		goto print_entries;
 | 
							goto print_entries;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						first = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fprintf(fp, "# ");
 | 
						fprintf(fp, "# ");
 | 
				
			||||||
	for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
 | 
						for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
 | 
				
			||||||
		unsigned int i;
 | 
							unsigned int i;
 | 
				
			||||||
| 
						 | 
					@ -410,8 +406,10 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
 | 
				
			||||||
		if (!perf_hpp__format[idx].cond)
 | 
							if (!perf_hpp__format[idx].cond)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (idx)
 | 
							if (!first)
 | 
				
			||||||
			fprintf(fp, "%s", sep ?: "  ");
 | 
								fprintf(fp, "%s", sep ?: "  ");
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								first = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		width = perf_hpp__format[idx].width(&dummy_hpp);
 | 
							width = perf_hpp__format[idx].width(&dummy_hpp);
 | 
				
			||||||
		for (i = 0; i < width; i++)
 | 
							for (i = 0; i < width; i++)
 | 
				
			||||||
| 
						 | 
					@ -441,24 +439,13 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
print_entries:
 | 
					print_entries:
 | 
				
			||||||
	total_period = hists->stats.total_period;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
 | 
						for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
 | 
				
			||||||
		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
 | 
							struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (h->filtered)
 | 
							if (h->filtered)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (show_displacement) {
 | 
							ret += hist_entry__fprintf(h, max_cols, hists, fp);
 | 
				
			||||||
			if (h->pair != NULL)
 | 
					 | 
				
			||||||
				displacement = ((long)h->pair->position -
 | 
					 | 
				
			||||||
					        (long)position);
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				displacement = 0;
 | 
					 | 
				
			||||||
			++position;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		ret += hist_entry__fprintf(h, max_cols, hists, pair, displacement,
 | 
					 | 
				
			||||||
					   total_period, fp);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (max_rows && ++nr_rows >= max_rows)
 | 
							if (max_rows && ++nr_rows >= max_rows)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -138,7 +138,10 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
 | 
				
			||||||
			 bool print_lines, bool full_paths, int min_pcnt,
 | 
								 bool print_lines, bool full_paths, int min_pcnt,
 | 
				
			||||||
			 int max_lines);
 | 
								 int max_lines);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef NO_NEWT_SUPPORT
 | 
					#ifdef NEWT_SUPPORT
 | 
				
			||||||
 | 
					int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
 | 
				
			||||||
 | 
								 void(*timer)(void *arg), void *arg, int delay_secs);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
 | 
					static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
 | 
				
			||||||
				       struct map *map __maybe_unused,
 | 
									       struct map *map __maybe_unused,
 | 
				
			||||||
				       int evidx __maybe_unused,
 | 
									       int evidx __maybe_unused,
 | 
				
			||||||
| 
						 | 
					@ -148,9 +151,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
 | 
					 | 
				
			||||||
			 void(*timer)(void *arg), void *arg, int delay_secs);
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const char	*disassembler_style;
 | 
					extern const char	*disassembler_style;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,39 +33,41 @@ extern int pager_use_color;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int use_browser;
 | 
					extern int use_browser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
 | 
					#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
 | 
				
			||||||
 | 
					void setup_browser(bool fallback_to_pager);
 | 
				
			||||||
 | 
					void exit_browser(bool wait_for_ok);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef NEWT_SUPPORT
 | 
				
			||||||
 | 
					int ui__init(void);
 | 
				
			||||||
 | 
					void ui__exit(bool wait_for_ok);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static inline int ui__init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef GTK2_SUPPORT
 | 
				
			||||||
 | 
					int perf_gtk__init(void);
 | 
				
			||||||
 | 
					void perf_gtk__exit(bool wait_for_ok);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static inline int perf_gtk__init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else /* NEWT_SUPPORT || GTK2_SUPPORT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void setup_browser(bool fallback_to_pager)
 | 
					static inline void setup_browser(bool fallback_to_pager)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (fallback_to_pager)
 | 
						if (fallback_to_pager)
 | 
				
			||||||
		setup_pager();
 | 
							setup_pager();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
 | 
					static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
 | 
				
			||||||
#else
 | 
					#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
 | 
				
			||||||
void setup_browser(bool fallback_to_pager);
 | 
					 | 
				
			||||||
void exit_browser(bool wait_for_ok);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef NO_NEWT_SUPPORT
 | 
					 | 
				
			||||||
static inline int ui__init(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return -1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
int ui__init(void);
 | 
					 | 
				
			||||||
void ui__exit(bool wait_for_ok);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef NO_GTK2_SUPPORT
 | 
					 | 
				
			||||||
static inline int perf_gtk__init(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return -1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
int perf_gtk__init(void);
 | 
					 | 
				
			||||||
void perf_gtk__exit(bool wait_for_ok);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *alias_lookup(const char *alias);
 | 
					char *alias_lookup(const char *alias);
 | 
				
			||||||
int split_cmdline(char *cmdline, const char ***argv);
 | 
					int split_cmdline(char *cmdline, const char ***argv);
 | 
				
			||||||
| 
						 | 
					@ -105,7 +107,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
 | 
				
			||||||
extern char *perf_pathdup(const char *fmt, ...)
 | 
					extern char *perf_pathdup(const char *fmt, ...)
 | 
				
			||||||
	__attribute__((format (printf, 1, 2)));
 | 
						__attribute__((format (printf, 1, 2)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef NO_STRLCPY
 | 
					#ifndef HAVE_STRLCPY
 | 
				
			||||||
extern size_t strlcpy(char *dest, const char *src, size_t size);
 | 
					extern size_t strlcpy(char *dest, const char *src, size_t size);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ int dump_printf(const char *fmt, ...)
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
 | 
					#if !defined(NEWT_SUPPORT) && !defined(GTK2_SUPPORT)
 | 
				
			||||||
int ui__warning(const char *format, ...)
 | 
					int ui__warning(const char *format, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	va_list args;
 | 
						va_list args;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,14 @@ void trace_event(union perf_event *event);
 | 
				
			||||||
struct ui_progress;
 | 
					struct ui_progress;
 | 
				
			||||||
struct perf_error_ops;
 | 
					struct perf_error_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
 | 
					#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../ui/progress.h"
 | 
				
			||||||
 | 
					int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
 | 
				
			||||||
 | 
					#include "../ui/util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void ui_progress__update(u64 curr __maybe_unused,
 | 
					static inline void ui_progress__update(u64 curr __maybe_unused,
 | 
				
			||||||
				       u64 total __maybe_unused,
 | 
									       u64 total __maybe_unused,
 | 
				
			||||||
				       const char *title __maybe_unused) {}
 | 
									       const char *title __maybe_unused) {}
 | 
				
			||||||
| 
						 | 
					@ -34,13 +41,7 @@ perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
 | 
					#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "../ui/progress.h"
 | 
					 | 
				
			||||||
int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
 | 
					 | 
				
			||||||
#include "../ui/util.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
 | 
					int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
 | 
				
			||||||
int ui__error_paranoid(void);
 | 
					int ui__error_paranoid(void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -154,7 +154,7 @@ error:
 | 
				
			||||||
	return -ENOMEM;
 | 
						return -ENOMEM;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int perf_evlist__add_attrs(struct perf_evlist *evlist,
 | 
					static int perf_evlist__add_attrs(struct perf_evlist *evlist,
 | 
				
			||||||
				  struct perf_event_attr *attrs, size_t nr_attrs)
 | 
									  struct perf_event_attr *attrs, size_t nr_attrs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct perf_evsel *evsel, *n;
 | 
						struct perf_evsel *evsel, *n;
 | 
				
			||||||
| 
						 | 
					@ -189,60 +189,6 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
 | 
				
			||||||
	return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
 | 
						return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int trace_event__id(const char *evname)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char *filename, *colon;
 | 
					 | 
				
			||||||
	int err = -1, fd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	colon = strrchr(filename, ':');
 | 
					 | 
				
			||||||
	if (colon != NULL)
 | 
					 | 
				
			||||||
		*colon = '/';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fd = open(filename, O_RDONLY);
 | 
					 | 
				
			||||||
	if (fd >= 0) {
 | 
					 | 
				
			||||||
		char id[16];
 | 
					 | 
				
			||||||
		if (read(fd, id, sizeof(id)) > 0)
 | 
					 | 
				
			||||||
			err = atoi(id);
 | 
					 | 
				
			||||||
		close(fd);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	free(filename);
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
 | 
					 | 
				
			||||||
				 const char *tracepoints[],
 | 
					 | 
				
			||||||
				 size_t nr_tracepoints)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
	size_t i;
 | 
					 | 
				
			||||||
	struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (attrs == NULL)
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (i = 0; i < nr_tracepoints; i++) {
 | 
					 | 
				
			||||||
		err = trace_event__id(tracepoints[i]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (err < 0)
 | 
					 | 
				
			||||||
			goto out_free_attrs;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		attrs[i].type	       = PERF_TYPE_TRACEPOINT;
 | 
					 | 
				
			||||||
		attrs[i].config	       = err;
 | 
					 | 
				
			||||||
	        attrs[i].sample_type   = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
 | 
					 | 
				
			||||||
					  PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
 | 
					 | 
				
			||||||
		attrs[i].sample_period = 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
 | 
					 | 
				
			||||||
out_free_attrs:
 | 
					 | 
				
			||||||
	free(attrs);
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct perf_evsel *
 | 
					struct perf_evsel *
 | 
				
			||||||
perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
 | 
					perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -257,32 +203,18 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
 | 
					int perf_evlist__add_newtp(struct perf_evlist *evlist,
 | 
				
			||||||
					  const struct perf_evsel_str_handler *assocs,
 | 
								   const char *sys, const char *name, void *handler)
 | 
				
			||||||
					  size_t nr_assocs)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct perf_evsel *evsel;
 | 
						struct perf_evsel *evsel;
 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
	size_t i;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < nr_assocs; i++) {
 | 
						evsel = perf_evsel__newtp(sys, name, evlist->nr_entries);
 | 
				
			||||||
		err = trace_event__id(assocs[i].name);
 | 
					 | 
				
			||||||
		if (err < 0)
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
 | 
					 | 
				
			||||||
	if (evsel == NULL)
 | 
						if (evsel == NULL)
 | 
				
			||||||
			continue;
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err = -EEXIST;
 | 
						evsel->handler.func = handler;
 | 
				
			||||||
		if (evsel->handler.func != NULL)
 | 
						perf_evlist__add(evlist, evsel);
 | 
				
			||||||
			goto out;
 | 
						return 0;
 | 
				
			||||||
		evsel->handler.func = assocs[i].handler;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = 0;
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void perf_evlist__disable(struct perf_evlist *evlist)
 | 
					void perf_evlist__disable(struct perf_evlist *evlist)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,26 +51,14 @@ void perf_evlist__delete(struct perf_evlist *evlist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
 | 
					void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
 | 
				
			||||||
int perf_evlist__add_default(struct perf_evlist *evlist);
 | 
					int perf_evlist__add_default(struct perf_evlist *evlist);
 | 
				
			||||||
int perf_evlist__add_attrs(struct perf_evlist *evlist,
 | 
					 | 
				
			||||||
			   struct perf_event_attr *attrs, size_t nr_attrs);
 | 
					 | 
				
			||||||
int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
 | 
					int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
 | 
				
			||||||
				     struct perf_event_attr *attrs, size_t nr_attrs);
 | 
									     struct perf_event_attr *attrs, size_t nr_attrs);
 | 
				
			||||||
int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
 | 
					 | 
				
			||||||
				 const char *tracepoints[], size_t nr_tracepoints);
 | 
					 | 
				
			||||||
int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
 | 
					 | 
				
			||||||
					  const struct perf_evsel_str_handler *assocs,
 | 
					 | 
				
			||||||
					  size_t nr_assocs);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define perf_evlist__add_attrs_array(evlist, array) \
 | 
					 | 
				
			||||||
	perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
 | 
					 | 
				
			||||||
#define perf_evlist__add_default_attrs(evlist, array) \
 | 
					#define perf_evlist__add_default_attrs(evlist, array) \
 | 
				
			||||||
	__perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
 | 
						__perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define perf_evlist__add_tracepoints_array(evlist, array) \
 | 
					int perf_evlist__add_newtp(struct perf_evlist *evlist,
 | 
				
			||||||
	perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
 | 
								   const char *sys, const char *name, void *handler);
 | 
				
			||||||
 | 
					 | 
				
			||||||
#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
 | 
					 | 
				
			||||||
	perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
 | 
					int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ do
 | 
				
			||||||
     }' "Documentation/perf-$cmd.txt"
 | 
					     }' "Documentation/perf-$cmd.txt"
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
echo "#ifndef NO_LIBELF_SUPPORT"
 | 
					echo "#ifdef LIBELF_SUPPORT"
 | 
				
			||||||
sed -n -e 's/^perf-\([^ 	]*\)[ 	].* full.*/\1/p' command-list.txt |
 | 
					sed -n -e 's/^perf-\([^ 	]*\)[ 	].* full.*/\1/p' command-list.txt |
 | 
				
			||||||
sort |
 | 
					sort |
 | 
				
			||||||
while read cmd
 | 
					while read cmd
 | 
				
			||||||
| 
						 | 
					@ -35,5 +35,5 @@ do
 | 
				
			||||||
	    p
 | 
						    p
 | 
				
			||||||
     }' "Documentation/perf-$cmd.txt"
 | 
					     }' "Documentation/perf-$cmd.txt"
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
echo "#endif /* NO_LIBELF_SUPPORT */"
 | 
					echo "#endif /* LIBELF_SUPPORT */"
 | 
				
			||||||
echo "};"
 | 
					echo "};"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,31 +135,47 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	switch (cpumode) {
 | 
						switch (cpumode) {
 | 
				
			||||||
	case PERF_RECORD_MISC_KERNEL:
 | 
						case PERF_RECORD_MISC_KERNEL:
 | 
				
			||||||
		he->period_sys += period;
 | 
							he->stat.period_sys += period;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case PERF_RECORD_MISC_USER:
 | 
						case PERF_RECORD_MISC_USER:
 | 
				
			||||||
		he->period_us += period;
 | 
							he->stat.period_us += period;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case PERF_RECORD_MISC_GUEST_KERNEL:
 | 
						case PERF_RECORD_MISC_GUEST_KERNEL:
 | 
				
			||||||
		he->period_guest_sys += period;
 | 
							he->stat.period_guest_sys += period;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case PERF_RECORD_MISC_GUEST_USER:
 | 
						case PERF_RECORD_MISC_GUEST_USER:
 | 
				
			||||||
		he->period_guest_us += period;
 | 
							he->stat.period_guest_us += period;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void he_stat__add_period(struct he_stat *he_stat, u64 period)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						he_stat->period		+= period;
 | 
				
			||||||
 | 
						he_stat->nr_events	+= 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						dest->period		+= src->period;
 | 
				
			||||||
 | 
						dest->period_sys	+= src->period_sys;
 | 
				
			||||||
 | 
						dest->period_us		+= src->period_us;
 | 
				
			||||||
 | 
						dest->period_guest_sys	+= src->period_guest_sys;
 | 
				
			||||||
 | 
						dest->period_guest_us	+= src->period_guest_us;
 | 
				
			||||||
 | 
						dest->nr_events		+= src->nr_events;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void hist_entry__decay(struct hist_entry *he)
 | 
					static void hist_entry__decay(struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	he->period = (he->period * 7) / 8;
 | 
						he->stat.period = (he->stat.period * 7) / 8;
 | 
				
			||||||
	he->nr_events = (he->nr_events * 7) / 8;
 | 
						he->stat.nr_events = (he->stat.nr_events * 7) / 8;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
 | 
					static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u64 prev_period = he->period;
 | 
						u64 prev_period = he->stat.period;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (prev_period == 0)
 | 
						if (prev_period == 0)
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
| 
						 | 
					@ -167,9 +183,9 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
 | 
				
			||||||
	hist_entry__decay(he);
 | 
						hist_entry__decay(he);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!he->filtered)
 | 
						if (!he->filtered)
 | 
				
			||||||
		hists->stats.total_period -= prev_period - he->period;
 | 
							hists->stats.total_period -= prev_period - he->stat.period;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return he->period == 0;
 | 
						return he->stat.period == 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void __hists__decay_entries(struct hists *hists, bool zap_user,
 | 
					static void __hists__decay_entries(struct hists *hists, bool zap_user,
 | 
				
			||||||
| 
						 | 
					@ -223,7 +239,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (he != NULL) {
 | 
						if (he != NULL) {
 | 
				
			||||||
		*he = *template;
 | 
							*he = *template;
 | 
				
			||||||
		he->nr_events = 1;
 | 
					
 | 
				
			||||||
		if (he->ms.map)
 | 
							if (he->ms.map)
 | 
				
			||||||
			he->ms.map->referenced = true;
 | 
								he->ms.map->referenced = true;
 | 
				
			||||||
		if (symbol_conf.use_callchain)
 | 
							if (symbol_conf.use_callchain)
 | 
				
			||||||
| 
						 | 
					@ -238,7 +254,7 @@ static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
 | 
				
			||||||
	if (!h->filtered) {
 | 
						if (!h->filtered) {
 | 
				
			||||||
		hists__calc_col_len(hists, h);
 | 
							hists__calc_col_len(hists, h);
 | 
				
			||||||
		++hists->nr_entries;
 | 
							++hists->nr_entries;
 | 
				
			||||||
		hists->stats.total_period += h->period;
 | 
							hists->stats.total_period += h->stat.period;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -270,8 +286,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
 | 
				
			||||||
		cmp = hist_entry__cmp(entry, he);
 | 
							cmp = hist_entry__cmp(entry, he);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!cmp) {
 | 
							if (!cmp) {
 | 
				
			||||||
			he->period += period;
 | 
								he_stat__add_period(&he->stat, period);
 | 
				
			||||||
			++he->nr_events;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* If the map of an existing hist_entry has
 | 
								/* If the map of an existing hist_entry has
 | 
				
			||||||
			 * become out-of-date due to an exec() or
 | 
								 * become out-of-date due to an exec() or
 | 
				
			||||||
| 
						 | 
					@ -321,10 +336,14 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
 | 
				
			||||||
		.cpu	= al->cpu,
 | 
							.cpu	= al->cpu,
 | 
				
			||||||
		.ip	= bi->to.addr,
 | 
							.ip	= bi->to.addr,
 | 
				
			||||||
		.level	= al->level,
 | 
							.level	= al->level,
 | 
				
			||||||
 | 
							.stat = {
 | 
				
			||||||
			.period	= period,
 | 
								.period	= period,
 | 
				
			||||||
 | 
								.nr_events = 1,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		.parent = sym_parent,
 | 
							.parent = sym_parent,
 | 
				
			||||||
		.filtered = symbol__parent_filter(sym_parent),
 | 
							.filtered = symbol__parent_filter(sym_parent),
 | 
				
			||||||
		.branch_info = bi,
 | 
							.branch_info = bi,
 | 
				
			||||||
 | 
							.hists	= self,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return add_hist_entry(self, &entry, al, period);
 | 
						return add_hist_entry(self, &entry, al, period);
 | 
				
			||||||
| 
						 | 
					@ -343,9 +362,13 @@ struct hist_entry *__hists__add_entry(struct hists *self,
 | 
				
			||||||
		.cpu	= al->cpu,
 | 
							.cpu	= al->cpu,
 | 
				
			||||||
		.ip	= al->addr,
 | 
							.ip	= al->addr,
 | 
				
			||||||
		.level	= al->level,
 | 
							.level	= al->level,
 | 
				
			||||||
 | 
							.stat = {
 | 
				
			||||||
			.period	= period,
 | 
								.period	= period,
 | 
				
			||||||
 | 
								.nr_events = 1,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		.parent = sym_parent,
 | 
							.parent = sym_parent,
 | 
				
			||||||
		.filtered = symbol__parent_filter(sym_parent),
 | 
							.filtered = symbol__parent_filter(sym_parent),
 | 
				
			||||||
 | 
							.hists	= self,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return add_hist_entry(self, &entry, al, period);
 | 
						return add_hist_entry(self, &entry, al, period);
 | 
				
			||||||
| 
						 | 
					@ -410,12 +433,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
 | 
				
			||||||
		cmp = hist_entry__collapse(iter, he);
 | 
							cmp = hist_entry__collapse(iter, he);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!cmp) {
 | 
							if (!cmp) {
 | 
				
			||||||
			iter->period		+= he->period;
 | 
								he_stat__add_stat(&iter->stat, &he->stat);
 | 
				
			||||||
			iter->period_sys	+= he->period_sys;
 | 
					 | 
				
			||||||
			iter->period_us		+= he->period_us;
 | 
					 | 
				
			||||||
			iter->period_guest_sys	+= he->period_guest_sys;
 | 
					 | 
				
			||||||
			iter->period_guest_us	+= he->period_guest_us;
 | 
					 | 
				
			||||||
			iter->nr_events		+= he->nr_events;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (symbol_conf.use_callchain) {
 | 
								if (symbol_conf.use_callchain) {
 | 
				
			||||||
				callchain_cursor_reset(&callchain_cursor);
 | 
									callchain_cursor_reset(&callchain_cursor);
 | 
				
			||||||
| 
						 | 
					@ -518,7 +536,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
 | 
				
			||||||
		parent = *p;
 | 
							parent = *p;
 | 
				
			||||||
		iter = rb_entry(parent, struct hist_entry, rb_node);
 | 
							iter = rb_entry(parent, struct hist_entry, rb_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (he->period > iter->period)
 | 
							if (he->stat.period > iter->stat.period)
 | 
				
			||||||
			p = &(*p)->rb_left;
 | 
								p = &(*p)->rb_left;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			p = &(*p)->rb_right;
 | 
								p = &(*p)->rb_right;
 | 
				
			||||||
| 
						 | 
					@ -579,8 +597,8 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
 | 
				
			||||||
	if (h->ms.unfolded)
 | 
						if (h->ms.unfolded)
 | 
				
			||||||
		hists->nr_entries += h->nr_rows;
 | 
							hists->nr_entries += h->nr_rows;
 | 
				
			||||||
	h->row_offset = 0;
 | 
						h->row_offset = 0;
 | 
				
			||||||
	hists->stats.total_period += h->period;
 | 
						hists->stats.total_period += h->stat.period;
 | 
				
			||||||
	hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events;
 | 
						hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hists__calc_col_len(hists, h);
 | 
						hists__calc_col_len(hists, h);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,9 +98,8 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows);
 | 
				
			||||||
void hists__inc_nr_events(struct hists *self, u32 type);
 | 
					void hists__inc_nr_events(struct hists *self, u32 type);
 | 
				
			||||||
size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
 | 
					size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t hists__fprintf(struct hists *self, struct hists *pair,
 | 
					size_t hists__fprintf(struct hists *self, bool show_header, int max_rows,
 | 
				
			||||||
		      bool show_displacement, bool show_header,
 | 
							      int max_cols, FILE *fp);
 | 
				
			||||||
		      int max_rows, int max_cols, FILE *fp);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
 | 
					int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
 | 
				
			||||||
int hist_entry__annotate(struct hist_entry *self, size_t privsize);
 | 
					int hist_entry__annotate(struct hist_entry *self, size_t privsize);
 | 
				
			||||||
| 
						 | 
					@ -118,9 +117,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
 | 
				
			||||||
struct perf_hpp {
 | 
					struct perf_hpp {
 | 
				
			||||||
	char *buf;
 | 
						char *buf;
 | 
				
			||||||
	size_t size;
 | 
						size_t size;
 | 
				
			||||||
	u64 total_period;
 | 
					 | 
				
			||||||
	const char *sep;
 | 
						const char *sep;
 | 
				
			||||||
	long displacement;
 | 
					 | 
				
			||||||
	void *ptr;
 | 
						void *ptr;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,6 +132,7 @@ struct perf_hpp_fmt {
 | 
				
			||||||
extern struct perf_hpp_fmt perf_hpp__format[];
 | 
					extern struct perf_hpp_fmt perf_hpp__format[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
 | 
						PERF_HPP__BASELINE,
 | 
				
			||||||
	PERF_HPP__OVERHEAD,
 | 
						PERF_HPP__OVERHEAD,
 | 
				
			||||||
	PERF_HPP__OVERHEAD_SYS,
 | 
						PERF_HPP__OVERHEAD_SYS,
 | 
				
			||||||
	PERF_HPP__OVERHEAD_US,
 | 
						PERF_HPP__OVERHEAD_US,
 | 
				
			||||||
| 
						 | 
					@ -148,13 +146,22 @@ enum {
 | 
				
			||||||
	PERF_HPP__MAX_INDEX
 | 
						PERF_HPP__MAX_INDEX
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void perf_hpp__init(bool need_pair, bool show_displacement);
 | 
					void perf_hpp__init(void);
 | 
				
			||||||
 | 
					void perf_hpp__column_enable(unsigned col, bool enable);
 | 
				
			||||||
int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
 | 
					int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
 | 
				
			||||||
				bool color);
 | 
									bool color);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct perf_evlist;
 | 
					struct perf_evlist;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef NO_NEWT_SUPPORT
 | 
					#ifdef NEWT_SUPPORT
 | 
				
			||||||
 | 
					#include "../ui/keysyms.h"
 | 
				
			||||||
 | 
					int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
 | 
				
			||||||
 | 
								     void(*timer)(void *arg), void *arg, int delay_secs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
 | 
				
			||||||
 | 
									  void(*timer)(void *arg), void *arg,
 | 
				
			||||||
 | 
									  int refresh);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
static inline
 | 
					static inline
 | 
				
			||||||
int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
 | 
					int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
 | 
				
			||||||
				  const char *help __maybe_unused,
 | 
									  const char *help __maybe_unused,
 | 
				
			||||||
| 
						 | 
					@ -177,17 +184,13 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#define K_LEFT -1
 | 
					#define K_LEFT -1
 | 
				
			||||||
#define K_RIGHT -2
 | 
					#define K_RIGHT -2
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#include "../ui/keysyms.h"
 | 
					 | 
				
			||||||
int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
 | 
					 | 
				
			||||||
			     void(*timer)(void *arg), void *arg, int delay_secs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
 | 
					 | 
				
			||||||
				  void(*timer)(void *arg), void *arg,
 | 
					 | 
				
			||||||
				  int refresh);
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef NO_GTK2_SUPPORT
 | 
					#ifdef GTK2_SUPPORT
 | 
				
			||||||
 | 
					int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
 | 
				
			||||||
 | 
									  void(*timer)(void *arg), void *arg,
 | 
				
			||||||
 | 
									  int refresh);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
static inline
 | 
					static inline
 | 
				
			||||||
int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
 | 
					int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
 | 
				
			||||||
				  const char *help __maybe_unused,
 | 
									  const char *help __maybe_unused,
 | 
				
			||||||
| 
						 | 
					@ -197,11 +200,6 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
 | 
					 | 
				
			||||||
				  void(*timer)(void *arg), void *arg,
 | 
					 | 
				
			||||||
				  int refresh);
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned int hists__sort_list_width(struct hists *self);
 | 
					unsigned int hists__sort_list_width(struct hists *self);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -162,7 +162,7 @@ int map__load(struct map *self, symbol_filter_t filter)
 | 
				
			||||||
		pr_warning(", continuing without symbols\n");
 | 
							pr_warning(", continuing without symbols\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
	} else if (nr == 0) {
 | 
						} else if (nr == 0) {
 | 
				
			||||||
#ifndef NO_LIBELF_SUPPORT
 | 
					#ifdef LIBELF_SUPPORT
 | 
				
			||||||
		const size_t len = strlen(name);
 | 
							const size_t len = strlen(name);
 | 
				
			||||||
		const size_t real_len = len - sizeof(DSO__DELETED);
 | 
							const size_t real_len = len - sizeof(DSO__DELETED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -384,6 +384,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
 | 
				
			||||||
			return usage_with_options_internal(usagestr, options, 1);
 | 
								return usage_with_options_internal(usagestr, options, 1);
 | 
				
			||||||
		if (internal_help && !strcmp(arg + 2, "help"))
 | 
							if (internal_help && !strcmp(arg + 2, "help"))
 | 
				
			||||||
			return parse_options_usage(usagestr, options);
 | 
								return parse_options_usage(usagestr, options);
 | 
				
			||||||
 | 
							if (!strcmp(arg + 2, "list-opts"))
 | 
				
			||||||
 | 
								return PARSE_OPT_LIST;
 | 
				
			||||||
		switch (parse_long_opt(ctx, arg + 2, options)) {
 | 
							switch (parse_long_opt(ctx, arg + 2, options)) {
 | 
				
			||||||
		case -1:
 | 
							case -1:
 | 
				
			||||||
			return parse_options_usage(usagestr, options);
 | 
								return parse_options_usage(usagestr, options);
 | 
				
			||||||
| 
						 | 
					@ -422,6 +424,12 @@ int parse_options(int argc, const char **argv, const struct option *options,
 | 
				
			||||||
		exit(129);
 | 
							exit(129);
 | 
				
			||||||
	case PARSE_OPT_DONE:
 | 
						case PARSE_OPT_DONE:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case PARSE_OPT_LIST:
 | 
				
			||||||
 | 
							while (options->type != OPTION_END) {
 | 
				
			||||||
 | 
								printf("--%s ", options->long_name);
 | 
				
			||||||
 | 
								options++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							exit(130);
 | 
				
			||||||
	default: /* PARSE_OPT_UNKNOWN */
 | 
						default: /* PARSE_OPT_UNKNOWN */
 | 
				
			||||||
		if (ctx.argv[0][1] == '-') {
 | 
							if (ctx.argv[0][1] == '-') {
 | 
				
			||||||
			error("unknown option `%s'", ctx.argv[0] + 2);
 | 
								error("unknown option `%s'", ctx.argv[0] + 2);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,6 +140,7 @@ extern NORETURN void usage_with_options(const char * const *usagestr,
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	PARSE_OPT_HELP = -1,
 | 
						PARSE_OPT_HELP = -1,
 | 
				
			||||||
	PARSE_OPT_DONE,
 | 
						PARSE_OPT_DONE,
 | 
				
			||||||
 | 
						PARSE_OPT_LIST,
 | 
				
			||||||
	PARSE_OPT_UNKNOWN,
 | 
						PARSE_OPT_UNKNOWN,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ static const char *get_perf_dir(void)
 | 
				
			||||||
	return ".";
 | 
						return ".";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef NO_STRLCPY
 | 
					#ifndef HAVE_STRLCPY
 | 
				
			||||||
size_t strlcpy(char *dest, const char *src, size_t size)
 | 
					size_t strlcpy(char *dest, const char *src, size_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	size_t ret = strlen(src);
 | 
						size_t ret = strlen(src);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
#ifndef __PERF_REGS_H
 | 
					#ifndef __PERF_REGS_H
 | 
				
			||||||
#define __PERF_REGS_H
 | 
					#define __PERF_REGS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef NO_PERF_REGS
 | 
					#ifdef HAVE_PERF_REGS
 | 
				
			||||||
#include <perf_regs.h>
 | 
					#include <perf_regs.h>
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#define PERF_REGS_MASK	0
 | 
					#define PERF_REGS_MASK	0
 | 
				
			||||||
| 
						 | 
					@ -10,5 +10,5 @@ static inline const char *perf_reg_name(int id __maybe_unused)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* NO_PERF_REGS */
 | 
					#endif /* HAVE_PERF_REGS */
 | 
				
			||||||
#endif /* __PERF_REGS_H */
 | 
					#endif /* __PERF_REGS_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,15 @@ extern struct sort_entry sort_sym_from;
 | 
				
			||||||
extern struct sort_entry sort_sym_to;
 | 
					extern struct sort_entry sort_sym_to;
 | 
				
			||||||
extern enum sort_type sort__first_dimension;
 | 
					extern enum sort_type sort__first_dimension;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct he_stat {
 | 
				
			||||||
 | 
						u64			period;
 | 
				
			||||||
 | 
						u64			period_sys;
 | 
				
			||||||
 | 
						u64			period_us;
 | 
				
			||||||
 | 
						u64			period_guest_sys;
 | 
				
			||||||
 | 
						u64			period_guest_us;
 | 
				
			||||||
 | 
						u32			nr_events;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * struct hist_entry - histogram entry
 | 
					 * struct hist_entry - histogram entry
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -52,16 +61,11 @@ extern enum sort_type sort__first_dimension;
 | 
				
			||||||
struct hist_entry {
 | 
					struct hist_entry {
 | 
				
			||||||
	struct rb_node		rb_node_in;
 | 
						struct rb_node		rb_node_in;
 | 
				
			||||||
	struct rb_node		rb_node;
 | 
						struct rb_node		rb_node;
 | 
				
			||||||
	u64			period;
 | 
						struct he_stat		stat;
 | 
				
			||||||
	u64			period_sys;
 | 
					 | 
				
			||||||
	u64			period_us;
 | 
					 | 
				
			||||||
	u64			period_guest_sys;
 | 
					 | 
				
			||||||
	u64			period_guest_us;
 | 
					 | 
				
			||||||
	struct map_symbol	ms;
 | 
						struct map_symbol	ms;
 | 
				
			||||||
	struct thread		*thread;
 | 
						struct thread		*thread;
 | 
				
			||||||
	u64			ip;
 | 
						u64			ip;
 | 
				
			||||||
	s32			cpu;
 | 
						s32			cpu;
 | 
				
			||||||
	u32			nr_events;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* XXX These two should move to some tree widget lib */
 | 
						/* XXX These two should move to some tree widget lib */
 | 
				
			||||||
	u16			row_offset;
 | 
						u16			row_offset;
 | 
				
			||||||
| 
						 | 
					@ -73,12 +77,13 @@ struct hist_entry {
 | 
				
			||||||
	u8			filtered;
 | 
						u8			filtered;
 | 
				
			||||||
	char			*srcline;
 | 
						char			*srcline;
 | 
				
			||||||
	struct symbol		*parent;
 | 
						struct symbol		*parent;
 | 
				
			||||||
	union {
 | 
					 | 
				
			||||||
	unsigned long		position;
 | 
						unsigned long		position;
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
		struct hist_entry *pair;
 | 
							struct hist_entry *pair;
 | 
				
			||||||
		struct rb_root	  sorted_chain;
 | 
							struct rb_root	  sorted_chain;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	struct branch_info	*branch_info;
 | 
						struct branch_info	*branch_info;
 | 
				
			||||||
 | 
						struct hists		*hists;
 | 
				
			||||||
	struct callchain_root	callchain[0];
 | 
						struct callchain_root	callchain[0];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@
 | 
				
			||||||
#include <byteswap.h>
 | 
					#include <byteswap.h>
 | 
				
			||||||
#include <libgen.h>
 | 
					#include <libgen.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef NO_LIBELF_SUPPORT
 | 
					#ifdef LIBELF_SUPPORT
 | 
				
			||||||
#include <libelf.h>
 | 
					#include <libelf.h>
 | 
				
			||||||
#include <gelf.h>
 | 
					#include <gelf.h>
 | 
				
			||||||
#include <elf.h>
 | 
					#include <elf.h>
 | 
				
			||||||
| 
						 | 
					@ -46,10 +46,10 @@ char *strxfrchar(char *s, char from, char to);
 | 
				
			||||||
 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
 | 
					 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
 | 
				
			||||||
 * for newer versions we can use mmap to reduce memory usage:
 | 
					 * for newer versions we can use mmap to reduce memory usage:
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#ifdef LIBELF_NO_MMAP
 | 
					#ifdef LIBELF_MMAP
 | 
				
			||||||
# define PERF_ELF_C_READ_MMAP ELF_C_READ
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
 | 
					# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					# define PERF_ELF_C_READ_MMAP ELF_C_READ
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef DMGL_PARAMS
 | 
					#ifndef DMGL_PARAMS
 | 
				
			||||||
| 
						 | 
					@ -233,7 +233,7 @@ struct symsrc {
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	enum dso_binary_type type;
 | 
						enum dso_binary_type type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef NO_LIBELF_SUPPORT
 | 
					#ifdef LIBELF_SUPPORT
 | 
				
			||||||
	Elf *elf;
 | 
						Elf *elf;
 | 
				
			||||||
	GElf_Ehdr ehdr;
 | 
						GElf_Ehdr ehdr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ struct unwind_entry {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
 | 
					typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef NO_LIBUNWIND_SUPPORT
 | 
					#ifdef LIBUNWIND_SUPPORT
 | 
				
			||||||
int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
 | 
					int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
 | 
				
			||||||
			struct machine *machine,
 | 
								struct machine *machine,
 | 
				
			||||||
			struct thread *thread,
 | 
								struct thread *thread,
 | 
				
			||||||
| 
						 | 
					@ -31,5 +31,5 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* NO_LIBUNWIND_SUPPORT */
 | 
					#endif /* LIBUNWIND_SUPPORT */
 | 
				
			||||||
#endif /* __UNWIND_H */
 | 
					#endif /* __UNWIND_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
#include "../perf.h"
 | 
					#include "../perf.h"
 | 
				
			||||||
#include "util.h"
 | 
					#include "util.h"
 | 
				
			||||||
#include <sys/mman.h>
 | 
					#include <sys/mman.h>
 | 
				
			||||||
#ifndef NO_BACKTRACE
 | 
					#ifdef BACKTRACE_SUPPORT
 | 
				
			||||||
#include <execinfo.h>
 | 
					#include <execinfo.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
| 
						 | 
					@ -165,7 +165,7 @@ size_t hex_width(u64 v)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Obtain a backtrace and print it to stdout. */
 | 
					/* Obtain a backtrace and print it to stdout. */
 | 
				
			||||||
#ifndef NO_BACKTRACE
 | 
					#ifdef BACKTRACE_SUPPORT
 | 
				
			||||||
void dump_stack(void)
 | 
					void dump_stack(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	void *array[16];
 | 
						void *array[16];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue