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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf tooling updates from Ingo Molnar:
"perf.data:

- Streaming compression of perf ring buffer into
PERF_RECORD_COMPRESSED user space records, resulting in ~3-5x
perf.data file size reduction on variety of tested workloads what
saves storage space on larger server systems where perf.data size
can easily reach several tens or even hundreds of GiBs, especially
when profiling with DWARF-based stacks and tracing of context
switches.

perf record:

- Improve -user-regs/intr-regs suggestions to overcome errors

perf annotate:

- Remove hist__account_cycles() from callback, speeding up branch
processing (perf record -b)

perf stat:

- Add a 'percore' event qualifier, e.g.: -e
cpu/event=0,umask=0x3,percore=1/, that sums up the event counts for
both hardware threads in a core.

We can already do this with --per-core, but it's often useful to do
this together with other metrics that are collected per hardware
thread.

I.e. now its possible to do this per-event, and have it mixed with
other events not aggregated by core.

arm64:

- Map Brahma-B53 CPUID to cortex-a53 events.

- Add Cortex-A57 and Cortex-A72 events.

csky:

- Add DWARF register mappings for libdw, allowing --call-graph=dwarf
to work on the C-SKY arch.

x86:

- Add support for recording and printing XMM registers, available,
for instance, on Icelake.

- Add uncore_upi (Intel's "Ultra Path Interconnect" events) JSON
support. UPI replaced the Intel QuickPath Interconnect (QPI) in
Xeon Skylake-SP.

Intel PT:

- Fix instructions sampling rate.

- Timestamp fixes.

- Improve exported-sql-viewer GUI, allowing, for instance, to
copy'n'paste the trees, useful for e-mailing"

* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (73 commits)
perf stat: Support 'percore' event qualifier
perf stat: Factor out aggregate counts printing
perf tools: Add a 'percore' event qualifier
perf docs: Add description for stderr
perf intel-pt: Fix sample timestamp wrt non-taken branches
perf intel-pt: Fix improved sample timestamp
perf intel-pt: Fix instructions sampling rate
perf regs x86: Add X86 specific arch__intr_reg_mask()
perf parse-regs: Add generic support for arch__intr/user_reg_mask()
perf parse-regs: Split parse_regs
perf vendor events arm64: Add Cortex-A57 and Cortex-A72 events
perf vendor events arm64: Map Brahma-B53 CPUID to cortex-a53 events
perf vendor events arm64: Remove [[:xdigit:]] wildcard
perf jevents: Remove unused variable
perf test zstd: Fixup verbose mode output
perf tests: Implement Zstd comp/decomp integration test
perf inject: Enable COMPRESSED record decompression
perf report: Implement perf.data record decompression
perf record: Implement -z,--compression_level[=<n>] option
perf report: Add stub processing of compressed events for -D
...

+5414 -214
+1
tools/arch/x86/include/uapi/asm/kvm.h
··· 381 381 #define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) 382 382 #define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) 383 383 #define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2) 384 + #define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) 384 385 385 386 #define KVM_STATE_NESTED_GUEST_MODE 0x00000001 386 387 #define KVM_STATE_NESTED_RUN_PENDING 0x00000002
+22 -1
tools/arch/x86/include/uapi/asm/perf_regs.h
··· 27 27 PERF_REG_X86_R13, 28 28 PERF_REG_X86_R14, 29 29 PERF_REG_X86_R15, 30 - 30 + /* These are the limits for the GPRs. */ 31 31 PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1, 32 32 PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1, 33 + 34 + /* These all need two bits set because they are 128bit */ 35 + PERF_REG_X86_XMM0 = 32, 36 + PERF_REG_X86_XMM1 = 34, 37 + PERF_REG_X86_XMM2 = 36, 38 + PERF_REG_X86_XMM3 = 38, 39 + PERF_REG_X86_XMM4 = 40, 40 + PERF_REG_X86_XMM5 = 42, 41 + PERF_REG_X86_XMM6 = 44, 42 + PERF_REG_X86_XMM7 = 46, 43 + PERF_REG_X86_XMM8 = 48, 44 + PERF_REG_X86_XMM9 = 50, 45 + PERF_REG_X86_XMM10 = 52, 46 + PERF_REG_X86_XMM11 = 54, 47 + PERF_REG_X86_XMM12 = 56, 48 + PERF_REG_X86_XMM13 = 58, 49 + PERF_REG_X86_XMM14 = 60, 50 + PERF_REG_X86_XMM15 = 62, 51 + 52 + /* These include both GPRs and XMMX registers */ 53 + PERF_REG_X86_XMM_MAX = PERF_REG_X86_XMM15 + 2, 33 54 }; 34 55 #endif /* _ASM_X86_PERF_REGS_H */
+2 -1
tools/arch/x86/lib/memcpy_64.S
··· 257 257 /* Copy successful. Return zero */ 258 258 .L_done_memcpy_trap: 259 259 xorl %eax, %eax 260 + .L_done: 260 261 ret 261 262 ENDPROC(__memcpy_mcsafe) 262 263 EXPORT_SYMBOL_GPL(__memcpy_mcsafe) ··· 274 273 addl %edx, %ecx 275 274 .E_trailing_bytes: 276 275 mov %ecx, %eax 277 - ret 276 + jmp .L_done 278 277 279 278 /* 280 279 * For write fault handling, given the destination is unaligned,
+207
tools/lib/traceevent/Documentation/Makefile
··· 1 + include ../../../scripts/Makefile.include 2 + include ../../../scripts/utilities.mak 3 + 4 + # This Makefile and manpage XSL files were taken from tools/perf/Documentation 5 + # and modified for libtraceevent. 6 + 7 + MAN3_TXT= \ 8 + $(wildcard libtraceevent-*.txt) \ 9 + libtraceevent.txt 10 + 11 + MAN_TXT = $(MAN3_TXT) 12 + _MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT)) 13 + _MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT)) 14 + _DOC_MAN3=$(patsubst %.txt,%.3,$(MAN3_TXT)) 15 + 16 + MAN_XML=$(addprefix $(OUTPUT),$(_MAN_XML)) 17 + MAN_HTML=$(addprefix $(OUTPUT),$(_MAN_HTML)) 18 + DOC_MAN3=$(addprefix $(OUTPUT),$(_DOC_MAN3)) 19 + 20 + # Make the path relative to DESTDIR, not prefix 21 + ifndef DESTDIR 22 + prefix?=$(HOME) 23 + endif 24 + bindir?=$(prefix)/bin 25 + htmldir?=$(prefix)/share/doc/libtraceevent-doc 26 + pdfdir?=$(prefix)/share/doc/libtraceevent-doc 27 + mandir?=$(prefix)/share/man 28 + man3dir=$(mandir)/man3 29 + 30 + ASCIIDOC=asciidoc 31 + ASCIIDOC_EXTRA = --unsafe -f asciidoc.conf 32 + ASCIIDOC_HTML = xhtml11 33 + MANPAGE_XSL = manpage-normal.xsl 34 + XMLTO_EXTRA = 35 + INSTALL?=install 36 + RM ?= rm -f 37 + 38 + ifdef USE_ASCIIDOCTOR 39 + ASCIIDOC = asciidoctor 40 + ASCIIDOC_EXTRA = -a compat-mode 41 + ASCIIDOC_EXTRA += -I. -rasciidoctor-extensions 42 + ASCIIDOC_EXTRA += -a mansource="libtraceevent" -a manmanual="libtraceevent Manual" 43 + ASCIIDOC_HTML = xhtml5 44 + endif 45 + 46 + XMLTO=xmlto 47 + 48 + _tmp_tool_path := $(call get-executable,$(ASCIIDOC)) 49 + ifeq ($(_tmp_tool_path),) 50 + missing_tools = $(ASCIIDOC) 51 + endif 52 + 53 + ifndef USE_ASCIIDOCTOR 54 + _tmp_tool_path := $(call get-executable,$(XMLTO)) 55 + ifeq ($(_tmp_tool_path),) 56 + missing_tools += $(XMLTO) 57 + endif 58 + endif 59 + 60 + # 61 + # For asciidoc ... 62 + # -7.1.2, no extra settings are needed. 63 + # 8.0-, set ASCIIDOC8. 64 + # 65 + 66 + # 67 + # For docbook-xsl ... 68 + # -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0) 69 + # 1.69.0, no extra settings are needed? 70 + # 1.69.1-1.71.0, set DOCBOOK_SUPPRESS_SP? 71 + # 1.71.1, no extra settings are needed? 72 + # 1.72.0, set DOCBOOK_XSL_172. 73 + # 1.73.0-, set ASCIIDOC_NO_ROFF 74 + # 75 + 76 + # 77 + # If you had been using DOCBOOK_XSL_172 in an attempt to get rid 78 + # of 'the ".ft C" problem' in your generated manpages, and you 79 + # instead ended up with weird characters around callouts, try 80 + # using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8). 81 + # 82 + 83 + ifdef ASCIIDOC8 84 + ASCIIDOC_EXTRA += -a asciidoc7compatible 85 + endif 86 + ifdef DOCBOOK_XSL_172 87 + ASCIIDOC_EXTRA += -a libtraceevent-asciidoc-no-roff 88 + MANPAGE_XSL = manpage-1.72.xsl 89 + else 90 + ifdef ASCIIDOC_NO_ROFF 91 + # docbook-xsl after 1.72 needs the regular XSL, but will not 92 + # pass-thru raw roff codes from asciidoc.conf, so turn them off. 93 + ASCIIDOC_EXTRA += -a libtraceevent-asciidoc-no-roff 94 + endif 95 + endif 96 + ifdef MAN_BOLD_LITERAL 97 + XMLTO_EXTRA += -m manpage-bold-literal.xsl 98 + endif 99 + ifdef DOCBOOK_SUPPRESS_SP 100 + XMLTO_EXTRA += -m manpage-suppress-sp.xsl 101 + endif 102 + 103 + SHELL_PATH ?= $(SHELL) 104 + # Shell quote; 105 + SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) 106 + 107 + DESTDIR ?= 108 + DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' 109 + 110 + export DESTDIR DESTDIR_SQ 111 + 112 + # 113 + # Please note that there is a minor bug in asciidoc. 114 + # The version after 6.0.3 _will_ include the patch found here: 115 + # http://marc.theaimsgroup.com/?l=libtraceevent&m=111558757202243&w=2 116 + # 117 + # Until that version is released you may have to apply the patch 118 + # yourself - yes, all 6 characters of it! 119 + # 120 + QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir 121 + QUIET_SUBDIR1 = 122 + 123 + ifneq ($(findstring $(MAKEFLAGS),w),w) 124 + PRINT_DIR = --no-print-directory 125 + else # "make -w" 126 + NO_SUBDIR = : 127 + endif 128 + 129 + ifneq ($(findstring $(MAKEFLAGS),s),s) 130 + ifneq ($(V),1) 131 + QUIET_ASCIIDOC = @echo ' ASCIIDOC '$@; 132 + QUIET_XMLTO = @echo ' XMLTO '$@; 133 + QUIET_SUBDIR0 = +@subdir= 134 + QUIET_SUBDIR1 = ;$(NO_SUBDIR) \ 135 + echo ' SUBDIR ' $$subdir; \ 136 + $(MAKE) $(PRINT_DIR) -C $$subdir 137 + export V 138 + endif 139 + endif 140 + 141 + all: html man 142 + 143 + man: man3 144 + man3: $(DOC_MAN3) 145 + 146 + html: $(MAN_HTML) 147 + 148 + $(MAN_HTML) $(DOC_MAN3): asciidoc.conf 149 + 150 + install: install-man 151 + 152 + check-man-tools: 153 + ifdef missing_tools 154 + $(error "You need to install $(missing_tools) for man pages") 155 + endif 156 + 157 + do-install-man: man 158 + $(call QUIET_INSTALL, Documentation-man) \ 159 + $(INSTALL) -d -m 755 $(DESTDIR)$(man3dir); \ 160 + $(INSTALL) -m 644 $(DOC_MAN3) $(DESTDIR)$(man3dir); 161 + 162 + install-man: check-man-tools man do-install-man 163 + 164 + uninstall: uninstall-man 165 + 166 + uninstall-man: 167 + $(call QUIET_UNINST, Documentation-man) \ 168 + $(Q)$(RM) $(addprefix $(DESTDIR)$(man3dir)/,$(DOC_MAN3)) 169 + 170 + 171 + ifdef missing_tools 172 + DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed) 173 + else 174 + DO_INSTALL_MAN = do-install-man 175 + endif 176 + 177 + CLEAN_FILES = \ 178 + $(MAN_XML) $(addsuffix +,$(MAN_XML)) \ 179 + $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \ 180 + $(DOC_MAN3) *.3 181 + 182 + clean: 183 + $(call QUIET_CLEAN, Documentation) $(RM) $(CLEAN_FILES) 184 + 185 + ifdef USE_ASCIIDOCTOR 186 + $(OUTPUT)%.3 : $(OUTPUT)%.txt 187 + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 188 + $(ASCIIDOC) -b manpage -d manpage \ 189 + $(ASCIIDOC_EXTRA) -alibtraceevent_version=$(EVENT_PARSE_VERSION) -o $@+ $< && \ 190 + mv $@+ $@ 191 + endif 192 + 193 + $(OUTPUT)%.3 : $(OUTPUT)%.xml 194 + $(QUIET_XMLTO)$(RM) $@ && \ 195 + $(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< 196 + 197 + $(OUTPUT)%.xml : %.txt 198 + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 199 + $(ASCIIDOC) -b docbook -d manpage \ 200 + $(ASCIIDOC_EXTRA) -alibtraceevent_version=$(EVENT_PARSE_VERSION) -o $@+ $< && \ 201 + mv $@+ $@ 202 + 203 + $(MAN_HTML): $(OUTPUT)%.html : %.txt 204 + $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 205 + $(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage \ 206 + $(ASCIIDOC_EXTRA) -aperf_version=$(EVENT_PARSE_VERSION) -o $@+ $< && \ 207 + mv $@+ $@
+120
tools/lib/traceevent/Documentation/asciidoc.conf
··· 1 + ## linktep: macro 2 + # 3 + # Usage: linktep:command[manpage-section] 4 + # 5 + # Note, {0} is the manpage section, while {target} is the command. 6 + # 7 + # Show TEP link as: <command>(<section>); if section is defined, else just show 8 + # the command. 9 + 10 + [macros] 11 + (?su)[\\]?(?P<name>linktep):(?P<target>\S*?)\[(?P<attrlist>.*?)\]= 12 + 13 + [attributes] 14 + asterisk=&#42; 15 + plus=&#43; 16 + caret=&#94; 17 + startsb=&#91; 18 + endsb=&#93; 19 + tilde=&#126; 20 + 21 + ifdef::backend-docbook[] 22 + [linktep-inlinemacro] 23 + {0%{target}} 24 + {0#<citerefentry>} 25 + {0#<refentrytitle>{target}</refentrytitle><manvolnum>{0}</manvolnum>} 26 + {0#</citerefentry>} 27 + endif::backend-docbook[] 28 + 29 + ifdef::backend-docbook[] 30 + ifndef::tep-asciidoc-no-roff[] 31 + # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. 32 + # v1.72 breaks with this because it replaces dots not in roff requests. 33 + [listingblock] 34 + <example><title>{title}</title> 35 + <literallayout> 36 + ifdef::doctype-manpage[] 37 + &#10;.ft C&#10; 38 + endif::doctype-manpage[] 39 + | 40 + ifdef::doctype-manpage[] 41 + &#10;.ft&#10; 42 + endif::doctype-manpage[] 43 + </literallayout> 44 + {title#}</example> 45 + endif::tep-asciidoc-no-roff[] 46 + 47 + ifdef::tep-asciidoc-no-roff[] 48 + ifdef::doctype-manpage[] 49 + # The following two small workarounds insert a simple paragraph after screen 50 + [listingblock] 51 + <example><title>{title}</title> 52 + <literallayout> 53 + | 54 + </literallayout><simpara></simpara> 55 + {title#}</example> 56 + 57 + [verseblock] 58 + <formalpara{id? id="{id}"}><title>{title}</title><para> 59 + {title%}<literallayout{id? id="{id}"}> 60 + {title#}<literallayout> 61 + | 62 + </literallayout> 63 + {title#}</para></formalpara> 64 + {title%}<simpara></simpara> 65 + endif::doctype-manpage[] 66 + endif::tep-asciidoc-no-roff[] 67 + endif::backend-docbook[] 68 + 69 + ifdef::doctype-manpage[] 70 + ifdef::backend-docbook[] 71 + [header] 72 + template::[header-declarations] 73 + <refentry> 74 + <refmeta> 75 + <refentrytitle>{mantitle}</refentrytitle> 76 + <manvolnum>{manvolnum}</manvolnum> 77 + <refmiscinfo class="source">libtraceevent</refmiscinfo> 78 + <refmiscinfo class="version">{libtraceevent_version}</refmiscinfo> 79 + <refmiscinfo class="manual">libtraceevent Manual</refmiscinfo> 80 + </refmeta> 81 + <refnamediv> 82 + <refname>{manname1}</refname> 83 + <refname>{manname2}</refname> 84 + <refname>{manname3}</refname> 85 + <refname>{manname4}</refname> 86 + <refname>{manname5}</refname> 87 + <refname>{manname6}</refname> 88 + <refname>{manname7}</refname> 89 + <refname>{manname8}</refname> 90 + <refname>{manname9}</refname> 91 + <refname>{manname10}</refname> 92 + <refname>{manname11}</refname> 93 + <refname>{manname12}</refname> 94 + <refname>{manname13}</refname> 95 + <refname>{manname14}</refname> 96 + <refname>{manname15}</refname> 97 + <refname>{manname16}</refname> 98 + <refname>{manname17}</refname> 99 + <refname>{manname18}</refname> 100 + <refname>{manname19}</refname> 101 + <refname>{manname20}</refname> 102 + <refname>{manname21}</refname> 103 + <refname>{manname22}</refname> 104 + <refname>{manname23}</refname> 105 + <refname>{manname24}</refname> 106 + <refname>{manname25}</refname> 107 + <refname>{manname26}</refname> 108 + <refname>{manname27}</refname> 109 + <refname>{manname28}</refname> 110 + <refname>{manname29}</refname> 111 + <refname>{manname30}</refname> 112 + <refpurpose>{manpurpose}</refpurpose> 113 + </refnamediv> 114 + endif::backend-docbook[] 115 + endif::doctype-manpage[] 116 + 117 + ifdef::backend-xhtml11[] 118 + [linktep-inlinemacro] 119 + <a href="{target}.html">{target}{0?({0})}</a> 120 + endif::backend-xhtml11[]
+153
tools/lib/traceevent/Documentation/libtraceevent-commands.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_register_comm, tep_override_comm, tep_pid_is_registered, 7 + tep_data_comm_from_pid, tep_data_pid_from_comm, tep_cmdline_pid - 8 + Manage pid to process name mappings. 9 + 10 + SYNOPSIS 11 + -------- 12 + [verse] 13 + -- 14 + *#include <event-parse.h>* 15 + 16 + int *tep_register_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, int _pid_); 17 + int *tep_override_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, int _pid_); 18 + bool *tep_is_pid_registered*(struct tep_handle pass:[*]_tep_, int _pid_); 19 + const char pass:[*]*tep_data_comm_from_pid*(struct tep_handle pass:[*]_pevent_, int _pid_); 20 + struct cmdline pass:[*]*tep_data_pid_from_comm*(struct tep_handle pass:[*]_pevent_, const char pass:[*]_comm_, struct cmdline pass:[*]_next_); 21 + int *tep_cmdline_pid*(struct tep_handle pass:[*]_pevent_, struct cmdline pass:[*]_cmdline_); 22 + -- 23 + 24 + DESCRIPTION 25 + ----------- 26 + These functions can be used to handle the mapping between pid and process name. 27 + The library builds a cache of these mappings, which is used to display the name 28 + of the process, instead of its pid. This information can be retrieved from 29 + tracefs/saved_cmdlines file. 30 + 31 + The _tep_register_comm()_ function registers a _pid_ / process name mapping. 32 + If a command with the same _pid_ is already registered, an error is returned. 33 + The _pid_ argument is the process ID, the _comm_ argument is the process name, 34 + _tep_ is the event context. The _comm_ is duplicated internally. 35 + 36 + The _tep_override_comm()_ function registers a _pid_ / process name mapping. 37 + If a process with the same pid is already registered, the process name string is 38 + udapted with the new one. The _pid_ argument is the process ID, the _comm_ 39 + argument is the process name, _tep_ is the event context. The _comm_ is 40 + duplicated internally. 41 + 42 + The _tep_is_pid_registered()_ function checks if a pid has a process name 43 + mapping registered. The _pid_ argument is the process ID, _tep_ is the event 44 + context. 45 + 46 + The _tep_data_comm_from_pid()_ function returns the process name for a given 47 + pid. The _pid_ argument is the process ID, _tep_ is the event context. 48 + The returned string should not be freed, but will be freed when the _tep_ 49 + handler is closed. 50 + 51 + The _tep_data_pid_from_comm()_ function returns a pid for a given process name. 52 + The _comm_ argument is the process name, _tep_ is the event context. 53 + The argument _next_ is the cmdline structure to search for the next pid. 54 + As there may be more than one pid for a given process, the result of this call 55 + can be passed back into a recurring call in the _next_ parameter, to search for 56 + the next pid. If _next_ is NULL, it will return the first pid associated with 57 + the _comm_. The function performs a linear search, so it may be slow. 58 + 59 + The _tep_cmdline_pid()_ function returns the pid associated with a given 60 + _cmdline_. The _tep_ argument is the event context. 61 + 62 + RETURN VALUE 63 + ------------ 64 + _tep_register_comm()_ function returns 0 on success. In case of an error -1 is 65 + returned and errno is set to indicate the cause of the problem: ENOMEM, if there 66 + is not enough memory to duplicate the _comm_ or EEXIST if a mapping for this 67 + _pid_ is already registered. 68 + 69 + _tep_override_comm()_ function returns 0 on success. In case of an error -1 is 70 + returned and errno is set to indicate the cause of the problem: ENOMEM, if there 71 + is not enough memory to duplicate the _comm_. 72 + 73 + _tep_is_pid_registered()_ function returns true if the _pid_ has a process name 74 + mapped to it, false otherwise. 75 + 76 + _tep_data_comm_from_pid()_ function returns the process name as string, or the 77 + string "<...>" if there is no mapping for the given pid. 78 + 79 + _tep_data_pid_from_comm()_ function returns a pointer to a struct cmdline, that 80 + holds a pid for a given process, or NULL if none is found. This result can be 81 + passed back into a recurring call as the _next_ parameter of the function. 82 + 83 + _tep_cmdline_pid()_ functions returns the pid for the give cmdline. If _cmdline_ 84 + is NULL, then -1 is returned. 85 + 86 + EXAMPLE 87 + ------- 88 + The following example registers pid for command "ls", in context of event _tep_ 89 + and performs various searches for pid / process name mappings: 90 + [source,c] 91 + -- 92 + #include <event-parse.h> 93 + ... 94 + int ret; 95 + int ls_pid = 1021; 96 + struct tep_handle *tep = tep_alloc(); 97 + ... 98 + ret = tep_register_comm(tep, "ls", ls_pid); 99 + if (ret != 0 && errno == EEXIST) 100 + ret = tep_override_comm(tep, "ls", ls_pid); 101 + if (ret != 0) { 102 + /* Failed to register pid / command mapping */ 103 + } 104 + ... 105 + if (tep_is_pid_registered(tep, ls_pid) == 0) { 106 + /* Command mapping for ls_pid is not registered */ 107 + } 108 + ... 109 + const char *comm = tep_data_comm_from_pid(tep, ls_pid); 110 + if (comm) { 111 + /* Found process name for ls_pid */ 112 + } 113 + ... 114 + int pid; 115 + struct cmdline *cmd = tep_data_pid_from_comm(tep, "ls", NULL); 116 + while (cmd) { 117 + pid = tep_cmdline_pid(tep, cmd); 118 + /* Found pid for process "ls" */ 119 + cmd = tep_data_pid_from_comm(tep, "ls", cmd); 120 + } 121 + -- 122 + FILES 123 + ----- 124 + [verse] 125 + -- 126 + *event-parse.h* 127 + Header file to include in order to have access to the library APIs. 128 + *-ltraceevent* 129 + Linker switch to add when building a program that uses the library. 130 + -- 131 + 132 + SEE ALSO 133 + -------- 134 + _libtraceevent(3)_, _trace-cmd(1)_ 135 + 136 + AUTHOR 137 + ------ 138 + [verse] 139 + -- 140 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 141 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 142 + -- 143 + REPORTING BUGS 144 + -------------- 145 + Report bugs to <linux-trace-devel@vger.kernel.org> 146 + 147 + LICENSE 148 + ------- 149 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 150 + 151 + RESOURCES 152 + --------- 153 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+77
tools/lib/traceevent/Documentation/libtraceevent-cpus.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_get_cpus, tep_set_cpus - Get / set the number of CPUs, which have a tracing 7 + buffer representing it. Note, the buffer may be empty. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + int *tep_get_cpus*(struct tep_handle pass:[*]_tep_); 16 + void *tep_set_cpus*(struct tep_handle pass:[*]_tep_, int _cpus_); 17 + -- 18 + 19 + DESCRIPTION 20 + ----------- 21 + The _tep_get_cpus()_ function gets the number of CPUs, which have a tracing 22 + buffer representing it. The _tep_ argument is trace event parser context. 23 + 24 + The _tep_set_cpus()_ function sets the number of CPUs, which have a tracing 25 + buffer representing it. The _tep_ argument is trace event parser context. 26 + The _cpu_ argument is the number of CPUs with tracing data. 27 + 28 + RETURN VALUE 29 + ------------ 30 + The _tep_get_cpus()_ functions returns the number of CPUs, which have tracing 31 + data recorded. 32 + 33 + EXAMPLE 34 + ------- 35 + [source,c] 36 + -- 37 + #include <event-parse.h> 38 + ... 39 + struct tep_handle *tep = tep_alloc(); 40 + ... 41 + tep_set_cpus(tep, 5); 42 + ... 43 + printf("We have tracing data for %d CPUs", tep_get_cpus(tep)); 44 + -- 45 + 46 + FILES 47 + ----- 48 + [verse] 49 + -- 50 + *event-parse.h* 51 + Header file to include in order to have access to the library APIs. 52 + *-ltraceevent* 53 + Linker switch to add when building a program that uses the library. 54 + -- 55 + 56 + SEE ALSO 57 + -------- 58 + _libtraceevent(3)_, _trace-cmd(1)_ 59 + 60 + AUTHOR 61 + ------ 62 + [verse] 63 + -- 64 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 65 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 66 + -- 67 + REPORTING BUGS 68 + -------------- 69 + Report bugs to <linux-trace-devel@vger.kernel.org> 70 + 71 + LICENSE 72 + ------- 73 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 74 + 75 + RESOURCES 76 + --------- 77 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+78
tools/lib/traceevent/Documentation/libtraceevent-endian_read.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_read_number - Reads a number from raw data. 7 + 8 + SYNOPSIS 9 + -------- 10 + [verse] 11 + -- 12 + *#include <event-parse.h>* 13 + 14 + unsigned long long *tep_read_number*(struct tep_handle pass:[*]_tep_, const void pass:[*]_ptr_, int _size_); 15 + -- 16 + 17 + DESCRIPTION 18 + ----------- 19 + The _tep_read_number()_ function reads an integer from raw data, taking into 20 + account the endianness of the raw data and the current host. The _tep_ argument 21 + is the trace event parser context. The _ptr_ is a pointer to the raw data, where 22 + the integer is, and the _size_ is the size of the integer. 23 + 24 + RETURN VALUE 25 + ------------ 26 + The _tep_read_number()_ function returns the integer in the byte order of 27 + the current host. In case of an error, 0 is returned. 28 + 29 + EXAMPLE 30 + ------- 31 + [source,c] 32 + -- 33 + #include <event-parse.h> 34 + ... 35 + struct tep_handle *tep = tep_alloc(); 36 + ... 37 + void process_record(struct tep_record *record) 38 + { 39 + int offset = 24; 40 + int data = tep_read_number(tep, record->data + offset, 4); 41 + 42 + /* Read the 4 bytes at the offset 24 of data as an integer */ 43 + } 44 + ... 45 + -- 46 + 47 + FILES 48 + ----- 49 + [verse] 50 + -- 51 + *event-parse.h* 52 + Header file to include in order to have access to the library APIs. 53 + *-ltraceevent* 54 + Linker switch to add when building a program that uses the library. 55 + -- 56 + 57 + SEE ALSO 58 + -------- 59 + _libtraceevent(3)_, _trace-cmd(1)_ 60 + 61 + AUTHOR 62 + ------ 63 + [verse] 64 + -- 65 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 66 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 67 + -- 68 + REPORTING BUGS 69 + -------------- 70 + Report bugs to <linux-trace-devel@vger.kernel.org> 71 + 72 + LICENSE 73 + ------- 74 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 75 + 76 + RESOURCES 77 + --------- 78 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+103
tools/lib/traceevent/Documentation/libtraceevent-event_find.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_find_event,tep_find_event_by_name,tep_find_event_by_record - 7 + Find events by given key. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + struct tep_event pass:[*]*tep_find_event*(struct tep_handle pass:[*]_tep_, int _id_); 16 + struct tep_event pass:[*]*tep_find_event_by_name*(struct tep_handle pass:[*]_tep_, const char pass:[*]_sys_, const char pass:[*]_name_); 17 + struct tep_event pass:[*]*tep_find_event_by_record*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_record_); 18 + -- 19 + 20 + DESCRIPTION 21 + ----------- 22 + This set of functions can be used to search for an event, based on a given 23 + criteria. All functions require a pointer to a _tep_, trace event parser 24 + context. 25 + 26 + The _tep_find_event()_ function searches for an event by given event _id_. The 27 + event ID is assigned dynamically and can be viewed in event's format file, 28 + "ID" field. 29 + 30 + The tep_find_event_by_name()_ function searches for an event by given 31 + event _name_, under the system _sys_. If the _sys_ is NULL (not specified), 32 + the first event with _name_ is returned. 33 + 34 + The tep_find_event_by_record()_ function searches for an event from a given 35 + _record_. 36 + 37 + RETURN VALUE 38 + ------------ 39 + All these functions return a pointer to the found event, or NULL if there is no 40 + such event. 41 + 42 + EXAMPLE 43 + ------- 44 + [source,c] 45 + -- 46 + #include <event-parse.h> 47 + ... 48 + struct tep_handle *tep = tep_alloc(); 49 + ... 50 + struct tep_event *event; 51 + 52 + event = tep_find_event(tep, 1857); 53 + if (event == NULL) { 54 + /* There is no event with ID 1857 */ 55 + } 56 + 57 + event = tep_find_event_by_name(tep, "kvm", "kvm_exit"); 58 + if (event == NULL) { 59 + /* There is no kvm_exit event, from kvm system */ 60 + } 61 + 62 + void event_from_record(struct tep_record *record) 63 + { 64 + struct tep_event *event = tep_find_event_by_record(tep, record); 65 + if (event == NULL) { 66 + /* There is no event from given record */ 67 + } 68 + } 69 + ... 70 + -- 71 + 72 + FILES 73 + ----- 74 + [verse] 75 + -- 76 + *event-parse.h* 77 + Header file to include in order to have access to the library APIs. 78 + *-ltraceevent* 79 + Linker switch to add when building a program that uses the library. 80 + -- 81 + 82 + SEE ALSO 83 + -------- 84 + _libtraceevent(3)_, _trace-cmd(1)_ 85 + 86 + AUTHOR 87 + ------ 88 + [verse] 89 + -- 90 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 91 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 92 + -- 93 + REPORTING BUGS 94 + -------------- 95 + Report bugs to <linux-trace-devel@vger.kernel.org> 96 + 97 + LICENSE 98 + ------- 99 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 100 + 101 + RESOURCES 102 + --------- 103 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+99
tools/lib/traceevent/Documentation/libtraceevent-event_get.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_get_event, tep_get_first_event, tep_get_events_count - Access events. 7 + 8 + SYNOPSIS 9 + -------- 10 + [verse] 11 + -- 12 + *#include <event-parse.h>* 13 + 14 + struct tep_event pass:[*]*tep_get_event*(struct tep_handle pass:[*]_tep_, int _index_); 15 + struct tep_event pass:[*]*tep_get_first_event*(struct tep_handle pass:[*]_tep_); 16 + int *tep_get_events_count*(struct tep_handle pass:[*]_tep_); 17 + -- 18 + 19 + DESCRIPTION 20 + ----------- 21 + The _tep_get_event()_ function returns a pointer to event at the given _index_. 22 + The _tep_ argument is trace event parser context, the _index_ is the index of 23 + the requested event. 24 + 25 + The _tep_get_first_event()_ function returns a pointer to the first event. 26 + As events are stored in an array, this function returns the pointer to the 27 + beginning of the array. The _tep_ argument is trace event parser context. 28 + 29 + The _tep_get_events_count()_ function returns the number of the events 30 + in the array. The _tep_ argument is trace event parser context. 31 + 32 + RETURN VALUE 33 + ------------ 34 + The _tep_get_event()_ returns a pointer to the event located at _index_. 35 + NULL is returned in case of error, in case there are no events or _index_ is 36 + out of range. 37 + 38 + The _tep_get_first_event()_ returns a pointer to the first event. NULL is 39 + returned in case of error, or in case there are no events. 40 + 41 + The _tep_get_events_count()_ returns the number of the events. 0 is 42 + returned in case of error, or in case there are no events. 43 + 44 + EXAMPLE 45 + ------- 46 + [source,c] 47 + -- 48 + #include <event-parse.h> 49 + ... 50 + struct tep_handle *tep = tep_alloc(); 51 + ... 52 + int i,count = tep_get_events_count(tep); 53 + struct tep_event *event, *events = tep_get_first_event(tep); 54 + 55 + if (events == NULL) { 56 + /* There are no events */ 57 + } else { 58 + for (i = 0; i < count; i++) { 59 + event = (events+i); 60 + /* process events[i] */ 61 + } 62 + 63 + /* Get the last event */ 64 + event = tep_get_event(tep, count-1); 65 + } 66 + -- 67 + 68 + FILES 69 + ----- 70 + [verse] 71 + -- 72 + *event-parse.h* 73 + Header file to include in order to have access to the library APIs. 74 + *-ltraceevent* 75 + Linker switch to add when building a program that uses the library. 76 + -- 77 + 78 + SEE ALSO 79 + -------- 80 + _libtraceevent(3)_, _trace-cmd(1)_ 81 + 82 + AUTHOR 83 + ------ 84 + [verse] 85 + -- 86 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 87 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 88 + -- 89 + REPORTING BUGS 90 + -------------- 91 + Report bugs to <linux-trace-devel@vger.kernel.org> 92 + 93 + LICENSE 94 + ------- 95 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 96 + 97 + RESOURCES 98 + --------- 99 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+122
tools/lib/traceevent/Documentation/libtraceevent-event_list.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_list_events, tep_list_events_copy - 7 + Get list of events, sorted by given criteria. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + enum *tep_event_sort_type* { 16 + _TEP_EVENT_SORT_ID_, 17 + _TEP_EVENT_SORT_NAME_, 18 + _TEP_EVENT_SORT_SYSTEM_, 19 + }; 20 + 21 + struct tep_event pass:[*]pass:[*]*tep_list_events*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); 22 + struct tep_event pass:[*]pass:[*]*tep_list_events_copy*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); 23 + -- 24 + 25 + DESCRIPTION 26 + ----------- 27 + The _tep_list_events()_ function returns an array of pointers to the events, 28 + sorted by the _sort_type_ criteria. The last element of the array is NULL. 29 + The returned memory must not be freed, it is managed by the library. 30 + The function is not thread safe. The _tep_ argument is trace event parser 31 + context. The _sort_type_ argument is the required sort criteria: 32 + [verse] 33 + -- 34 + _TEP_EVENT_SORT_ID_ - sort by the event ID. 35 + _TEP_EVENT_SORT_NAME_ - sort by the event (name, system, id) triplet. 36 + _TEP_EVENT_SORT_SYSTEM_ - sort by the event (system, name, id) triplet. 37 + -- 38 + 39 + The _tep_list_events_copy()_ is a thread safe version of _tep_list_events()_. 40 + It has the same behavior, but the returned array is allocated internally and 41 + must be freed by the caller. Note that the content of the array must not be 42 + freed (see the EXAMPLE below). 43 + 44 + RETURN VALUE 45 + ------------ 46 + The _tep_list_events()_ function returns an array of pointers to events. 47 + In case of an error, NULL is returned. The returned array must not be freed, 48 + it is managed by the library. 49 + 50 + The _tep_list_events_copy()_ function returns an array of pointers to events. 51 + In case of an error, NULL is returned. The returned array must be freed by 52 + the caller. 53 + 54 + EXAMPLE 55 + ------- 56 + [source,c] 57 + -- 58 + #include <event-parse.h> 59 + ... 60 + struct tep_handle *tep = tep_alloc(); 61 + ... 62 + int i; 63 + struct tep_event_format **events; 64 + 65 + i=0; 66 + events = tep_list_events(tep, TEP_EVENT_SORT_ID); 67 + if (events == NULL) { 68 + /* Failed to get the events, sorted by ID */ 69 + } else { 70 + while(events[i]) { 71 + /* walk through the list of the events, sorted by ID */ 72 + i++; 73 + } 74 + } 75 + 76 + i=0; 77 + events = tep_list_events_copy(tep, TEP_EVENT_SORT_NAME); 78 + if (events == NULL) { 79 + /* Failed to get the events, sorted by name */ 80 + } else { 81 + while(events[i]) { 82 + /* walk through the list of the events, sorted by name */ 83 + i++; 84 + } 85 + free(events); 86 + } 87 + 88 + ... 89 + -- 90 + 91 + FILES 92 + ----- 93 + [verse] 94 + -- 95 + *event-parse.h* 96 + Header file to include in order to have access to the library APIs. 97 + *-ltraceevent* 98 + Linker switch to add when building a program that uses the library. 99 + -- 100 + 101 + SEE ALSO 102 + -------- 103 + _libtraceevent(3)_, _trace-cmd(1)_ 104 + 105 + AUTHOR 106 + ------ 107 + [verse] 108 + -- 109 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 110 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 111 + -- 112 + REPORTING BUGS 113 + -------------- 114 + Report bugs to <linux-trace-devel@vger.kernel.org> 115 + 116 + LICENSE 117 + ------- 118 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 119 + 120 + RESOURCES 121 + --------- 122 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+118
tools/lib/traceevent/Documentation/libtraceevent-field_find.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_find_common_field, tep_find_field, tep_find_any_field - 7 + Search for a field in an event. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + struct tep_format_field pass:[*]*tep_find_common_field*(struct tep_event pass:[*]_event_, const char pass:[*]_name_); 16 + struct tep_format_field pass:[*]*tep_find_field*(struct tep_event_ormat pass:[*]_event_, const char pass:[*]_name_); 17 + struct tep_format_field pass:[*]*tep_find_any_field*(struct tep_event pass:[*]_event_, const char pass:[*]_name_); 18 + -- 19 + 20 + DESCRIPTION 21 + ----------- 22 + These functions search for a field with given name in an event. The field 23 + returned can be used to find the field content from within a data record. 24 + 25 + The _tep_find_common_field()_ function searches for a common field with _name_ 26 + in the _event_. 27 + 28 + The _tep_find_field()_ function searches for an event specific field with 29 + _name_ in the _event_. 30 + 31 + The _tep_find_any_field()_ function searches for any field with _name_ in the 32 + _event_. 33 + 34 + RETURN VALUE 35 + ------------ 36 + The _tep_find_common_field(), _tep_find_field()_ and _tep_find_any_field()_ 37 + functions return a pointer to the found field, or NULL in case there is no field 38 + with the requested name. 39 + 40 + EXAMPLE 41 + ------- 42 + [source,c] 43 + -- 44 + #include <event-parse.h> 45 + ... 46 + void get_htimer_info(struct tep_handle *tep, struct tep_record *record) 47 + { 48 + struct tep_format_field *field; 49 + struct tep_event *event; 50 + long long softexpires; 51 + int mode; 52 + int pid; 53 + 54 + event = tep_find_event_by_name(tep, "timer", "hrtimer_start"); 55 + 56 + field = tep_find_common_field(event, "common_pid"); 57 + if (field == NULL) { 58 + /* Cannot find "common_pid" field in the event */ 59 + } else { 60 + /* Get pid from the data record */ 61 + pid = tep_read_number(tep, record->data + field->offset, 62 + field->size); 63 + } 64 + 65 + field = tep_find_field(event, "softexpires"); 66 + if (field == NULL) { 67 + /* Cannot find "softexpires" event specific field in the event */ 68 + } else { 69 + /* Get softexpires parameter from the data record */ 70 + softexpires = tep_read_number(tep, record->data + field->offset, 71 + field->size); 72 + } 73 + 74 + field = tep_find_any_field(event, "mode"); 75 + if (field == NULL) { 76 + /* Cannot find "mode" field in the event */ 77 + } else 78 + { 79 + /* Get mode parameter from the data record */ 80 + mode = tep_read_number(tep, record->data + field->offset, 81 + field->size); 82 + } 83 + } 84 + ... 85 + -- 86 + 87 + FILES 88 + ----- 89 + [verse] 90 + -- 91 + *event-parse.h* 92 + Header file to include in order to have access to the library APIs. 93 + *-ltraceevent* 94 + Linker switch to add when building a program that uses the library. 95 + -- 96 + 97 + SEE ALSO 98 + -------- 99 + _libtraceevent(3)_, _trace-cmd(1)_ 100 + 101 + AUTHOR 102 + ------ 103 + [verse] 104 + -- 105 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 106 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 107 + -- 108 + REPORTING BUGS 109 + -------------- 110 + Report bugs to <linux-trace-devel@vger.kernel.org> 111 + 112 + LICENSE 113 + ------- 114 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 115 + 116 + RESOURCES 117 + --------- 118 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+122
tools/lib/traceevent/Documentation/libtraceevent-field_get_val.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_get_any_field_val, tep_get_common_field_val, tep_get_field_val, 7 + tep_get_field_raw - Get value of a field. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + *#include <trace-seq.h>* 15 + 16 + int *tep_get_any_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); 17 + int *tep_get_common_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); 18 + int *tep_get_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); 19 + void pass:[*]*tep_get_field_raw*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int pass:[*]_len_, int _err_); 20 + -- 21 + 22 + DESCRIPTION 23 + ----------- 24 + These functions can be used to find a field and retrieve its value. 25 + 26 + The _tep_get_any_field_val()_ function searches in the _record_ for a field 27 + with _name_, part of the _event_. If the field is found, its value is stored in 28 + _val_. If there is an error and _err_ is not zero, then an error string is 29 + written into _s_. 30 + 31 + The _tep_get_common_field_val()_ function does the same as 32 + _tep_get_any_field_val()_, but searches only in the common fields. This works 33 + for any event as all events include the common fields. 34 + 35 + The _tep_get_field_val()_ function does the same as _tep_get_any_field_val()_, 36 + but searches only in the event specific fields. 37 + 38 + The _tep_get_field_raw()_ function searches in the _record_ for a field with 39 + _name_, part of the _event_. If the field is found, a pointer to where the field 40 + exists in the record's raw data is returned. The size of the data is stored in 41 + _len_. If there is an error and _err_ is not zero, then an error string is 42 + written into _s_. 43 + 44 + RETURN VALUE 45 + ------------ 46 + The _tep_get_any_field_val()_, _tep_get_common_field_val()_ and 47 + _tep_get_field_val()_ functions return 0 on success, or -1 in case of an error. 48 + 49 + The _tep_get_field_raw()_ function returns a pointer to field's raw data, and 50 + places the length of this data in _len_. In case of an error NULL is returned. 51 + 52 + EXAMPLE 53 + ------- 54 + [source,c] 55 + -- 56 + #include <event-parse.h> 57 + #include <trace-seq.h> 58 + ... 59 + struct tep_handle *tep = tep_alloc(); 60 + ... 61 + struct tep_event *event = tep_find_event_by_name(tep, "kvm", "kvm_exit"); 62 + ... 63 + void process_record(struct tep_record *record) 64 + { 65 + int len; 66 + char *comm; 67 + struct tep_event_format *event; 68 + unsigned long long val; 69 + 70 + event = tep_find_event_by_record(pevent, record); 71 + if (event != NULL) { 72 + if (tep_get_common_field_val(NULL, event, "common_type", 73 + record, &val, 0) == 0) { 74 + /* Got the value of common type field */ 75 + } 76 + if (tep_get_field_val(NULL, event, "pid", record, &val, 0) == 0) { 77 + /* Got the value of pid specific field */ 78 + } 79 + comm = tep_get_field_raw(NULL, event, "comm", record, &len, 0); 80 + if (comm != NULL) { 81 + /* Got a pointer to the comm event specific field */ 82 + } 83 + } 84 + } 85 + -- 86 + 87 + FILES 88 + ----- 89 + [verse] 90 + -- 91 + *event-parse.h* 92 + Header file to include in order to have access to the library APIs. 93 + *trace-seq.h* 94 + Header file to include in order to have access to trace sequences 95 + related APIs. Trace sequences are used to allow a function to call 96 + several other functions to create a string of data to use. 97 + *-ltraceevent* 98 + Linker switch to add when building a program that uses the library. 99 + -- 100 + 101 + SEE ALSO 102 + -------- 103 + _libtraceevent(3)_, _trace-cmd(1)_ 104 + 105 + AUTHOR 106 + ------ 107 + [verse] 108 + -- 109 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 110 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 111 + -- 112 + REPORTING BUGS 113 + -------------- 114 + Report bugs to <linux-trace-devel@vger.kernel.org> 115 + 116 + LICENSE 117 + ------- 118 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 119 + 120 + RESOURCES 121 + --------- 122 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+126
tools/lib/traceevent/Documentation/libtraceevent-field_print.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_print_field, tep_print_fields, tep_print_num_field, tep_print_func_field - 7 + Print the field content. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + *#include <trace-seq.h>* 15 + 16 + void *tep_print_field*(struct trace_seq pass:[*]_s_, void pass:[*]_data_, struct tep_format_field pass:[*]_field_); 17 + void *tep_print_fields*(struct trace_seq pass:[*]_s_, void pass:[*]_data_, int _size_, struct tep_event pass:[*]_event_); 18 + int *tep_print_num_field*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int _err_); 19 + int *tep_print_func_field*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int _err_); 20 + -- 21 + 22 + DESCRIPTION 23 + ----------- 24 + These functions print recorded field's data, according to the field's type. 25 + 26 + The _tep_print_field()_ function extracts from the recorded raw _data_ value of 27 + the _field_ and prints it into _s_, according to the field type. 28 + 29 + The _tep_print_fields()_ prints each field name followed by the record's field 30 + value according to the field's type: 31 + [verse] 32 + -- 33 + "field1_name=field1_value field2_name=field2_value ..." 34 + -- 35 + It iterates all fields of the _event_, and calls _tep_print_field()_ for each of 36 + them. 37 + 38 + The _tep_print_num_field()_ function prints a numeric field with given format 39 + string. A search is performed in the _event_ for a field with _name_. If such 40 + field is found, its value is extracted from the _record_ and is printed in the 41 + _s_, according to the given format string _fmt_. If the argument _err_ is 42 + non-zero, and an error occures - it is printed in the _s_. 43 + 44 + The _tep_print_func_field()_ function prints a function field with given format 45 + string. A search is performed in the _event_ for a field with _name_. If such 46 + field is found, its value is extracted from the _record_. The value is assumed 47 + to be a function address, and a search is perform to find the name of this 48 + function. The function name (if found) and its address are printed in the _s_, 49 + according to the given format string _fmt_. If the argument _err_ is non-zero, 50 + and an error occures - it is printed in _s_. 51 + 52 + RETURN VALUE 53 + ------------ 54 + The _tep_print_num_field()_ and _tep_print_func_field()_ functions return 1 55 + on success, -1 in case of an error or 0 if the print buffer _s_ is full. 56 + 57 + EXAMPLE 58 + ------- 59 + [source,c] 60 + -- 61 + #include <event-parse.h> 62 + #include <trace-seq.h> 63 + ... 64 + struct tep_handle *tep = tep_alloc(); 65 + ... 66 + struct trace_seq seq; 67 + trace_seq_init(&seq); 68 + struct tep_event *event = tep_find_event_by_name(tep, "timer", "hrtimer_start"); 69 + ... 70 + void process_record(struct tep_record *record) 71 + { 72 + struct tep_format_field *field_pid = tep_find_common_field(event, "common_pid"); 73 + 74 + trace_seq_reset(&seq); 75 + 76 + /* Print the value of "common_pid" */ 77 + tep_print_field(&seq, record->data, field_pid); 78 + 79 + /* Print all fields of the "hrtimer_start" event */ 80 + tep_print_fields(&seq, record->data, record->size, event); 81 + 82 + /* Print the value of "expires" field with custom format string */ 83 + tep_print_num_field(&seq, " timer expires in %llu ", event, "expires", record, 0); 84 + 85 + /* Print the address and the name of "function" field with custom format string */ 86 + tep_print_func_field(&seq, " timer function is %s ", event, "function", record, 0); 87 + } 88 + ... 89 + -- 90 + 91 + FILES 92 + ----- 93 + [verse] 94 + -- 95 + *event-parse.h* 96 + Header file to include in order to have access to the library APIs. 97 + *trace-seq.h* 98 + Header file to include in order to have access to trace sequences related APIs. 99 + Trace sequences are used to allow a function to call several other functions 100 + to create a string of data to use. 101 + *-ltraceevent* 102 + Linker switch to add when building a program that uses the library. 103 + -- 104 + 105 + SEE ALSO 106 + -------- 107 + _libtraceevent(3)_, _trace-cmd(1)_ 108 + 109 + AUTHOR 110 + ------ 111 + [verse] 112 + -- 113 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 114 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 115 + -- 116 + REPORTING BUGS 117 + -------------- 118 + Report bugs to <linux-trace-devel@vger.kernel.org> 119 + 120 + LICENSE 121 + ------- 122 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 123 + 124 + RESOURCES 125 + --------- 126 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+81
tools/lib/traceevent/Documentation/libtraceevent-field_read.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_read_number_field - Reads a number from raw data. 7 + 8 + SYNOPSIS 9 + -------- 10 + [verse] 11 + -- 12 + *#include <event-parse.h>* 13 + 14 + int *tep_read_number_field*(struct tep_format_field pass:[*]_field_, const void pass:[*]_data_, unsigned long long pass:[*]_value_); 15 + -- 16 + 17 + DESCRIPTION 18 + ----------- 19 + The _tep_read_number_field()_ function reads the value of the _field_ from the 20 + raw _data_ and stores it in the _value_. The function sets the _value_ according 21 + to the endianness of the raw data and the current machine and stores it in 22 + _value_. 23 + 24 + RETURN VALUE 25 + ------------ 26 + The _tep_read_number_field()_ function retunrs 0 in case of success, or -1 in 27 + case of an error. 28 + 29 + EXAMPLE 30 + ------- 31 + [source,c] 32 + -- 33 + #include <event-parse.h> 34 + ... 35 + struct tep_handle *tep = tep_alloc(); 36 + ... 37 + struct tep_event *event = tep_find_event_by_name(tep, "timer", "hrtimer_start"); 38 + ... 39 + void process_record(struct tep_record *record) 40 + { 41 + unsigned long long pid; 42 + struct tep_format_field *field_pid = tep_find_common_field(event, "common_pid"); 43 + 44 + if (tep_read_number_field(field_pid, record->data, &pid) != 0) { 45 + /* Failed to get "common_pid" value */ 46 + } 47 + } 48 + ... 49 + -- 50 + FILES 51 + ----- 52 + [verse] 53 + -- 54 + *event-parse.h* 55 + Header file to include in order to have access to the library APIs. 56 + *-ltraceevent* 57 + Linker switch to add when building a program that uses the library. 58 + -- 59 + 60 + SEE ALSO 61 + -------- 62 + _libtraceevent(3)_, _trace-cmd(1)_ 63 + 64 + AUTHOR 65 + ------ 66 + [verse] 67 + -- 68 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 69 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 70 + -- 71 + REPORTING BUGS 72 + -------------- 73 + Report bugs to <linux-trace-devel@vger.kernel.org> 74 + 75 + LICENSE 76 + ------- 77 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 78 + 79 + RESOURCES 80 + --------- 81 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+105
tools/lib/traceevent/Documentation/libtraceevent-fields.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_event_common_fields, tep_event_fields - Get a list of fields for an event. 7 + 8 + SYNOPSIS 9 + -------- 10 + [verse] 11 + -- 12 + *#include <event-parse.h>* 13 + 14 + struct tep_format_field pass:[*]pass:[*]*tep_event_common_fields*(struct tep_event pass:[*]_event_); 15 + struct tep_format_field pass:[*]pass:[*]*tep_event_fields*(struct tep_event pass:[*]_event_); 16 + -- 17 + 18 + DESCRIPTION 19 + ----------- 20 + The _tep_event_common_fields()_ function returns an array of pointers to common 21 + fields for the _event_. The array is allocated in the function and must be freed 22 + by free(). The last element of the array is NULL. 23 + 24 + The _tep_event_fields()_ function returns an array of pointers to event specific 25 + fields for the _event_. The array is allocated in the function and must be freed 26 + by free(). The last element of the array is NULL. 27 + 28 + RETURN VALUE 29 + ------------ 30 + Both _tep_event_common_fields()_ and _tep_event_fields()_ functions return 31 + an array of pointers to tep_format_field structures in case of success, or 32 + NULL in case of an error. 33 + 34 + EXAMPLE 35 + ------- 36 + [source,c] 37 + -- 38 + #include <event-parse.h> 39 + ... 40 + struct tep_handle *tep = tep_alloc(); 41 + ... 42 + int i; 43 + struct tep_format_field **fields; 44 + struct tep_event *event = tep_find_event_by_name(tep, "kvm", "kvm_exit"); 45 + if (event != NULL) { 46 + fields = tep_event_common_fields(event); 47 + if (fields != NULL) { 48 + i = 0; 49 + while (fields[i]) { 50 + /* 51 + walk through the list of the common fields 52 + of the kvm_exit event 53 + */ 54 + i++; 55 + } 56 + free(fields); 57 + } 58 + fields = tep_event_fields(event); 59 + if (fields != NULL) { 60 + i = 0; 61 + while (fields[i]) { 62 + /* 63 + walk through the list of the event specific 64 + fields of the kvm_exit event 65 + */ 66 + i++; 67 + } 68 + free(fields); 69 + } 70 + } 71 + ... 72 + -- 73 + 74 + FILES 75 + ----- 76 + [verse] 77 + -- 78 + *event-parse.h* 79 + Header file to include in order to have access to the library APIs. 80 + *-ltraceevent* 81 + Linker switch to add when building a program that uses the library. 82 + -- 83 + 84 + SEE ALSO 85 + -------- 86 + _libtraceevent(3)_, _trace-cmd(1)_ 87 + 88 + AUTHOR 89 + ------ 90 + [verse] 91 + -- 92 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 93 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 94 + -- 95 + REPORTING BUGS 96 + -------------- 97 + Report bugs to <linux-trace-devel@vger.kernel.org> 98 + 99 + LICENSE 100 + ------- 101 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 102 + 103 + RESOURCES 104 + --------- 105 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+91
tools/lib/traceevent/Documentation/libtraceevent-file_endian.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_is_file_bigendian, tep_set_file_bigendian - Get / set the endianness of the 7 + raw data being accessed by the tep handler. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + enum *tep_endian* { 16 + TEP_LITTLE_ENDIAN = 0, 17 + TEP_BIG_ENDIAN 18 + }; 19 + 20 + bool *tep_is_file_bigendian*(struct tep_handle pass:[*]_tep_); 21 + void *tep_set_file_bigendian*(struct tep_handle pass:[*]_tep_, enum tep_endian _endian_); 22 + 23 + -- 24 + DESCRIPTION 25 + ----------- 26 + The _tep_is_file_bigendian()_ function gets the endianness of the raw data, 27 + being accessed by the tep handler. The _tep_ argument is trace event parser 28 + context. 29 + 30 + The _tep_set_file_bigendian()_ function sets the endianness of raw data being 31 + accessed by the tep handler. The _tep_ argument is trace event parser context. 32 + [verse] 33 + -- 34 + The _endian_ argument is the endianness: 35 + _TEP_LITTLE_ENDIAN_ - the raw data is in little endian format, 36 + _TEP_BIG_ENDIAN_ - the raw data is in big endian format. 37 + -- 38 + RETURN VALUE 39 + ------------ 40 + The _tep_is_file_bigendian()_ function returns true if the data is in bigendian 41 + format, false otherwise. 42 + 43 + EXAMPLE 44 + ------- 45 + [source,c] 46 + -- 47 + #include <event-parse.h> 48 + ... 49 + struct tep_handle *tep = tep_alloc(); 50 + ... 51 + tep_set_file_bigendian(tep, TEP_LITTLE_ENDIAN); 52 + ... 53 + if (tep_is_file_bigendian(tep)) { 54 + /* The raw data is in big endian */ 55 + } else { 56 + /* The raw data is in little endian */ 57 + } 58 + -- 59 + 60 + FILES 61 + ----- 62 + [verse] 63 + -- 64 + *event-parse.h* 65 + Header file to include in order to have access to the library APIs. 66 + *-ltraceevent* 67 + Linker switch to add when building a program that uses the library. 68 + -- 69 + 70 + SEE ALSO 71 + -------- 72 + _libtraceevent(3)_, _trace-cmd(1)_ 73 + 74 + AUTHOR 75 + ------ 76 + [verse] 77 + -- 78 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 79 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 80 + -- 81 + REPORTING BUGS 82 + -------------- 83 + Report bugs to <linux-trace-devel@vger.kernel.org> 84 + 85 + LICENSE 86 + ------- 87 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 88 + 89 + RESOURCES 90 + --------- 91 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+209
tools/lib/traceevent/Documentation/libtraceevent-filter.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_filter_alloc, tep_filter_free, tep_filter_reset, tep_filter_make_string, 7 + tep_filter_copy, tep_filter_compare, tep_filter_match, tep_event_filtered, 8 + tep_filter_remove_event, tep_filter_strerror, tep_filter_add_filter_str - 9 + Event filter related APIs. 10 + 11 + SYNOPSIS 12 + -------- 13 + [verse] 14 + -- 15 + *#include <event-parse.h>* 16 + 17 + struct tep_event_filter pass:[*]*tep_filter_alloc*(struct tep_handle pass:[*]_tep_); 18 + void *tep_filter_free*(struct tep_event_filter pass:[*]_filter_); 19 + void *tep_filter_reset*(struct tep_event_filter pass:[*]_filter_); 20 + enum tep_errno *tep_filter_add_filter_str*(struct tep_event_filter pass:[*]_filter_, const char pass:[*]_filter_str_); 21 + int *tep_event_filtered*(struct tep_event_filter pass:[*]_filter_, int _event_id_); 22 + int *tep_filter_remove_event*(struct tep_event_filter pass:[*]_filter_, int _event_id_); 23 + enum tep_errno *tep_filter_match*(struct tep_event_filter pass:[*]_filter_, struct tep_record pass:[*]_record_); 24 + int *tep_filter_copy*(struct tep_event_filter pass:[*]_dest_, struct tep_event_filter pass:[*]_source_); 25 + int *tep_filter_compare*(struct tep_event_filter pass:[*]_filter1_, struct tep_event_filter pass:[*]_filter2_); 26 + char pass:[*]*tep_filter_make_string*(struct tep_event_filter pass:[*]_filter_, int _event_id_); 27 + int *tep_filter_strerror*(struct tep_event_filter pass:[*]_filter_, enum tep_errno _err_, char pass:[*]buf, size_t _buflen_); 28 + -- 29 + 30 + DESCRIPTION 31 + ----------- 32 + Filters can be attached to traced events. They can be used to filter out various 33 + events when outputting them. Each event can be filtered based on its parameters, 34 + described in the event's format file. This set of functions can be used to 35 + create, delete, modify and attach event filters. 36 + 37 + The _tep_filter_alloc()_ function creates a new event filter. The _tep_ argument 38 + is the trace event parser context. 39 + 40 + The _tep_filter_free()_ function frees an event filter and all resources that it 41 + had used. 42 + 43 + The _tep_filter_reset()_ function removes all rules from an event filter and 44 + resets it. 45 + 46 + The _tep_filter_add_filter_str()_ function adds a new rule to the _filter_. The 47 + _filter_str_ argument is the filter string, that contains the rule. 48 + 49 + The _tep_event_filtered()_ function checks if the event with _event_id_ has 50 + _filter_. 51 + 52 + The _tep_filter_remove_event()_ function removes a _filter_ for an event with 53 + _event_id_. 54 + 55 + The _tep_filter_match()_ function tests if a _record_ matches given _filter_. 56 + 57 + The _tep_filter_copy()_ function copies a _source_ filter into a _dest_ filter. 58 + 59 + The _tep_filter_compare()_ function compares two filers - _filter1_ and _filter2_. 60 + 61 + The _tep_filter_make_string()_ function constructs a string, displaying 62 + the _filter_ contents for given _event_id_. 63 + 64 + The _tep_filter_strerror()_ function copies the _filter_ error buffer into the 65 + given _buf_ with the size _buflen_. If the error buffer is empty, in the _buf_ 66 + is copied a string, describing the error _err_. 67 + 68 + RETURN VALUE 69 + ------------ 70 + The _tep_filter_alloc()_ function returns a pointer to the newly created event 71 + filter, or NULL in case of an error. 72 + 73 + The _tep_filter_add_filter_str()_ function returns 0 if the rule was 74 + successfully added or a negative error code. Use _tep_filter_strerror()_ to see 75 + actual error message in case of an error. 76 + 77 + The _tep_event_filtered()_ function returns 1 if the filter is found for given 78 + event, or 0 otherwise. 79 + 80 + The _tep_filter_remove_event()_ function returns 1 if the vent was removed, or 81 + 0 if the event was not found. 82 + 83 + The _tep_filter_match()_ function returns _tep_errno_, according to the result: 84 + [verse] 85 + -- 86 + _pass:[TEP_ERRNO__FILTER_MATCH]_ - filter found for event, the record matches. 87 + _pass:[TEP_ERRNO__FILTER_MISS]_ - filter found for event, the record does not match. 88 + _pass:[TEP_ERRNO__FILTER_NOT_FOUND]_ - no filter found for record's event. 89 + _pass:[TEP_ERRNO__NO_FILTER]_ - no rules in the filter. 90 + -- 91 + or any other _tep_errno_, if an error occurred during the test. 92 + 93 + The _tep_filter_copy()_ function returns 0 on success or -1 if not all rules 94 + were copied. 95 + 96 + The _tep_filter_compare()_ function returns 1 if the two filters hold the same 97 + content, or 0 if they do not. 98 + 99 + The _tep_filter_make_string()_ function returns a string, which must be freed 100 + with free(), or NULL in case of an error. 101 + 102 + The _tep_filter_strerror()_ function returns 0 if message was filled 103 + successfully, or -1 in case of an error. 104 + 105 + EXAMPLE 106 + ------- 107 + [source,c] 108 + -- 109 + #include <event-parse.h> 110 + ... 111 + struct tep_handle *tep = tep_alloc(); 112 + ... 113 + char errstr[200]; 114 + int ret; 115 + 116 + struct tep_event_filter *filter = tep_filter_alloc(tep); 117 + struct tep_event_filter *filter1 = tep_filter_alloc(tep); 118 + ret = tep_filter_add_filter_str(filter, "sched/sched_wakeup:target_cpu==1"); 119 + if(ret < 0) { 120 + tep_filter_strerror(filter, ret, errstr, sizeof(errstr)); 121 + /* Failed to add a new rule to the filter, the error string is in errstr */ 122 + } 123 + if (tep_filter_copy(filter1, filter) != 0) { 124 + /* Failed to copy filter in filter1 */ 125 + } 126 + ... 127 + if (tep_filter_compare(filter, filter1) != 1) { 128 + /* Both filters are different */ 129 + } 130 + ... 131 + void process_record(struct tep_handle *tep, struct tep_record *record) 132 + { 133 + struct tep_event *event; 134 + char *fstring; 135 + 136 + event = tep_find_event_by_record(tep, record); 137 + 138 + if (tep_event_filtered(filter, event->id) == 1) { 139 + /* The event has filter */ 140 + fstring = tep_filter_make_string(filter, event->id); 141 + if (fstring != NULL) { 142 + /* The filter for the event is in fstring */ 143 + free(fstring); 144 + } 145 + } 146 + 147 + switch (tep_filter_match(filter, record)) { 148 + case TEP_ERRNO__FILTER_MATCH: 149 + /* The filter matches the record */ 150 + break; 151 + case TEP_ERRNO__FILTER_MISS: 152 + /* The filter does not match the record */ 153 + break; 154 + case TEP_ERRNO__FILTER_NOT_FOUND: 155 + /* No filter found for record's event */ 156 + break; 157 + case TEP_ERRNO__NO_FILTER: 158 + /* There are no rules in the filter */ 159 + break 160 + default: 161 + /* An error occurred during the test */ 162 + break; 163 + } 164 + 165 + if (tep_filter_remove_event(filter, event->id) == 1) { 166 + /* The event was removed from the filter */ 167 + } 168 + } 169 + 170 + ... 171 + tep_filter_reset(filter); 172 + ... 173 + tep_filter_free(filter); 174 + tep_filter_free(filter1); 175 + ... 176 + -- 177 + 178 + FILES 179 + ----- 180 + [verse] 181 + -- 182 + *event-parse.h* 183 + Header file to include in order to have access to the library APIs. 184 + *-ltraceevent* 185 + Linker switch to add when building a program that uses the library. 186 + -- 187 + 188 + SEE ALSO 189 + -------- 190 + _libtraceevent(3)_, _trace-cmd(1)_ 191 + 192 + AUTHOR 193 + ------ 194 + [verse] 195 + -- 196 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 197 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 198 + -- 199 + REPORTING BUGS 200 + -------------- 201 + Report bugs to <linux-trace-devel@vger.kernel.org> 202 + 203 + LICENSE 204 + ------- 205 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 206 + 207 + RESOURCES 208 + --------- 209 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+183
tools/lib/traceevent/Documentation/libtraceevent-func_apis.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_find_function, tep_find_function_address, tep_set_function_resolver, 7 + tep_reset_function_resolver, tep_register_function, tep_register_print_string - 8 + function related tep APIs 9 + 10 + SYNOPSIS 11 + -------- 12 + [verse] 13 + -- 14 + *#include <event-parse.h>* 15 + 16 + typedef char pass:[*](*tep_func_resolver_t*)(void pass:[*]_priv_, unsigned long long pass:[*]_addrp_, char pass:[**]_modp_); 17 + int *tep_set_function_resolver*(struct tep_handle pass:[*]_tep_, tep_func_resolver_t pass:[*]_func_, void pass:[*]_priv_); 18 + void *tep_reset_function_resolver*(struct tep_handle pass:[*]_tep_); 19 + const char pass:[*]*tep_find_function*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); 20 + unsigned long long *tep_find_function_address*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); 21 + int *tep_register_function*(struct tep_handle pass:[*]_tep_, char pass:[*]_name_, unsigned long long _addr_, char pass:[*]_mod_); 22 + int *tep_register_print_string*(struct tep_handle pass:[*]_tep_, const char pass:[*]_fmt_, unsigned long long _addr_); 23 + -- 24 + 25 + DESCRIPTION 26 + ----------- 27 + Some tools may have already a way to resolve the kernel functions. These APIs 28 + allow them to keep using it instead of duplicating all the entries inside. 29 + 30 + The _tep_func_resolver_t_ type is the prototype of the alternative kernel 31 + functions resolver. This function receives a pointer to its custom context 32 + (set with the _tep_set_function_resolver()_ call ) and the address of a kernel 33 + function, which has to be resolved. In case of success, it should return 34 + the name of the function and its module (if any) in _modp_. 35 + 36 + The _tep_set_function_resolver()_ function registers _func_ as an alternative 37 + kernel functions resolver. The _tep_ argument is trace event parser context. 38 + The _priv_ argument is a custom context of the _func_ function. The function 39 + resolver is used by the APIs _tep_find_function()_, 40 + _tep_find_function_address()_, and _tep_print_func_field()_ to resolve 41 + a function address to a function name. 42 + 43 + The _tep_reset_function_resolver()_ function resets the kernel functions 44 + resolver to the default function. The _tep_ argument is trace event parser 45 + context. 46 + 47 + 48 + These APIs can be used to find function name and start address, by given 49 + address. The given address does not have to be exact, it will select 50 + the function that would contain it. 51 + 52 + The _tep_find_function()_ function returns the function name, which contains the 53 + given address _addr_. The _tep_ argument is the trace event parser context. 54 + 55 + The _tep_find_function_address()_ function returns the function start address, 56 + by given address _addr_. The _addr_ does not have to be exact, it will select 57 + the function that would contain it. The _tep_ argument is the trace event 58 + parser context. 59 + 60 + The _tep_register_function()_ function registers a function name mapped to an 61 + address and (optional) module. This mapping is used in case the function tracer 62 + or events have "%pF" or "%pS" parameter in its format string. It is common to 63 + pass in the kallsyms function names with their corresponding addresses with this 64 + function. The _tep_ argument is the trace event parser context. The _name_ is 65 + the name of the function, the string is copied internally. The _addr_ is 66 + the start address of the function. The _mod_ is the kernel module 67 + the function may be in (NULL for none). 68 + 69 + The _tep_register_print_string()_ function registers a string by the address 70 + it was stored in the kernel. Some strings internal to the kernel with static 71 + address are passed to certain events. The "%s" in the event's format field 72 + which has an address needs to know what string would be at that address. The 73 + tep_register_print_string() supplies the parsing with the mapping between kernel 74 + addresses and those strings. The _tep_ argument is the trace event parser 75 + context. The _fmt_ is the string to register, it is copied internally. 76 + The _addr_ is the address the string was located at. 77 + 78 + 79 + RETURN VALUE 80 + ------------ 81 + The _tep_set_function_resolver()_ function returns 0 in case of success, or -1 82 + in case of an error. 83 + 84 + The _tep_find_function()_ function returns the function name, or NULL in case 85 + it cannot be found. 86 + 87 + The _tep_find_function_address()_ function returns the function start address, 88 + or 0 in case it cannot be found. 89 + 90 + The _tep_register_function()_ function returns 0 in case of success. In case of 91 + an error -1 is returned, and errno is set to the appropriate error number. 92 + 93 + The _tep_register_print_string()_ function returns 0 in case of success. In case 94 + of an error -1 is returned, and errno is set to the appropriate error number. 95 + 96 + EXAMPLE 97 + ------- 98 + [source,c] 99 + -- 100 + #include <event-parse.h> 101 + ... 102 + struct tep_handle *tep = tep_alloc(); 103 + ... 104 + char *my_resolve_kernel_addr(void *context, 105 + unsigned long long *addrp, char **modp) 106 + { 107 + struct db *function_database = context; 108 + struct symbol *sym = sql_lookup(function_database, *addrp); 109 + 110 + if (!sym) 111 + return NULL; 112 + 113 + *modp = sym->module_name; 114 + return sym->name; 115 + } 116 + 117 + void show_function( unsigned long long addr) 118 + { 119 + unsigned long long fstart; 120 + const char *fname; 121 + 122 + if (tep_set_function_resolver(tep, my_resolve_kernel_addr, 123 + function_database) != 0) { 124 + /* failed to register my_resolve_kernel_addr */ 125 + } 126 + 127 + /* These APIs use my_resolve_kernel_addr() to resolve the addr */ 128 + fname = tep_find_function(tep, addr); 129 + fstart = tep_find_function_address(tep, addr); 130 + 131 + /* 132 + addr is in function named fname, starting at fstart address, 133 + at offset (addr - fstart) 134 + */ 135 + 136 + tep_reset_function_resolver(tep); 137 + 138 + } 139 + ... 140 + if (tep_register_function(tep, "kvm_exit", 141 + (unsigned long long) 0x12345678, "kvm") != 0) { 142 + /* Failed to register kvm_exit address mapping */ 143 + } 144 + ... 145 + if (tep_register_print_string(tep, "print string", 146 + (unsigned long long) 0x87654321, NULL) != 0) { 147 + /* Failed to register "print string" address mapping */ 148 + } 149 + ... 150 + -- 151 + 152 + FILES 153 + ----- 154 + [verse] 155 + -- 156 + *event-parse.h* 157 + Header file to include in order to have access to the library APIs. 158 + *-ltraceevent* 159 + Linker switch to add when building a program that uses the library. 160 + -- 161 + 162 + SEE ALSO 163 + -------- 164 + _libtraceevent(3)_, _trace-cmd(1)_ 165 + 166 + AUTHOR 167 + ------ 168 + [verse] 169 + -- 170 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 171 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 172 + -- 173 + REPORTING BUGS 174 + -------------- 175 + Report bugs to <linux-trace-devel@vger.kernel.org> 176 + 177 + LICENSE 178 + ------- 179 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 180 + 181 + RESOURCES 182 + --------- 183 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+88
tools/lib/traceevent/Documentation/libtraceevent-func_find.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_find_function,tep_find_function_address - Find function name / start address. 7 + 8 + SYNOPSIS 9 + -------- 10 + [verse] 11 + -- 12 + *#include <event-parse.h>* 13 + 14 + const char pass:[*]*tep_find_function*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); 15 + unsigned long long *tep_find_function_address*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); 16 + -- 17 + 18 + DESCRIPTION 19 + ----------- 20 + These functions can be used to find function name and start address, by given 21 + address. The given address does not have to be exact, it will select the function 22 + that would contain it. 23 + 24 + The _tep_find_function()_ function returns the function name, which contains the 25 + given address _addr_. The _tep_ argument is the trace event parser context. 26 + 27 + The _tep_find_function_address()_ function returns the function start address, 28 + by given address _addr_. The _addr_ does not have to be exact, it will select the 29 + function that would contain it. The _tep_ argument is the trace event parser context. 30 + 31 + RETURN VALUE 32 + ------------ 33 + The _tep_find_function()_ function returns the function name, or NULL in case 34 + it cannot be found. 35 + 36 + The _tep_find_function_address()_ function returns the function start address, 37 + or 0 in case it cannot be found. 38 + 39 + EXAMPLE 40 + ------- 41 + [source,c] 42 + -- 43 + #include <event-parse.h> 44 + ... 45 + struct tep_handle *tep = tep_alloc(); 46 + ... 47 + void show_function( unsigned long long addr) 48 + { 49 + const char *fname = tep_find_function(tep, addr); 50 + unsigned long long fstart = tep_find_function_address(tep, addr); 51 + 52 + /* addr is in function named fname, starting at fstart address, at offset (addr - fstart) */ 53 + } 54 + ... 55 + -- 56 + 57 + FILES 58 + ----- 59 + [verse] 60 + -- 61 + *event-parse.h* 62 + Header file to include in order to have access to the library APIs. 63 + *-ltraceevent* 64 + Linker switch to add when building a program that uses the library. 65 + -- 66 + 67 + SEE ALSO 68 + -------- 69 + _libtraceevent(3)_, _trace-cmd(1)_ 70 + 71 + AUTHOR 72 + ------ 73 + [verse] 74 + -- 75 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 76 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 77 + -- 78 + REPORTING BUGS 79 + -------------- 80 + Report bugs to <linux-trace-devel@vger.kernel.org> 81 + 82 + LICENSE 83 + ------- 84 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 85 + 86 + RESOURCES 87 + --------- 88 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+101
tools/lib/traceevent/Documentation/libtraceevent-handle.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_alloc, tep_free,tep_ref, tep_unref,tep_ref_get - Create, destroy, manage 7 + references of trace event parser context. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + struct tep_handle pass:[*]*tep_alloc*(void); 16 + void *tep_free*(struct tep_handle pass:[*]_tep_); 17 + void *tep_ref*(struct tep_handle pass:[*]_tep_); 18 + void *tep_unref*(struct tep_handle pass:[*]_tep_); 19 + int *tep_ref_get*(struct tep_handle pass:[*]_tep_); 20 + -- 21 + 22 + DESCRIPTION 23 + ----------- 24 + These are the main functions to create and destroy tep_handle - the main 25 + structure, representing the trace event parser context. This context is used as 26 + the input parameter of most library APIs. 27 + 28 + The _tep_alloc()_ function allocates and initializes the tep context. 29 + 30 + The _tep_free()_ function will decrement the reference of the _tep_ handler. 31 + When there is no more references, then it will free the handler, as well 32 + as clean up all its resources that it had used. The argument _tep_ is 33 + the pointer to the trace event parser context. 34 + 35 + The _tep_ref()_ function adds a reference to the _tep_ handler. 36 + 37 + The _tep_unref()_ function removes a reference from the _tep_ handler. When 38 + the last reference is removed, the _tep_ is destroyed, and all resources that 39 + it had used are cleaned up. 40 + 41 + The _tep_ref_get()_ functions gets the current references of the _tep_ handler. 42 + 43 + RETURN VALUE 44 + ------------ 45 + _tep_alloc()_ returns a pointer to a newly created tep_handle structure. 46 + NULL is returned in case there is not enough free memory to allocate it. 47 + 48 + _tep_ref_get()_ returns the current references of _tep_. 49 + If _tep_ is NULL, 0 is returned. 50 + 51 + EXAMPLE 52 + ------- 53 + [source,c] 54 + -- 55 + #include <event-parse.h> 56 + 57 + ... 58 + struct tep_handle *tep = tep_alloc(); 59 + ... 60 + int ref = tep_ref_get(tep); 61 + tep_ref(tep); 62 + if ( (ref+1) != tep_ref_get(tep)) { 63 + /* Something wrong happened, the counter is not incremented by 1 */ 64 + } 65 + tep_unref(tep); 66 + ... 67 + tep_free(tep); 68 + ... 69 + -- 70 + FILES 71 + ----- 72 + [verse] 73 + -- 74 + *event-parse.h* 75 + Header file to include in order to have access to the library APIs. 76 + *-ltraceevent* 77 + Linker switch to add when building a program that uses the library. 78 + -- 79 + 80 + SEE ALSO 81 + -------- 82 + _libtraceevent(3)_, _trace-cmd(1)_ 83 + 84 + AUTHOR 85 + ------ 86 + [verse] 87 + -- 88 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 89 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 90 + -- 91 + REPORTING BUGS 92 + -------------- 93 + Report bugs to <linux-trace-devel@vger.kernel.org> 94 + 95 + LICENSE 96 + ------- 97 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 98 + 99 + RESOURCES 100 + --------- 101 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+102
tools/lib/traceevent/Documentation/libtraceevent-header_page.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_get_header_page_size, tep_get_header_timestamp_size, tep_is_old_format - 7 + Get the data stored in the header page, in kernel context. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + int *tep_get_header_page_size*(struct tep_handle pass:[*]_tep_); 16 + int *tep_get_header_timestamp_size*(struct tep_handle pass:[*]_tep_); 17 + bool *tep_is_old_format*(struct tep_handle pass:[*]_tep_); 18 + -- 19 + DESCRIPTION 20 + ----------- 21 + These functions retrieve information from kernel context, stored in tracefs 22 + events/header_page. Old kernels do not have header page info, so default values 23 + from user space context are used. 24 + 25 + The _tep_get_header_page_size()_ function returns the size of a long integer, 26 + in kernel context. The _tep_ argument is trace event parser context. 27 + This information is retrieved from tracefs events/header_page, "commit" field. 28 + 29 + The _tep_get_header_timestamp_size()_ function returns the size of timestamps, 30 + in kernel context. The _tep_ argument is trace event parser context. This 31 + information is retrieved from tracefs events/header_page, "timestamp" field. 32 + 33 + The _tep_is_old_format()_ function returns true if the kernel predates 34 + the addition of events/header_page, otherwise it returns false. 35 + 36 + RETURN VALUE 37 + ------------ 38 + The _tep_get_header_page_size()_ function returns the size of a long integer, 39 + in bytes. 40 + 41 + The _tep_get_header_timestamp_size()_ function returns the size of timestamps, 42 + in bytes. 43 + 44 + The _tep_is_old_format()_ function returns true, if an old kernel is used to 45 + generate the tracing data, which has no event/header_page. If the kernel is new, 46 + or _tep_ is NULL, false is returned. 47 + 48 + EXAMPLE 49 + ------- 50 + [source,c] 51 + -- 52 + #include <event-parse.h> 53 + ... 54 + struct tep_handle *tep = tep_alloc(); 55 + ... 56 + int longsize; 57 + int timesize; 58 + bool old; 59 + 60 + longsize = tep_get_header_page_size(tep); 61 + timesize = tep_get_header_timestamp_size(tep); 62 + old = tep_is_old_format(tep); 63 + 64 + printf ("%s kernel is used to generate the tracing data.\n", 65 + old?"Old":"New"); 66 + printf("The size of a long integer is %d bytes.\n", longsize); 67 + printf("The timestamps size is %d bytes.\n", timesize); 68 + ... 69 + -- 70 + 71 + FILES 72 + ----- 73 + [verse] 74 + -- 75 + *event-parse.h* 76 + Header file to include in order to have access to the library APIs. 77 + *-ltraceevent* 78 + Linker switch to add when building a program that uses the library. 79 + -- 80 + 81 + SEE ALSO 82 + -------- 83 + _libtraceevent(3)_, _trace-cmd(1)_ 84 + 85 + AUTHOR 86 + ------ 87 + [verse] 88 + -- 89 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 90 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 91 + -- 92 + REPORTING BUGS 93 + -------------- 94 + Report bugs to <linux-trace-devel@vger.kernel.org> 95 + 96 + LICENSE 97 + ------- 98 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 99 + 100 + RESOURCES 101 + --------- 102 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+104
tools/lib/traceevent/Documentation/libtraceevent-host_endian.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_is_bigendian, tep_is_local_bigendian, tep_set_local_bigendian - Get / set 7 + the endianness of the local machine. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + enum *tep_endian* { 16 + TEP_LITTLE_ENDIAN = 0, 17 + TEP_BIG_ENDIAN 18 + }; 19 + 20 + int *tep_is_bigendian*(void); 21 + bool *tep_is_local_bigendian*(struct tep_handle pass:[*]_tep_); 22 + void *tep_set_local_bigendian*(struct tep_handle pass:[*]_tep_, enum tep_endian _endian_); 23 + -- 24 + 25 + DESCRIPTION 26 + ----------- 27 + 28 + The _tep_is_bigendian()_ gets the endianness of the machine, executing 29 + the function. 30 + 31 + The _tep_is_local_bigendian()_ function gets the endianness of the local 32 + machine, saved in the _tep_ handler. The _tep_ argument is the trace event 33 + parser context. This API is a bit faster than _tep_is_bigendian()_, as it 34 + returns cached endianness of the local machine instead of checking it each time. 35 + 36 + The _tep_set_local_bigendian()_ function sets the endianness of the local 37 + machine in the _tep_ handler. The _tep_ argument is trace event parser context. 38 + The _endian_ argument is the endianness: 39 + [verse] 40 + -- 41 + _TEP_LITTLE_ENDIAN_ - the machine is little endian, 42 + _TEP_BIG_ENDIAN_ - the machine is big endian. 43 + -- 44 + 45 + RETURN VALUE 46 + ------------ 47 + The _tep_is_bigendian()_ function returns non zero if the endianness of the 48 + machine, executing the code, is big endian and zero otherwise. 49 + 50 + The _tep_is_local_bigendian()_ function returns true, if the endianness of the 51 + local machine, saved in the _tep_ handler, is big endian, or false otherwise. 52 + 53 + EXAMPLE 54 + ------- 55 + [source,c] 56 + -- 57 + #include <event-parse.h> 58 + ... 59 + struct tep_handle *tep = tep_alloc(); 60 + ... 61 + if (tep_is_bigendian()) 62 + tep_set_local_bigendian(tep, TEP_BIG_ENDIAN); 63 + else 64 + tep_set_local_bigendian(tep, TEP_LITTLE_ENDIAN); 65 + ... 66 + if (tep_is_local_bigendian(tep)) 67 + printf("This machine you are running on is bigendian\n"); 68 + else 69 + printf("This machine you are running on is little endian\n"); 70 + 71 + -- 72 + 73 + FILES 74 + ----- 75 + [verse] 76 + -- 77 + *event-parse.h* 78 + Header file to include in order to have access to the library APIs. 79 + *-ltraceevent* 80 + Linker switch to add when building a program that uses the library. 81 + -- 82 + 83 + SEE ALSO 84 + -------- 85 + _libtraceevent(3)_, _trace-cmd(1)_ 86 + 87 + AUTHOR 88 + ------ 89 + [verse] 90 + -- 91 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 92 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 93 + -- 94 + REPORTING BUGS 95 + -------------- 96 + Report bugs to <linux-trace-devel@vger.kernel.org> 97 + 98 + LICENSE 99 + ------- 100 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 101 + 102 + RESOURCES 103 + --------- 104 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+78
tools/lib/traceevent/Documentation/libtraceevent-long_size.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_get_long_size, tep_set_long_size - Get / set the size of a long integer on 7 + the machine, where the trace is generated, in bytes 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + int *tep_get_long_size*(strucqt tep_handle pass:[*]_tep_); 16 + void *tep_set_long_size*(struct tep_handle pass:[*]_tep_, int _long_size_); 17 + -- 18 + 19 + DESCRIPTION 20 + ----------- 21 + The _tep_get_long_size()_ function returns the size of a long integer on the machine, 22 + where the trace is generated. The _tep_ argument is trace event parser context. 23 + 24 + The _tep_set_long_size()_ function sets the size of a long integer on the machine, 25 + where the trace is generated. The _tep_ argument is trace event parser context. 26 + The _long_size_ is the size of a long integer, in bytes. 27 + 28 + RETURN VALUE 29 + ------------ 30 + The _tep_get_long_size()_ function returns the size of a long integer on the machine, 31 + where the trace is generated, in bytes. 32 + 33 + EXAMPLE 34 + ------- 35 + [source,c] 36 + -- 37 + #include <event-parse.h> 38 + ... 39 + struct tep_handle *tep = tep_alloc(); 40 + ... 41 + tep_set_long_size(tep, 4); 42 + ... 43 + int long_size = tep_get_long_size(tep); 44 + ... 45 + -- 46 + 47 + FILES 48 + ----- 49 + [verse] 50 + -- 51 + *event-parse.h* 52 + Header file to include in order to have access to the library APIs. 53 + *-ltraceevent* 54 + Linker switch to add when building a program that uses the library. 55 + -- 56 + 57 + SEE ALSO 58 + -------- 59 + _libtraceevent(3)_, _trace-cmd(1)_ 60 + 61 + AUTHOR 62 + ------ 63 + [verse] 64 + -- 65 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 66 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 67 + -- 68 + REPORTING BUGS 69 + -------------- 70 + Report bugs to <linux-trace-devel@vger.kernel.org> 71 + 72 + LICENSE 73 + ------- 74 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 75 + 76 + RESOURCES 77 + --------- 78 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+82
tools/lib/traceevent/Documentation/libtraceevent-page_size.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_get_page_size, tep_set_page_size - Get / set the size of a memory page on 7 + the machine, where the trace is generated 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + int *tep_get_page_size*(struct tep_handle pass:[*]_tep_); 16 + void *tep_set_page_size*(struct tep_handle pass:[*]_tep_, int _page_size_); 17 + -- 18 + 19 + DESCRIPTION 20 + ----------- 21 + The _tep_get_page_size()_ function returns the size of a memory page on 22 + the machine, where the trace is generated. The _tep_ argument is trace 23 + event parser context. 24 + 25 + The _tep_set_page_size()_ function stores in the _tep_ context the size of a 26 + memory page on the machine, where the trace is generated. 27 + The _tep_ argument is trace event parser context. 28 + The _page_size_ argument is the size of a memory page, in bytes. 29 + 30 + RETURN VALUE 31 + ------------ 32 + The _tep_get_page_size()_ function returns size of the memory page, in bytes. 33 + 34 + EXAMPLE 35 + ------- 36 + [source,c] 37 + -- 38 + #include <unistd.h> 39 + #include <event-parse.h> 40 + ... 41 + struct tep_handle *tep = tep_alloc(); 42 + ... 43 + int page_size = getpagesize(); 44 + 45 + tep_set_page_size(tep, page_size); 46 + 47 + printf("The page size for this machine is %d\n", tep_get_page_size(tep)); 48 + 49 + -- 50 + 51 + FILES 52 + ----- 53 + [verse] 54 + -- 55 + *event-parse.h* 56 + Header file to include in order to have access to the library APIs. 57 + *-ltraceevent* 58 + Linker switch to add when building a program that uses the library. 59 + -- 60 + 61 + SEE ALSO 62 + -------- 63 + _libtraceevent(3)_, _trace-cmd(1)_ 64 + 65 + AUTHOR 66 + ------ 67 + [verse] 68 + -- 69 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 70 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 71 + -- 72 + REPORTING BUGS 73 + -------------- 74 + Report bugs to <linux-trace-devel@vger.kernel.org> 75 + 76 + LICENSE 77 + ------- 78 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 79 + 80 + RESOURCES 81 + --------- 82 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+90
tools/lib/traceevent/Documentation/libtraceevent-parse_event.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_parse_event, tep_parse_format - Parse the event format information 7 + 8 + SYNOPSIS 9 + -------- 10 + [verse] 11 + -- 12 + *#include <event-parse.h>* 13 + 14 + enum tep_errno *tep_parse_event*(struct tep_handle pass:[*]_tep_, const char pass:[*]_buf_, unsigned long _size_, const char pass:[*]_sys_); 15 + enum tep_errno *tep_parse_format*(struct tep_handle pass:[*]_tep_, struct tep_event pass:[*]pass:[*]_eventp_, const char pass:[*]_buf_, unsigned long _size_, const char pass:[*]_sys_); 16 + -- 17 + 18 + DESCRIPTION 19 + ----------- 20 + The _tep_parse_event()_ function parses the event format and creates an event 21 + structure to quickly parse raw data for a given event. The _tep_ argument is 22 + the trace event parser context. The created event structure is stored in the 23 + _tep_ context. The _buf_ argument is a buffer with _size_, where the event 24 + format data is. The event format data can be taken from 25 + tracefs/events/.../.../format files. The _sys_ argument is the system of 26 + the event. 27 + 28 + The _tep_parse_format()_ function does the same as _tep_parse_event()_. The only 29 + difference is in the extra _eventp_ argument, where the newly created event 30 + structure is returned. 31 + 32 + RETURN VALUE 33 + ------------ 34 + Both _tep_parse_event()_ and _tep_parse_format()_ functions return 0 on success, 35 + or TEP_ERRNO__... in case of an error. 36 + 37 + EXAMPLE 38 + ------- 39 + [source,c] 40 + -- 41 + #include <event-parse.h> 42 + ... 43 + struct tep_handle *tep = tep_alloc(); 44 + ... 45 + char *buf; 46 + int size; 47 + struct tep_event *event = NULL; 48 + buf = read_file("/sys/kernel/tracing/events/ftrace/print/format", &size); 49 + if (tep_parse_event(tep, buf, size, "ftrace") != 0) { 50 + /* Failed to parse the ftrace print format */ 51 + } 52 + 53 + if (tep_parse_format(tep, &event, buf, size, "ftrace") != 0) { 54 + /* Failed to parse the ftrace print format */ 55 + } 56 + ... 57 + -- 58 + 59 + FILES 60 + ----- 61 + [verse] 62 + -- 63 + *event-parse.h* 64 + Header file to include in order to have access to the library APIs. 65 + *-ltraceevent* 66 + Linker switch to add when building a program that uses the library. 67 + -- 68 + 69 + SEE ALSO 70 + -------- 71 + _libtraceevent(3)_, _trace-cmd(1)_ 72 + 73 + AUTHOR 74 + ------ 75 + [verse] 76 + -- 77 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 78 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 79 + -- 80 + REPORTING BUGS 81 + -------------- 82 + Report bugs to <linux-trace-devel@vger.kernel.org> 83 + 84 + LICENSE 85 + ------- 86 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 87 + 88 + RESOURCES 89 + --------- 90 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+82
tools/lib/traceevent/Documentation/libtraceevent-parse_head.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_parse_header_page - Parses the data stored in the header page. 7 + 8 + SYNOPSIS 9 + -------- 10 + [verse] 11 + -- 12 + *#include <event-parse.h>* 13 + 14 + int *tep_parse_header_page*(struct tep_handle pass:[*]_tep_, char pass:[*]_buf_, unsigned long _size_, int _long_size_); 15 + -- 16 + 17 + DESCRIPTION 18 + ----------- 19 + The _tep_parse_header_page()_ function parses the header page data from _buf_, 20 + and initializes the _tep_, trace event parser context, with it. The buffer 21 + _buf_ is with _size_, and is supposed to be copied from 22 + tracefs/events/header_page. 23 + 24 + Some old kernels do not have header page info, in this case the 25 + _tep_parse_header_page()_ function can be called with _size_ equal to 0. The 26 + _tep_ context is initialized with default values. The _long_size_ can be used in 27 + this use case, to set the size of a long integer to be used. 28 + 29 + RETURN VALUE 30 + ------------ 31 + The _tep_parse_header_page()_ function returns 0 in case of success, or -1 32 + in case of an error. 33 + 34 + EXAMPLE 35 + ------- 36 + [source,c] 37 + -- 38 + #include <event-parse.h> 39 + ... 40 + struct tep_handle *tep = tep_alloc(); 41 + ... 42 + char *buf; 43 + int size; 44 + buf = read_file("/sys/kernel/tracing/events/header_page", &size); 45 + if (tep_parse_header_page(tep, buf, size, sizeof(unsigned long)) != 0) { 46 + /* Failed to parse the header page */ 47 + } 48 + ... 49 + -- 50 + 51 + FILES 52 + ----- 53 + [verse] 54 + -- 55 + *event-parse.h* 56 + Header file to include in order to have access to the library APIs. 57 + *-ltraceevent* 58 + Linker switch to add when building a program that uses the library. 59 + -- 60 + 61 + SEE ALSO 62 + -------- 63 + _libtraceevent(3)_, _trace-cmd(1)_ 64 + 65 + AUTHOR 66 + ------ 67 + [verse] 68 + -- 69 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 70 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 71 + -- 72 + REPORTING BUGS 73 + -------------- 74 + Report bugs to <linux-trace-devel@vger.kernel.org> 75 + 76 + LICENSE 77 + ------- 78 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 79 + 80 + RESOURCES 81 + --------- 82 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+137
tools/lib/traceevent/Documentation/libtraceevent-record_parse.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_data_type, tep_data_pid,tep_data_preempt_count, tep_data_flags - 7 + Extract common fields from a record. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + enum *trace_flag_type* { 16 + _TRACE_FLAG_IRQS_OFF_, 17 + _TRACE_FLAG_IRQS_NOSUPPORT_, 18 + _TRACE_FLAG_NEED_RESCHED_, 19 + _TRACE_FLAG_HARDIRQ_, 20 + _TRACE_FLAG_SOFTIRQ_, 21 + }; 22 + 23 + int *tep_data_type*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 24 + int *tep_data_pid*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 25 + int *tep_data_preempt_count*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 26 + int *tep_data_flags*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 27 + -- 28 + 29 + DESCRIPTION 30 + ----------- 31 + This set of functions can be used to extract common fields from a record. 32 + 33 + The _tep_data_type()_ function gets the event id from the record _rec_. 34 + It reads the "common_type" field. The _tep_ argument is the trace event parser 35 + context. 36 + 37 + The _tep_data_pid()_ function gets the process id from the record _rec_. 38 + It reads the "common_pid" field. The _tep_ argument is the trace event parser 39 + context. 40 + 41 + The _tep_data_preempt_count()_ function gets the preemption count from the 42 + record _rec_. It reads the "common_preempt_count" field. The _tep_ argument is 43 + the trace event parser context. 44 + 45 + The _tep_data_flags()_ function gets the latency flags from the record _rec_. 46 + It reads the "common_flags" field. The _tep_ argument is the trace event parser 47 + context. Supported latency flags are: 48 + [verse] 49 + -- 50 + _TRACE_FLAG_IRQS_OFF_, Interrupts are disabled. 51 + _TRACE_FLAG_IRQS_NOSUPPORT_, Reading IRQ flag is not supported by the architecture. 52 + _TRACE_FLAG_NEED_RESCHED_, Task needs rescheduling. 53 + _TRACE_FLAG_HARDIRQ_, Hard IRQ is running. 54 + _TRACE_FLAG_SOFTIRQ_, Soft IRQ is running. 55 + -- 56 + 57 + RETURN VALUE 58 + ------------ 59 + The _tep_data_type()_ function returns an integer, representing the event id. 60 + 61 + The _tep_data_pid()_ function returns an integer, representing the process id 62 + 63 + The _tep_data_preempt_count()_ function returns an integer, representing the 64 + preemption count. 65 + 66 + The _tep_data_flags()_ function returns an integer, representing the latency 67 + flags. Look at the _trace_flag_type_ enum for supported flags. 68 + 69 + All these functions in case of an error return a negative integer. 70 + 71 + EXAMPLE 72 + ------- 73 + [source,c] 74 + -- 75 + #include <event-parse.h> 76 + ... 77 + struct tep_handle *tep = tep_alloc(); 78 + ... 79 + void process_record(struct tep_record *record) 80 + { 81 + int data; 82 + 83 + data = tep_data_type(tep, record); 84 + if (data >= 0) { 85 + /* Got the ID of the event */ 86 + } 87 + 88 + data = tep_data_pid(tep, record); 89 + if (data >= 0) { 90 + /* Got the process ID */ 91 + } 92 + 93 + data = tep_data_preempt_count(tep, record); 94 + if (data >= 0) { 95 + /* Got the preemption count */ 96 + } 97 + 98 + data = tep_data_flags(tep, record); 99 + if (data >= 0) { 100 + /* Got the latency flags */ 101 + } 102 + } 103 + ... 104 + -- 105 + 106 + FILES 107 + ----- 108 + [verse] 109 + -- 110 + *event-parse.h* 111 + Header file to include in order to have access to the library APIs. 112 + *-ltraceevent* 113 + Linker switch to add when building a program that uses the library. 114 + -- 115 + 116 + SEE ALSO 117 + -------- 118 + _libtraceevent(3)_, _trace-cmd(1)_ 119 + 120 + AUTHOR 121 + ------ 122 + [verse] 123 + -- 124 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 125 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 126 + -- 127 + REPORTING BUGS 128 + -------------- 129 + Report bugs to <linux-trace-devel@vger.kernel.org> 130 + 131 + LICENSE 132 + ------- 133 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 134 + 135 + RESOURCES 136 + --------- 137 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+156
tools/lib/traceevent/Documentation/libtraceevent-reg_event_handler.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_register_event_handler, tep_unregister_event_handler - Register / 7 + unregisters a callback function to parse an event information. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + enum *tep_reg_handler* { 16 + _TEP_REGISTER_SUCCESS_, 17 + _TEP_REGISTER_SUCCESS_OVERWRITE_, 18 + }; 19 + 20 + int *tep_register_event_handler*(struct tep_handle pass:[*]_tep_, int _id_, const char pass:[*]_sys_name_, const char pass:[*]_event_name_, tep_event_handler_func _func_, void pass:[*]_context_); 21 + int *tep_unregister_event_handler*(struct tep_handle pass:[*]tep, int id, const char pass:[*]sys_name, const char pass:[*]event_name, tep_event_handler_func func, void pass:[*]_context_); 22 + 23 + typedef int (*pass:[*]tep_event_handler_func*)(struct trace_seq pass:[*]s, struct tep_record pass:[*]record, struct tep_event pass:[*]event, void pass:[*]context); 24 + -- 25 + 26 + DESCRIPTION 27 + ----------- 28 + The _tep_register_event_handler()_ function registers a handler function, 29 + which is going to be called to parse the information for a given event. 30 + The _tep_ argument is the trace event parser context. The _id_ argument is 31 + the id of the event. The _sys_name_ argument is the name of the system, 32 + the event belongs to. The _event_name_ argument is the name of the event. 33 + If _id_ is >= 0, it is used to find the event, otherwise _sys_name_ and 34 + _event_name_ are used. The _func_ is a pointer to the function, which is going 35 + to be called to parse the event information. The _context_ argument is a pointer 36 + to the context data, which will be passed to the _func_. If a handler function 37 + for the same event is already registered, it will be overridden with the new 38 + one. This mechanism allows a developer to override the parsing of a given event. 39 + If for some reason the default print format is not sufficient, the developer 40 + can register a function for an event to be used to parse the data instead. 41 + 42 + The _tep_unregister_event_handler()_ function unregisters the handler function, 43 + previously registered with _tep_register_event_handler()_. The _tep_ argument 44 + is the trace event parser context. The _id_, _sys_name_, _event_name_, _func_, 45 + and _context_ are the same arguments, as when the callback function _func_ was 46 + registered. 47 + 48 + The _tep_event_handler_func_ is the type of the custom event handler 49 + function. The _s_ argument is the trace sequence, it can be used to create a 50 + custom string, describing the event. A _record_ to get the event from is passed 51 + as input parameter and also the _event_ - the handle to the record's event. The 52 + _context_ is custom context, set when the custom event handler is registered. 53 + 54 + RETURN VALUE 55 + ------------ 56 + The _tep_register_event_handler()_ function returns _TEP_REGISTER_SUCCESS_ 57 + if the new handler is registered successfully or 58 + _TEP_REGISTER_SUCCESS_OVERWRITE_ if an existing handler is overwritten. 59 + If there is not enough memory to complete the registration, 60 + TEP_ERRNO__MEM_ALLOC_FAILED is returned. 61 + 62 + The _tep_unregister_event_handler()_ function returns 0 if _func_ was removed 63 + successful or, -1 if the event was not found. 64 + 65 + The _tep_event_handler_func_ should return -1 in case of an error, 66 + or 0 otherwise. 67 + 68 + EXAMPLE 69 + ------- 70 + [source,c] 71 + -- 72 + #include <event-parse.h> 73 + #include <trace-seq.h> 74 + ... 75 + struct tep_handle *tep = tep_alloc(); 76 + ... 77 + int timer_expire_handler(struct trace_seq *s, struct tep_record *record, 78 + struct tep_event *event, void *context) 79 + { 80 + trace_seq_printf(s, "hrtimer="); 81 + 82 + if (tep_print_num_field(s, "0x%llx", event, "timer", record, 0) == -1) 83 + tep_print_num_field(s, "0x%llx", event, "hrtimer", record, 1); 84 + 85 + trace_seq_printf(s, " now="); 86 + 87 + tep_print_num_field(s, "%llu", event, "now", record, 1); 88 + 89 + tep_print_func_field(s, " function=%s", event, "function", record, 0); 90 + 91 + return 0; 92 + } 93 + ... 94 + int ret; 95 + 96 + ret = tep_register_event_handler(tep, -1, "timer", "hrtimer_expire_entry", 97 + timer_expire_handler, NULL); 98 + if (ret < 0) { 99 + char buf[32]; 100 + 101 + tep_strerror(tep, ret, buf, 32) 102 + printf("Failed to register handler for hrtimer_expire_entry: %s\n", buf); 103 + } else { 104 + switch (ret) { 105 + case TEP_REGISTER_SUCCESS: 106 + printf ("Registered handler for hrtimer_expire_entry\n"); 107 + break; 108 + case TEP_REGISTER_SUCCESS_OVERWRITE: 109 + printf ("Overwrote handler for hrtimer_expire_entry\n"); 110 + break; 111 + } 112 + } 113 + ... 114 + ret = tep_unregister_event_handler(tep, -1, "timer", "hrtimer_expire_entry", 115 + timer_expire_handler, NULL); 116 + if ( ret ) 117 + printf ("Failed to unregister handler for hrtimer_expire_entry\n"); 118 + 119 + -- 120 + 121 + FILES 122 + ----- 123 + [verse] 124 + -- 125 + *event-parse.h* 126 + Header file to include in order to have access to the library APIs. 127 + *trace-seq.h* 128 + Header file to include in order to have access to trace sequences 129 + related APIs. Trace sequences are used to allow a function to call 130 + several other functions to create a string of data to use. 131 + *-ltraceevent* 132 + Linker switch to add when building a program that uses the library. 133 + -- 134 + 135 + SEE ALSO 136 + -------- 137 + _libtraceevent(3)_, _trace-cmd(1)_ 138 + 139 + AUTHOR 140 + ------ 141 + [verse] 142 + -- 143 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 144 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 145 + -- 146 + REPORTING BUGS 147 + -------------- 148 + Report bugs to <linux-trace-devel@vger.kernel.org> 149 + 150 + LICENSE 151 + ------- 152 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 153 + 154 + RESOURCES 155 + --------- 156 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+155
tools/lib/traceevent/Documentation/libtraceevent-reg_print_func.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_register_print_function,tep_unregister_print_function - 7 + Registers / Unregisters a helper function. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + enum *tep_func_arg_type* { 16 + TEP_FUNC_ARG_VOID, 17 + TEP_FUNC_ARG_INT, 18 + TEP_FUNC_ARG_LONG, 19 + TEP_FUNC_ARG_STRING, 20 + TEP_FUNC_ARG_PTR, 21 + TEP_FUNC_ARG_MAX_TYPES 22 + }; 23 + 24 + typedef unsigned long long (*pass:[*]tep_func_handler*)(struct trace_seq pass:[*]s, unsigned long long pass:[*]args); 25 + 26 + int *tep_register_print_function*(struct tep_handle pass:[*]_tep_, tep_func_handler _func_, enum tep_func_arg_type _ret_type_, char pass:[*]_name_, _..._); 27 + int *tep_unregister_print_function*(struct tep_handle pass:[*]_tep_, tep_func_handler _func_, char pass:[*]_name_); 28 + -- 29 + 30 + DESCRIPTION 31 + ----------- 32 + Some events may have helper functions in the print format arguments. 33 + This allows a plugin to dynamically create a way to process one of 34 + these functions. 35 + 36 + The _tep_register_print_function()_ registers such helper function. The _tep_ 37 + argument is the trace event parser context. The _func_ argument is a pointer 38 + to the helper function. The _ret_type_ argument is the return type of the 39 + helper function, value from the _tep_func_arg_type_ enum. The _name_ is the name 40 + of the helper function, as seen in the print format arguments. The _..._ is a 41 + variable list of _tep_func_arg_type_ enums, the _func_ function arguments. 42 + This list must end with _TEP_FUNC_ARG_VOID_. See 'EXAMPLE' section. 43 + 44 + The _tep_unregister_print_function()_ unregisters a helper function, previously 45 + registered with _tep_register_print_function()_. The _tep_ argument is the 46 + trace event parser context. The _func_ and _name_ arguments are the same, used 47 + when the helper function was registered. 48 + 49 + The _tep_func_handler_ is the type of the helper function. The _s_ argument is 50 + the trace sequence, it can be used to create a custom string. 51 + The _args_ is a list of arguments, defined when the helper function was 52 + registered. 53 + 54 + RETURN VALUE 55 + ------------ 56 + The _tep_register_print_function()_ function returns 0 in case of success. 57 + In case of an error, TEP_ERRNO_... code is returned. 58 + 59 + The _tep_unregister_print_function()_ returns 0 in case of success, or -1 in 60 + case of an error. 61 + 62 + EXAMPLE 63 + ------- 64 + Some events have internal functions calls, that appear in the print format 65 + output. For example "tracefs/events/i915/g4x_wm/format" has: 66 + [source,c] 67 + -- 68 + print fmt: "pipe %c, frame=%u, scanline=%u, wm %d/%d/%d, sr %s/%d/%d/%d, hpll %s/%d/%d/%d, fbc %s", 69 + ((REC->pipe) + 'A'), REC->frame, REC->scanline, REC->primary, 70 + REC->sprite, REC->cursor, yesno(REC->cxsr), REC->sr_plane, 71 + REC->sr_cursor, REC->sr_fbc, yesno(REC->hpll), REC->hpll_plane, 72 + REC->hpll_cursor, REC->hpll_fbc, yesno(REC->fbc) 73 + -- 74 + Notice the call to function _yesno()_ in the print arguments. In the kernel 75 + context, this function has the following implementation: 76 + [source,c] 77 + -- 78 + static const char *yesno(int x) 79 + { 80 + static const char *yes = "yes"; 81 + static const char *no = "no"; 82 + 83 + return x ? yes : no; 84 + } 85 + -- 86 + The user space event parser has no idea how to handle this _yesno()_ function. 87 + The _tep_register_print_function()_ API can be used to register a user space 88 + helper function, mapped to the kernel's _yesno()_: 89 + [source,c] 90 + -- 91 + #include <event-parse.h> 92 + #include <trace-seq.h> 93 + ... 94 + struct tep_handle *tep = tep_alloc(); 95 + ... 96 + static const char *yes_no_helper(int x) 97 + { 98 + return x ? "yes" : "no"; 99 + } 100 + ... 101 + if ( tep_register_print_function(tep, 102 + yes_no_helper, 103 + TEP_FUNC_ARG_STRING, 104 + "yesno", 105 + TEP_FUNC_ARG_INT, 106 + TEP_FUNC_ARG_VOID) != 0) { 107 + /* Failed to register yes_no_helper function */ 108 + } 109 + 110 + /* 111 + Now, when the event parser encounters this yesno() function, it will know 112 + how to handle it. 113 + */ 114 + ... 115 + if (tep_unregister_print_function(tep, yes_no_helper, "yesno") != 0) { 116 + /* Failed to unregister yes_no_helper function */ 117 + } 118 + -- 119 + 120 + FILES 121 + ----- 122 + [verse] 123 + -- 124 + *event-parse.h* 125 + Header file to include in order to have access to the library APIs. 126 + *trace-seq.h* 127 + Header file to include in order to have access to trace sequences 128 + related APIs. Trace sequences are used to allow a function to call 129 + several other functions to create a string of data to use. 130 + *-ltraceevent* 131 + Linker switch to add when building a program that uses the library. 132 + -- 133 + 134 + SEE ALSO 135 + -------- 136 + _libtraceevent(3)_, _trace-cmd(1)_ 137 + 138 + AUTHOR 139 + ------ 140 + [verse] 141 + -- 142 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 143 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 144 + -- 145 + REPORTING BUGS 146 + -------------- 147 + Report bugs to <linux-trace-devel@vger.kernel.org> 148 + 149 + LICENSE 150 + ------- 151 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 152 + 153 + RESOURCES 154 + --------- 155 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+104
tools/lib/traceevent/Documentation/libtraceevent-set_flag.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_set_flag, tep_clear_flag, tep_test_flag - 7 + Manage flags of trace event parser context. 8 + 9 + SYNOPSIS 10 + -------- 11 + [verse] 12 + -- 13 + *#include <event-parse.h>* 14 + 15 + enum *tep_flag* { 16 + _TEP_NSEC_OUTPUT_, 17 + _TEP_DISABLE_SYS_PLUGINS_, 18 + _TEP_DISABLE_PLUGINS_ 19 + }; 20 + void *tep_set_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); 21 + void *tep_clear_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); 22 + bool *tep_test_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); 23 + -- 24 + 25 + DESCRIPTION 26 + ----------- 27 + Trace event parser context flags are defined in *enum tep_flag*: 28 + [verse] 29 + -- 30 + _TEP_NSEC_OUTPUT_ - print event's timestamp in nano seconds, instead of micro seconds. 31 + _TEP_DISABLE_SYS_PLUGINS_ - disable plugins, located in system's plugin 32 + directory. This directory is defined at library compile 33 + time, and usually depends on library installation 34 + prefix: (install_preffix)/lib/traceevent/plugins 35 + _TEP_DISABLE_PLUGINS_ - disable all library plugins: 36 + - in system's plugin directory 37 + - in directory, defined by the environment variable _TRACEEVENT_PLUGIN_DIR_ 38 + - in user's home directory, _~/.traceevent/plugins_ 39 + -- 40 + Note: plugin related flags must me set before calling _tep_load_plugins()_ API. 41 + 42 + The _tep_set_flag()_ function sets _flag_ to _tep_ context. 43 + 44 + The _tep_clear_flag()_ function clears _flag_ from _tep_ context. 45 + 46 + The _tep_test_flag()_ function tests if _flag_ is set to _tep_ context. 47 + 48 + RETURN VALUE 49 + ------------ 50 + _tep_test_flag()_ function returns true if _flag_ is set, false otherwise. 51 + 52 + EXAMPLE 53 + ------- 54 + [source,c] 55 + -- 56 + #include <event-parse.h> 57 + ... 58 + struct tep_handle *tep = tep_alloc(); 59 + ... 60 + /* Print timestamps in nanoseconds */ 61 + tep_set_flag(tep, TEP_NSEC_OUTPUT); 62 + ... 63 + if (tep_test_flag(tep, TEP_NSEC_OUTPUT)) { 64 + /* print timestamps in nanoseconds */ 65 + } else { 66 + /* print timestamps in microseconds */ 67 + } 68 + ... 69 + /* Print timestamps in microseconds */ 70 + tep_clear_flag(tep, TEP_NSEC_OUTPUT); 71 + ... 72 + -- 73 + FILES 74 + ----- 75 + [verse] 76 + -- 77 + *event-parse.h* 78 + Header file to include in order to have access to the library APIs. 79 + *-ltraceevent* 80 + Linker switch to add when building a program that uses the library. 81 + -- 82 + 83 + SEE ALSO 84 + -------- 85 + _libtraceevent(3)_, _trace-cmd(1)_ 86 + 87 + AUTHOR 88 + ------ 89 + [verse] 90 + -- 91 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 92 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 93 + -- 94 + REPORTING BUGS 95 + -------------- 96 + Report bugs to <linux-trace-devel@vger.kernel.org> 97 + 98 + LICENSE 99 + ------- 100 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 101 + 102 + RESOURCES 103 + --------- 104 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+85
tools/lib/traceevent/Documentation/libtraceevent-strerror.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + tep_strerror - Returns a string describing regular errno and tep error number. 7 + 8 + SYNOPSIS 9 + -------- 10 + [verse] 11 + -- 12 + *#include <event-parse.h>* 13 + 14 + int *tep_strerror*(struct tep_handle pass:[*]_tep_, enum tep_errno _errnum_, char pass:[*]_buf_, size_t _buflen_); 15 + 16 + -- 17 + DESCRIPTION 18 + ----------- 19 + The _tep_strerror()_ function converts tep error number into a human 20 + readable string. 21 + The _tep_ argument is trace event parser context. The _errnum_ is a regular 22 + errno, defined in errno.h, or a tep error number. The string, describing this 23 + error number is copied in the _buf_ argument. The _buflen_ argument is 24 + the size of the _buf_. 25 + 26 + It as a thread safe wrapper around strerror_r(). The library function has two 27 + different behaviors - POSIX and GNU specific. The _tep_strerror()_ API always 28 + behaves as the POSIX version - the error string is copied in the user supplied 29 + buffer. 30 + 31 + RETURN VALUE 32 + ------------ 33 + The _tep_strerror()_ function returns 0, if a valid _errnum_ is passed and the 34 + string is copied into _buf_. If _errnum_ is not a valid error number, 35 + -1 is returned and _buf_ is not modified. 36 + 37 + EXAMPLE 38 + ------- 39 + [source,c] 40 + -- 41 + #include <event-parse.h> 42 + ... 43 + struct tep_handle *tep = tep_alloc(); 44 + ... 45 + char buf[32]; 46 + char *pool = calloc(1, 128); 47 + if (tep == NULL) { 48 + tep_strerror(tep, TEP_ERRNO__MEM_ALLOC_FAILED, buf, 32); 49 + printf ("The pool is not initialized, %s", buf); 50 + } 51 + ... 52 + -- 53 + 54 + FILES 55 + ----- 56 + [verse] 57 + -- 58 + *event-parse.h* 59 + Header file to include in order to have access to the library APIs. 60 + *-ltraceevent* 61 + Linker switch to add when building a program that uses the library. 62 + -- 63 + 64 + SEE ALSO 65 + -------- 66 + _libtraceevent(3)_, _trace-cmd(1)_ 67 + 68 + AUTHOR 69 + ------ 70 + [verse] 71 + -- 72 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 73 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 74 + -- 75 + REPORTING BUGS 76 + -------------- 77 + Report bugs to <linux-trace-devel@vger.kernel.org> 78 + 79 + LICENSE 80 + ------- 81 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 82 + 83 + RESOURCES 84 + --------- 85 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+158
tools/lib/traceevent/Documentation/libtraceevent-tseq.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + trace_seq_init, trace_seq_destroy, trace_seq_reset, trace_seq_terminate, 7 + trace_seq_putc, trace_seq_puts, trace_seq_printf, trace_seq_vprintf, 8 + trace_seq_do_fprintf, trace_seq_do_printf - 9 + Initialize / destroy a trace sequence. 10 + 11 + SYNOPSIS 12 + -------- 13 + [verse] 14 + -- 15 + *#include <event-parse.h>* 16 + *#include <trace-seq.h>* 17 + 18 + void *trace_seq_init*(struct trace_seq pass:[*]_s_); 19 + void *trace_seq_destroy*(struct trace_seq pass:[*]_s_); 20 + void *trace_seq_reset*(struct trace_seq pass:[*]_s_); 21 + void *trace_seq_terminate*(struct trace_seq pass:[*]_s_); 22 + int *trace_seq_putc*(struct trace_seq pass:[*]_s_, unsigned char _c_); 23 + int *trace_seq_puts*(struct trace_seq pass:[*]_s_, const char pass:[*]_str_); 24 + int *trace_seq_printf*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, _..._); 25 + int *trace_seq_vprintf*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, va_list _args_); 26 + int *trace_seq_do_printf*(struct trace_seq pass:[*]_s_); 27 + int *trace_seq_do_fprintf*(struct trace_seq pass:[*]_s_, FILE pass:[*]_fp_); 28 + -- 29 + 30 + DESCRIPTION 31 + ----------- 32 + Trace sequences are used to allow a function to call several other functions 33 + to create a string of data to use. 34 + 35 + The _trace_seq_init()_ function initializes the trace sequence _s_. 36 + 37 + The _trace_seq_destroy()_ function destroys the trace sequence _s_ and frees 38 + all its resources that it had used. 39 + 40 + The _trace_seq_reset()_ function re-initializes the trace sequence _s_. All 41 + characters already written in _s_ will be deleted. 42 + 43 + The _trace_seq_terminate()_ function terminates the trace sequence _s_. It puts 44 + the null character pass:['\0'] at the end of the buffer. 45 + 46 + The _trace_seq_putc()_ function puts a single character _c_ in the trace 47 + sequence _s_. 48 + 49 + The _trace_seq_puts()_ function puts a NULL terminated string _str_ in the 50 + trace sequence _s_. 51 + 52 + The _trace_seq_printf()_ function puts a formated string _fmt _with 53 + variable arguments _..._ in the trace sequence _s_. 54 + 55 + The _trace_seq_vprintf()_ function puts a formated string _fmt _with 56 + list of arguments _args_ in the trace sequence _s_. 57 + 58 + The _trace_seq_do_printf()_ function prints the buffer of trace sequence _s_ to 59 + the standard output stdout. 60 + 61 + The _trace_seq_do_fprintf()_ function prints the buffer of trace sequence _s_ 62 + to the given file _fp_. 63 + 64 + RETURN VALUE 65 + ------------ 66 + Both _trace_seq_putc()_ and _trace_seq_puts()_ functions return the number of 67 + characters put in the trace sequence, or 0 in case of an error 68 + 69 + Both _trace_seq_printf()_ and _trace_seq_vprintf()_ functions return 0 if the 70 + trace oversizes the buffer's free space, the number of characters printed, or 71 + a negative value in case of an error. 72 + 73 + Both _trace_seq_do_printf()_ and _trace_seq_do_fprintf()_ functions return the 74 + number of printed characters, or -1 in case of an error. 75 + 76 + EXAMPLE 77 + ------- 78 + [source,c] 79 + -- 80 + #include <event-parse.h> 81 + #include <trace-seq.h> 82 + ... 83 + struct trace_seq seq; 84 + trace_seq_init(&seq); 85 + ... 86 + void foo_seq_print(struct trace_seq *tseq, char *format, ...) 87 + { 88 + va_list ap; 89 + va_start(ap, format); 90 + if (trace_seq_vprintf(tseq, format, ap) <= 0) { 91 + /* Failed to print in the trace sequence */ 92 + } 93 + va_end(ap); 94 + } 95 + 96 + trace_seq_reset(&seq); 97 + 98 + char *str = " MAN page example"; 99 + if (trace_seq_puts(&seq, str) != strlen(str)) { 100 + /* Failed to put str in the trace sequence */ 101 + } 102 + if (trace_seq_putc(&seq, ':') != 1) { 103 + /* Failed to put ':' in the trace sequence */ 104 + } 105 + if (trace_seq_printf(&seq, " trace sequence: %d", 1) <= 0) { 106 + /* Failed to print in the trace sequence */ 107 + } 108 + foo_seq_print( &seq, " %d\n", 2); 109 + 110 + trace_seq_terminate(&seq); 111 + ... 112 + 113 + if (trace_seq_do_printf(&seq) < 0 ) { 114 + /* Failed to print the sequence buffer to the standard output */ 115 + } 116 + FILE *fp = fopen("trace.txt", "w"); 117 + if (trace_seq_do_fprintf(&seq, fp) < 0 ) [ 118 + /* Failed to print the sequence buffer to the trace.txt file */ 119 + } 120 + 121 + trace_seq_destroy(&seq); 122 + ... 123 + -- 124 + 125 + FILES 126 + ----- 127 + [verse] 128 + -- 129 + *event-parse.h* 130 + Header file to include in order to have access to the library APIs. 131 + *trace-seq.h* 132 + Header file to include in order to have access to trace sequences related APIs. 133 + *-ltraceevent* 134 + Linker switch to add when building a program that uses the library. 135 + -- 136 + 137 + SEE ALSO 138 + -------- 139 + _libtraceevent(3)_, _trace-cmd(1)_ 140 + 141 + AUTHOR 142 + ------ 143 + [verse] 144 + -- 145 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 146 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 147 + -- 148 + REPORTING BUGS 149 + -------------- 150 + Report bugs to <linux-trace-devel@vger.kernel.org> 151 + 152 + LICENSE 153 + ------- 154 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 155 + 156 + RESOURCES 157 + --------- 158 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+203
tools/lib/traceevent/Documentation/libtraceevent.txt
··· 1 + libtraceevent(3) 2 + ================ 3 + 4 + NAME 5 + ---- 6 + libtraceevent - Linux kernel trace event library 7 + 8 + SYNOPSIS 9 + -------- 10 + [verse] 11 + -- 12 + *#include <event-parse.h>* 13 + 14 + Management of tep handler data structure and access of its members: 15 + struct tep_handle pass:[*]*tep_alloc*(void); 16 + void *tep_free*(struct tep_handle pass:[*]_tep_); 17 + void *tep_ref*(struct tep_handle pass:[*]_tep_); 18 + void *tep_unref*(struct tep_handle pass:[*]_tep_); 19 + int *tep_ref_get*(struct tep_handle pass:[*]_tep_); 20 + void *tep_set_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); 21 + void *tep_clear_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flag_); 22 + bool *tep_test_flag*(struct tep_handle pass:[*]_tep_, enum tep_flag _flags_); 23 + int *tep_get_cpus*(struct tep_handle pass:[*]_tep_); 24 + void *tep_set_cpus*(struct tep_handle pass:[*]_tep_, int _cpus_); 25 + int *tep_get_long_size*(strucqt tep_handle pass:[*]_tep_); 26 + void *tep_set_long_size*(struct tep_handle pass:[*]_tep_, int _long_size_); 27 + int *tep_get_page_size*(struct tep_handle pass:[*]_tep_); 28 + void *tep_set_page_size*(struct tep_handle pass:[*]_tep_, int _page_size_); 29 + bool *tep_is_latency_format*(struct tep_handle pass:[*]_tep_); 30 + void *tep_set_latency_format*(struct tep_handle pass:[*]_tep_, int _lat_); 31 + int *tep_get_header_page_size*(struct tep_handle pass:[*]_tep_); 32 + int *tep_get_header_timestamp_size*(struct tep_handle pass:[*]_tep_); 33 + bool *tep_is_old_format*(struct tep_handle pass:[*]_tep_); 34 + int *tep_strerror*(struct tep_handle pass:[*]_tep_, enum tep_errno _errnum_, char pass:[*]_buf_, size_t _buflen_); 35 + 36 + Register / unregister APIs: 37 + int *tep_register_trace_clock*(struct tep_handle pass:[*]_tep_, const char pass:[*]_trace_clock_); 38 + int *tep_register_function*(struct tep_handle pass:[*]_tep_, char pass:[*]_name_, unsigned long long _addr_, char pass:[*]_mod_); 39 + int *tep_register_event_handler*(struct tep_handle pass:[*]_tep_, int _id_, const char pass:[*]_sys_name_, const char pass:[*]_event_name_, tep_event_handler_func _func_, void pass:[*]_context_); 40 + int *tep_unregister_event_handler*(struct tep_handle pass:[*]tep, int id, const char pass:[*]sys_name, const char pass:[*]event_name, tep_event_handler_func func, void pass:[*]_context_); 41 + int *tep_register_print_string*(struct tep_handle pass:[*]_tep_, const char pass:[*]_fmt_, unsigned long long _addr_); 42 + int *tep_register_print_function*(struct tep_handle pass:[*]_tep_, tep_func_handler _func_, enum tep_func_arg_type _ret_type_, char pass:[*]_name_, _..._); 43 + int *tep_unregister_print_function*(struct tep_handle pass:[*]_tep_, tep_func_handler _func_, char pass:[*]_name_); 44 + 45 + Plugins management: 46 + struct tep_plugin_list pass:[*]*tep_load_plugins*(struct tep_handle pass:[*]_tep_); 47 + void *tep_unload_plugins*(struct tep_plugin_list pass:[*]_plugin_list_, struct tep_handle pass:[*]_tep_); 48 + char pass:[*]pass:[*]*tep_plugin_list_options*(void); 49 + void *tep_plugin_free_options_list*(char pass:[*]pass:[*]_list_); 50 + int *tep_plugin_add_options*(const char pass:[*]_name_, struct tep_plugin_option pass:[*]_options_); 51 + void *tep_plugin_remove_options*(struct tep_plugin_option pass:[*]_options_); 52 + void *tep_print_plugins*(struct trace_seq pass:[*]_s_, const char pass:[*]_prefix_, const char pass:[*]_suffix_, const struct tep_plugin_list pass:[*]_list_); 53 + 54 + Event related APIs: 55 + struct tep_event pass:[*]*tep_get_event*(struct tep_handle pass:[*]_tep_, int _index_); 56 + struct tep_event pass:[*]*tep_get_first_event*(struct tep_handle pass:[*]_tep_); 57 + int *tep_get_events_count*(struct tep_handle pass:[*]_tep_); 58 + struct tep_event pass:[*]pass:[*]*tep_list_events*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); 59 + struct tep_event pass:[*]pass:[*]*tep_list_events_copy*(struct tep_handle pass:[*]_tep_, enum tep_event_sort_type _sort_type_); 60 + 61 + Event printing: 62 + void *tep_print_event*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_, bool _use_trace_clock_); 63 + void *tep_print_event_data*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); 64 + void *tep_event_info*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); 65 + void *tep_print_event_task*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]_record_); 66 + void *tep_print_event_time*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, struct tep_record pass:[*]record, bool _use_trace_clock_); 67 + void *tep_set_print_raw*(struct tep_handle pass:[*]_tep_, int _print_raw_); 68 + 69 + Event finding: 70 + struct tep_event pass:[*]*tep_find_event*(struct tep_handle pass:[*]_tep_, int _id_); 71 + struct tep_event pass:[*]*tep_find_event_by_name*(struct tep_handle pass:[*]_tep_, const char pass:[*]_sys_, const char pass:[*]_name_); 72 + struct tep_event pass:[*]*tep_find_event_by_record*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_record_); 73 + 74 + Parsing of event files: 75 + int *tep_parse_header_page*(struct tep_handle pass:[*]_tep_, char pass:[*]_buf_, unsigned long _size_, int _long_size_); 76 + enum tep_errno *tep_parse_event*(struct tep_handle pass:[*]_tep_, const char pass:[*]_buf_, unsigned long _size_, const char pass:[*]_sys_); 77 + enum tep_errno *tep_parse_format*(struct tep_handle pass:[*]_tep_, struct tep_event pass:[*]pass:[*]_eventp_, const char pass:[*]_buf_, unsigned long _size_, const char pass:[*]_sys_); 78 + 79 + APIs related to fields from event's format files: 80 + struct tep_format_field pass:[*]pass:[*]*tep_event_common_fields*(struct tep_event pass:[*]_event_); 81 + struct tep_format_field pass:[*]pass:[*]*tep_event_fields*(struct tep_event pass:[*]_event_); 82 + void pass:[*]*tep_get_field_raw*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int pass:[*]_len_, int _err_); 83 + int *tep_get_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); 84 + int *tep_get_common_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); 85 + int *tep_get_any_field_val*(struct trace_seq pass:[*]_s_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, unsigned long long pass:[*]_val_, int _err_); 86 + int *tep_read_number_field*(struct tep_format_field pass:[*]_field_, const void pass:[*]_data_, unsigned long long pass:[*]_value_); 87 + 88 + Event fields printing: 89 + void *tep_print_field*(struct trace_seq pass:[*]_s_, void pass:[*]_data_, struct tep_format_field pass:[*]_field_); 90 + void *tep_print_fields*(struct trace_seq pass:[*]_s_, void pass:[*]_data_, int _size_, struct tep_event pass:[*]_event_); 91 + int *tep_print_num_field*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int _err_); 92 + int *tep_print_func_field*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, struct tep_event pass:[*]_event_, const char pass:[*]_name_, struct tep_record pass:[*]_record_, int _err_); 93 + 94 + Event fields finding: 95 + struct tep_format_field pass:[*]*tep_find_common_field*(struct tep_event pass:[*]_event_, const char pass:[*]_name_); 96 + struct tep_format_field pass:[*]*tep_find_field*(struct tep_event_ormat pass:[*]_event_, const char pass:[*]_name_); 97 + struct tep_format_field pass:[*]*tep_find_any_field*(struct tep_event pass:[*]_event_, const char pass:[*]_name_); 98 + 99 + Functions resolver: 100 + int *tep_set_function_resolver*(struct tep_handle pass:[*]_tep_, tep_func_resolver_t pass:[*]_func_, void pass:[*]_priv_); 101 + void *tep_reset_function_resolver*(struct tep_handle pass:[*]_tep_); 102 + const char pass:[*]*tep_find_function*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); 103 + unsigned long long *tep_find_function_address*(struct tep_handle pass:[*]_tep_, unsigned long long _addr_); 104 + 105 + Filter management: 106 + struct tep_event_filter pass:[*]*tep_filter_alloc*(struct tep_handle pass:[*]_tep_); 107 + enum tep_errno *tep_filter_add_filter_str*(struct tep_event_filter pass:[*]_filter_, const char pass:[*]_filter_str_); 108 + enum tep_errno *tep_filter_match*(struct tep_event_filter pass:[*]_filter_, struct tep_record pass:[*]_record_); 109 + int *tep_filter_strerror*(struct tep_event_filter pass:[*]_filter_, enum tep_errno _err_, char pass:[*]buf, size_t _buflen_); 110 + int *tep_event_filtered*(struct tep_event_filter pass:[*]_filter_, int _event_id_); 111 + void *tep_filter_reset*(struct tep_event_filter pass:[*]_filter_); 112 + void *tep_filter_free*(struct tep_event_filter pass:[*]_filter_); 113 + char pass:[*]*tep_filter_make_string*(struct tep_event_filter pass:[*]_filter_, int _event_id_); 114 + int *tep_filter_remove_event*(struct tep_event_filter pass:[*]_filter_, int _event_id_); 115 + int *tep_filter_copy*(struct tep_event_filter pass:[*]_dest_, struct tep_event_filter pass:[*]_source_); 116 + int *tep_filter_compare*(struct tep_event_filter pass:[*]_filter1_, struct tep_event_filter pass:[*]_filter2_); 117 + 118 + Parsing various data from the records: 119 + void *tep_data_latency_format*(struct tep_handle pass:[*]_tep_, struct trace_seq pass:[*]_s_, struct tep_record pass:[*]_record_); 120 + int *tep_data_type*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 121 + int *tep_data_pid*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 122 + int *tep_data_preempt_count*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 123 + int *tep_data_flags*(struct tep_handle pass:[*]_tep_, struct tep_record pass:[*]_rec_); 124 + 125 + Command and task related APIs: 126 + const char pass:[*]*tep_data_comm_from_pid*(struct tep_handle pass:[*]_tep_, int _pid_); 127 + struct cmdline pass:[*]*tep_data_pid_from_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, struct cmdline pass:[*]_next_); 128 + int *tep_register_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, int _pid_); 129 + int *tep_override_comm*(struct tep_handle pass:[*]_tep_, const char pass:[*]_comm_, int _pid_); 130 + bool *tep_is_pid_registered*(struct tep_handle pass:[*]_tep_, int _pid_); 131 + int *tep_cmdline_pid*(struct tep_handle pass:[*]_tep_, struct cmdline pass:[*]_cmdline_); 132 + 133 + Endian related APIs: 134 + int *tep_is_bigendian*(void); 135 + unsigned long long *tep_read_number*(struct tep_handle pass:[*]_tep_, const void pass:[*]_ptr_, int _size_); 136 + bool *tep_is_file_bigendian*(struct tep_handle pass:[*]_tep_); 137 + void *tep_set_file_bigendian*(struct tep_handle pass:[*]_tep_, enum tep_endian _endian_); 138 + bool *tep_is_local_bigendian*(struct tep_handle pass:[*]_tep_); 139 + void *tep_set_local_bigendian*(struct tep_handle pass:[*]_tep_, enum tep_endian _endian_); 140 + 141 + Trace sequences: 142 + *#include <trace-seq.h>* 143 + void *trace_seq_init*(struct trace_seq pass:[*]_s_); 144 + void *trace_seq_reset*(struct trace_seq pass:[*]_s_); 145 + void *trace_seq_destroy*(struct trace_seq pass:[*]_s_); 146 + int *trace_seq_printf*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, ...); 147 + int *trace_seq_vprintf*(struct trace_seq pass:[*]_s_, const char pass:[*]_fmt_, va_list _args_); 148 + int *trace_seq_puts*(struct trace_seq pass:[*]_s_, const char pass:[*]_str_); 149 + int *trace_seq_putc*(struct trace_seq pass:[*]_s_, unsigned char _c_); 150 + void *trace_seq_terminate*(struct trace_seq pass:[*]_s_); 151 + int *trace_seq_do_fprintf*(struct trace_seq pass:[*]_s_, FILE pass:[*]_fp_); 152 + int *trace_seq_do_printf*(struct trace_seq pass:[*]_s_); 153 + -- 154 + 155 + DESCRIPTION 156 + ----------- 157 + The libtraceevent(3) library provides APIs to access kernel tracepoint events, 158 + located in the tracefs file system under the events directory. 159 + 160 + ENVIRONMENT 161 + ----------- 162 + [verse] 163 + -- 164 + TRACEEVENT_PLUGIN_DIR 165 + Additional plugin directory. All shared object files, located in this directory will be loaded as traceevent plugins. 166 + -- 167 + 168 + FILES 169 + ----- 170 + [verse] 171 + -- 172 + *event-parse.h* 173 + Header file to include in order to have access to the library APIs. 174 + *trace-seq.h* 175 + Header file to include in order to have access to trace sequences related APIs. 176 + Trace sequences are used to allow a function to call several other functions 177 + to create a string of data to use. 178 + *-ltraceevent* 179 + Linker switch to add when building a program that uses the library. 180 + -- 181 + 182 + SEE ALSO 183 + -------- 184 + _trace-cmd(1)_ 185 + 186 + AUTHOR 187 + ------ 188 + [verse] 189 + -- 190 + *Steven Rostedt* <rostedt@goodmis.org>, author of *libtraceevent*. 191 + *Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>, author of this man page. 192 + -- 193 + REPORTING BUGS 194 + -------------- 195 + Report bugs to <linux-trace-devel@vger.kernel.org> 196 + 197 + LICENSE 198 + ------- 199 + libtraceevent is Free Software licensed under the GNU LGPL 2.1 200 + 201 + RESOURCES 202 + --------- 203 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+14
tools/lib/traceevent/Documentation/manpage-1.72.xsl
··· 1 + <!-- manpage-1.72.xsl: 2 + special settings for manpages rendered from asciidoc+docbook 3 + handles peculiarities in docbook-xsl 1.72.0 --> 4 + <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 5 + version="1.0"> 6 + 7 + <xsl:import href="manpage-base.xsl"/> 8 + 9 + <!-- these are the special values for the roff control characters 10 + needed for docbook-xsl 1.72.0 --> 11 + <xsl:param name="git.docbook.backslash">&#x2593;</xsl:param> 12 + <xsl:param name="git.docbook.dot" >&#x2302;</xsl:param> 13 + 14 + </xsl:stylesheet>
+35
tools/lib/traceevent/Documentation/manpage-base.xsl
··· 1 + <!-- manpage-base.xsl: 2 + special formatting for manpages rendered from asciidoc+docbook --> 3 + <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4 + version="1.0"> 5 + 6 + <!-- these params silence some output from xmlto --> 7 + <xsl:param name="man.output.quietly" select="1"/> 8 + <xsl:param name="refentry.meta.get.quietly" select="1"/> 9 + 10 + <!-- convert asciidoc callouts to man page format; 11 + git.docbook.backslash and git.docbook.dot params 12 + must be supplied by another XSL file or other means --> 13 + <xsl:template match="co"> 14 + <xsl:value-of select="concat( 15 + $git.docbook.backslash,'fB(', 16 + substring-after(@id,'-'),')', 17 + $git.docbook.backslash,'fR')"/> 18 + </xsl:template> 19 + <xsl:template match="calloutlist"> 20 + <xsl:value-of select="$git.docbook.dot"/> 21 + <xsl:text>sp&#10;</xsl:text> 22 + <xsl:apply-templates/> 23 + <xsl:text>&#10;</xsl:text> 24 + </xsl:template> 25 + <xsl:template match="callout"> 26 + <xsl:value-of select="concat( 27 + $git.docbook.backslash,'fB', 28 + substring-after(@arearefs,'-'), 29 + '. ',$git.docbook.backslash,'fR')"/> 30 + <xsl:apply-templates/> 31 + <xsl:value-of select="$git.docbook.dot"/> 32 + <xsl:text>br&#10;</xsl:text> 33 + </xsl:template> 34 + 35 + </xsl:stylesheet>
+17
tools/lib/traceevent/Documentation/manpage-bold-literal.xsl
··· 1 + <!-- manpage-bold-literal.xsl: 2 + special formatting for manpages rendered from asciidoc+docbook --> 3 + <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4 + version="1.0"> 5 + 6 + <!-- render literal text as bold (instead of plain or monospace); 7 + this makes literal text easier to distinguish in manpages 8 + viewed on a tty --> 9 + <xsl:template match="literal"> 10 + <xsl:value-of select="$git.docbook.backslash"/> 11 + <xsl:text>fB</xsl:text> 12 + <xsl:apply-templates/> 13 + <xsl:value-of select="$git.docbook.backslash"/> 14 + <xsl:text>fR</xsl:text> 15 + </xsl:template> 16 + 17 + </xsl:stylesheet>
+13
tools/lib/traceevent/Documentation/manpage-normal.xsl
··· 1 + <!-- manpage-normal.xsl: 2 + special settings for manpages rendered from asciidoc+docbook 3 + handles anything we want to keep away from docbook-xsl 1.72.0 --> 4 + <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 5 + version="1.0"> 6 + 7 + <xsl:import href="manpage-base.xsl"/> 8 + 9 + <!-- these are the normal values for the roff control characters --> 10 + <xsl:param name="git.docbook.backslash">\</xsl:param> 11 + <xsl:param name="git.docbook.dot" >.</xsl:param> 12 + 13 + </xsl:stylesheet>
+21
tools/lib/traceevent/Documentation/manpage-suppress-sp.xsl
··· 1 + <!-- manpage-suppress-sp.xsl: 2 + special settings for manpages rendered from asciidoc+docbook 3 + handles erroneous, inline .sp in manpage output of some 4 + versions of docbook-xsl --> 5 + <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 6 + version="1.0"> 7 + 8 + <!-- attempt to work around spurious .sp at the tail of the line 9 + that some versions of docbook stylesheets seem to add --> 10 + <xsl:template match="simpara"> 11 + <xsl:variable name="content"> 12 + <xsl:apply-templates/> 13 + </xsl:variable> 14 + <xsl:value-of select="normalize-space($content)"/> 15 + <xsl:if test="not(ancestor::authorblurb) and 16 + not(ancestor::personblurb)"> 17 + <xsl:text>&#10;&#10;</xsl:text> 18 + </xsl:if> 19 + </xsl:template> 20 + 21 + </xsl:stylesheet>
+42 -4
tools/lib/traceevent/Makefile
··· 50 50 man_dir_SQ = '$(subst ','\'',$(man_dir))' 51 51 pkgconfig_dir ?= $(word 1,$(shell $(PKG_CONFIG) \ 52 52 --variable pc_path pkg-config | tr ":" " ")) 53 + includedir_relative = traceevent 54 + includedir = $(prefix)/include/$(includedir_relative) 55 + includedir_SQ = '$(subst ','\'',$(includedir))' 53 56 54 57 export man_dir man_dir_SQ INSTALL 55 58 export DESTDIR DESTDIR_SQ 59 + export EVENT_PARSE_VERSION 56 60 57 61 set_plugin_dir := 1 58 62 ··· 283 279 cp -f ${PKG_CONFIG_FILE}.template ${PKG_CONFIG_FILE}; \ 284 280 sed -i "s|INSTALL_PREFIX|${1}|g" ${PKG_CONFIG_FILE}; \ 285 281 sed -i "s|LIB_VERSION|${EVENT_PARSE_VERSION}|g" ${PKG_CONFIG_FILE}; \ 282 + sed -i "s|LIB_DIR|${libdir}|g" ${PKG_CONFIG_FILE}; \ 283 + sed -i "s|HEADER_DIR|$(includedir)|g" ${PKG_CONFIG_FILE}; \ 286 284 $(call do_install,$(PKG_CONFIG_FILE),$(pkgconfig_dir),644); \ 287 285 else \ 288 286 (echo Failed to locate pkg-config directory) 1>&2; \ ··· 306 300 307 301 install_headers: 308 302 $(call QUIET_INSTALL, headers) \ 309 - $(call do_install,event-parse.h,$(prefix)/include/traceevent,644); \ 310 - $(call do_install,event-utils.h,$(prefix)/include/traceevent,644); \ 311 - $(call do_install,trace-seq.h,$(prefix)/include/traceevent,644); \ 312 - $(call do_install,kbuffer.h,$(prefix)/include/traceevent,644) 303 + $(call do_install,event-parse.h,$(DESTDIR)$(includedir_SQ),644); \ 304 + $(call do_install,event-utils.h,$(DESTDIR)$(includedir_SQ),644); \ 305 + $(call do_install,trace-seq.h,$(DESTDIR)$(includedir_SQ),644); \ 306 + $(call do_install,kbuffer.h,$(DESTDIR)$(includedir_SQ),644) 313 307 314 308 install: install_lib 315 309 ··· 319 313 $(RM) TRACEEVENT-CFLAGS tags TAGS; \ 320 314 $(RM) $(PKG_CONFIG_FILE) 321 315 316 + PHONY += doc 317 + doc: 318 + $(call descend,Documentation) 319 + 320 + PHONY += doc-clean 321 + doc-clean: 322 + $(call descend,Documentation,clean) 323 + 324 + PHONY += doc-install 325 + doc-install: 326 + $(call descend,Documentation,install) 327 + 328 + PHONY += doc-uninstall 329 + doc-uninstall: 330 + $(call descend,Documentation,uninstall) 331 + 332 + PHONY += help 333 + help: 334 + @echo 'Possible targets:' 335 + @echo'' 336 + @echo ' all - default, compile the library and the'\ 337 + 'plugins' 338 + @echo ' plugins - compile the plugins' 339 + @echo ' install - install the library, the plugins,'\ 340 + 'the header and pkgconfig files' 341 + @echo ' clean - clean the library and the plugins object files' 342 + @echo ' doc - compile the documentation files - man'\ 343 + 'and html pages, in the Documentation directory' 344 + @echo ' doc-clean - clean the documentation files' 345 + @echo ' doc-install - install the man pages' 346 + @echo ' doc-uninstall - uninstall the man pages' 347 + @echo'' 322 348 PHONY += force plugins 323 349 force: 324 350
+2 -2
tools/lib/traceevent/libtraceevent.pc.template
··· 1 1 prefix=INSTALL_PREFIX 2 - libdir=${prefix}/lib64 3 - includedir=${prefix}/include/traceevent 2 + libdir=LIB_DIR 3 + includedir=HEADER_DIR 4 4 5 5 Name: libtraceevent 6 6 URL: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+1 -1
tools/pci/Makefile
··· 47 47 48 48 install: $(ALL_PROGRAMS) 49 49 install -d -m 755 $(DESTDIR)$(bindir); \ 50 - for program in $(ALL_PROGRAMS); do \ 50 + for program in $(ALL_PROGRAMS) pcitest.sh; do \ 51 51 install $$program $(DESTDIR)$(bindir); \ 52 52 done; \ 53 53 for script in $(ALL_SCRIPTS); do \
+12
tools/perf/Documentation/perf-list.txt
··· 199 199 200 200 perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ... 201 201 202 + EVENT QUALIFIERS: 203 + 204 + It is also possible to add extra qualifiers to an event: 205 + 206 + percore: 207 + 208 + Sums up the event counts for all hardware threads in a core, e.g.: 209 + 210 + 211 + perf stat -e cpu/event=0,umask=0x3,percore=1/ 212 + 213 + 202 214 EVENT GROUPS 203 215 ------------ 204 216
+7 -1
tools/perf/Documentation/perf-record.txt
··· 406 406 --intr-regs=ax,bx. The list of register is architecture dependent. 407 407 408 408 --user-regs:: 409 - Capture user registers at sample time. Same arguments as -I. 409 + Similar to -I, but capture user registers at sample time. To list the available 410 + user registers use --user-regs=\?. 410 411 411 412 --running-time:: 412 413 Record running and enabled time for read events (:S) ··· 478 477 Also at some cases executing less output write syscalls with bigger data size 479 478 can take less time than executing more output write syscalls with smaller data 480 479 size thus lowering runtime profiling overhead. 480 + 481 + -z:: 482 + --compression-level[=n]:: 483 + Produce compressed trace using specified level n (default: 1 - fastest compression, 484 + 22 - smallest trace) 481 485 482 486 --all-kernel:: 483 487 Configure all used events to run in kernel space.
+4
tools/perf/Documentation/perf-stat.txt
··· 43 43 param1 and param2 are defined as formats for the PMU in 44 44 /sys/bus/event_source/devices/<pmu>/format/* 45 45 46 + 'percore' is a event qualifier that sums up the event counts for both 47 + hardware threads in a core. For example: 48 + perf stat -A -a -e cpu/event,percore=1/,otherevent ... 49 + 46 50 - a symbolically formed event like 'pmu/config=M,config1=N,config2=K/' 47 51 where M, N, K are numbers (in decimal, hex, octal format). 48 52 Acceptable values for each of 'config', 'config1' and 'config2'
+24
tools/perf/Documentation/perf.data-file-format.txt
··· 272 272 273 273 Two uint64_t for the time of first sample and the time of last sample. 274 274 275 + HEADER_COMPRESSED = 27, 276 + 277 + struct { 278 + u32 version; 279 + u32 type; 280 + u32 level; 281 + u32 ratio; 282 + u32 mmap_len; 283 + }; 284 + 285 + Indicates that trace contains records of PERF_RECORD_COMPRESSED type 286 + that have perf_events records in compressed form. 287 + 275 288 other bits are reserved and should ignored for now 276 289 HEADER_FEAT_BITS = 256, 277 290 ··· 449 436 450 437 Describes a header feature. These are records used in pipe-mode that 451 438 contain information that otherwise would be in perf.data file's header. 439 + 440 + PERF_RECORD_COMPRESSED = 81, 441 + 442 + struct compressed_event { 443 + struct perf_event_header header; 444 + char data[]; 445 + }; 446 + 447 + The header is followed by compressed data frame that can be decompressed 448 + into array of perf trace records. The size of the entire compressed event 449 + record including the header is limited by the max value of header.size. 452 450 453 451 Event types 454 452
+2
tools/perf/Documentation/perf.txt
··· 22 22 verbose - general debug messages 23 23 ordered-events - ordered events object debug messages 24 24 data-convert - data convert command debug messages 25 + stderr - write debug output (option -v) to stderr 26 + in browser mode 25 27 26 28 --buildid-dir:: 27 29 Setup buildid cache directory. It has higher priority than
+24 -2
tools/perf/arch/x86/include/perf_regs.h
··· 8 8 9 9 void perf_regs_load(u64 *regs); 10 10 11 + #define PERF_REGS_MAX PERF_REG_X86_XMM_MAX 12 + #define PERF_XMM_REGS_MASK (~((1ULL << PERF_REG_X86_XMM0) - 1)) 11 13 #ifndef HAVE_ARCH_X86_64_SUPPORT 12 14 #define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1) 13 - #define PERF_REGS_MAX PERF_REG_X86_32_MAX 14 15 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32 15 16 #else 16 17 #define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ ··· 19 18 (1ULL << PERF_REG_X86_FS) | \ 20 19 (1ULL << PERF_REG_X86_GS)) 21 20 #define PERF_REGS_MASK (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~REG_NOSUPPORT) 22 - #define PERF_REGS_MAX PERF_REG_X86_64_MAX 23 21 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64 24 22 #endif 25 23 #define PERF_REG_IP PERF_REG_X86_IP ··· 77 77 case PERF_REG_X86_R15: 78 78 return "R15"; 79 79 #endif /* HAVE_ARCH_X86_64_SUPPORT */ 80 + 81 + #define XMM(x) \ 82 + case PERF_REG_X86_XMM ## x: \ 83 + case PERF_REG_X86_XMM ## x + 1: \ 84 + return "XMM" #x; 85 + XMM(0) 86 + XMM(1) 87 + XMM(2) 88 + XMM(3) 89 + XMM(4) 90 + XMM(5) 91 + XMM(6) 92 + XMM(7) 93 + XMM(8) 94 + XMM(9) 95 + XMM(10) 96 + XMM(11) 97 + XMM(12) 98 + XMM(13) 99 + XMM(14) 100 + XMM(15) 101 + #undef XMM 80 102 default: 81 103 return NULL; 82 104 }
+44
tools/perf/arch/x86/util/perf_regs.c
··· 31 31 SMPL_REG(R14, PERF_REG_X86_R14), 32 32 SMPL_REG(R15, PERF_REG_X86_R15), 33 33 #endif 34 + SMPL_REG2(XMM0, PERF_REG_X86_XMM0), 35 + SMPL_REG2(XMM1, PERF_REG_X86_XMM1), 36 + SMPL_REG2(XMM2, PERF_REG_X86_XMM2), 37 + SMPL_REG2(XMM3, PERF_REG_X86_XMM3), 38 + SMPL_REG2(XMM4, PERF_REG_X86_XMM4), 39 + SMPL_REG2(XMM5, PERF_REG_X86_XMM5), 40 + SMPL_REG2(XMM6, PERF_REG_X86_XMM6), 41 + SMPL_REG2(XMM7, PERF_REG_X86_XMM7), 42 + SMPL_REG2(XMM8, PERF_REG_X86_XMM8), 43 + SMPL_REG2(XMM9, PERF_REG_X86_XMM9), 44 + SMPL_REG2(XMM10, PERF_REG_X86_XMM10), 45 + SMPL_REG2(XMM11, PERF_REG_X86_XMM11), 46 + SMPL_REG2(XMM12, PERF_REG_X86_XMM12), 47 + SMPL_REG2(XMM13, PERF_REG_X86_XMM13), 48 + SMPL_REG2(XMM14, PERF_REG_X86_XMM14), 49 + SMPL_REG2(XMM15, PERF_REG_X86_XMM15), 34 50 SMPL_REG_END 35 51 }; 36 52 ··· 269 253 (int)(rm[5].rm_eo - rm[5].rm_so), old_op + rm[5].rm_so); 270 254 271 255 return SDT_ARG_VALID; 256 + } 257 + 258 + uint64_t arch__intr_reg_mask(void) 259 + { 260 + struct perf_event_attr attr = { 261 + .type = PERF_TYPE_HARDWARE, 262 + .config = PERF_COUNT_HW_CPU_CYCLES, 263 + .sample_type = PERF_SAMPLE_REGS_INTR, 264 + .sample_regs_intr = PERF_XMM_REGS_MASK, 265 + .precise_ip = 1, 266 + .disabled = 1, 267 + .exclude_kernel = 1, 268 + }; 269 + int fd; 270 + /* 271 + * In an unnamed union, init it here to build on older gcc versions 272 + */ 273 + attr.sample_period = 1; 274 + 275 + event_attr_init(&attr); 276 + 277 + fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 278 + if (fd != -1) { 279 + close(fd); 280 + return (PERF_XMM_REGS_MASK | PERF_REGS_MASK); 281 + } 282 + 283 + return PERF_REGS_MASK; 272 284 }
+2 -2
tools/perf/builtin-annotate.c
··· 159 159 struct perf_evsel *evsel = iter->evsel; 160 160 int err; 161 161 162 - hist__account_cycles(sample->branch_stack, al, sample, false); 163 - 164 162 bi = he->branch_info; 165 163 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); 166 164 ··· 196 198 197 199 if (a.map != NULL) 198 200 a.map->dso->hit = 1; 201 + 202 + hist__account_cycles(sample->branch_stack, al, sample, false); 199 203 200 204 ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann); 201 205 return ret;
+4
tools/perf/builtin-inject.c
··· 837 837 if (inject.session == NULL) 838 838 return -1; 839 839 840 + if (zstd_init(&(inject.session->zstd_data), 0) < 0) 841 + pr_warning("Decompression initialization failed.\n"); 842 + 840 843 if (inject.build_ids) { 841 844 /* 842 845 * to make sure the mmap records are ordered correctly ··· 870 867 ret = __cmd_inject(&inject); 871 868 872 869 out_delete: 870 + zstd_fini(&(inject.session->zstd_data)); 873 871 perf_session__delete(inject.session); 874 872 return ret; 875 873 }
+197 -32
tools/perf/builtin-record.c
··· 133 133 return 0; 134 134 } 135 135 136 + static int record__aio_enabled(struct record *rec); 137 + static int record__comp_enabled(struct record *rec); 138 + static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, 139 + void *src, size_t src_size); 140 + 136 141 #ifdef HAVE_AIO_SUPPORT 137 142 static int record__aio_write(struct aiocb *cblock, int trace_fd, 138 143 void *buf, size_t size, off_t off) ··· 188 183 if (rem_size == 0) { 189 184 cblock->aio_fildes = -1; 190 185 /* 191 - * md->refcount is incremented in perf_mmap__push() for 192 - * every enqueued aio write request so decrement it because 193 - * the request is now complete. 186 + * md->refcount is incremented in record__aio_pushfn() for 187 + * every aio write request started in record__aio_push() so 188 + * decrement it because the request is now complete. 194 189 */ 195 190 perf_mmap__put(md); 196 191 rc = 1; ··· 245 240 } while (1); 246 241 } 247 242 248 - static int record__aio_pushfn(void *to, struct aiocb *cblock, void *bf, size_t size, off_t off) 243 + struct record_aio { 244 + struct record *rec; 245 + void *data; 246 + size_t size; 247 + }; 248 + 249 + static int record__aio_pushfn(struct perf_mmap *map, void *to, void *buf, size_t size) 249 250 { 250 - struct record *rec = to; 251 - int ret, trace_fd = rec->session->data->file.fd; 251 + struct record_aio *aio = to; 252 + 253 + /* 254 + * map->base data pointed by buf is copied into free map->aio.data[] buffer 255 + * to release space in the kernel buffer as fast as possible, calling 256 + * perf_mmap__consume() from perf_mmap__push() function. 257 + * 258 + * That lets the kernel to proceed with storing more profiling data into 259 + * the kernel buffer earlier than other per-cpu kernel buffers are handled. 260 + * 261 + * Coping can be done in two steps in case the chunk of profiling data 262 + * crosses the upper bound of the kernel buffer. In this case we first move 263 + * part of data from map->start till the upper bound and then the reminder 264 + * from the beginning of the kernel buffer till the end of the data chunk. 265 + */ 266 + 267 + if (record__comp_enabled(aio->rec)) { 268 + size = zstd_compress(aio->rec->session, aio->data + aio->size, 269 + perf_mmap__mmap_len(map) - aio->size, 270 + buf, size); 271 + } else { 272 + memcpy(aio->data + aio->size, buf, size); 273 + } 274 + 275 + if (!aio->size) { 276 + /* 277 + * Increment map->refcount to guard map->aio.data[] buffer 278 + * from premature deallocation because map object can be 279 + * released earlier than aio write request started on 280 + * map->aio.data[] buffer is complete. 281 + * 282 + * perf_mmap__put() is done at record__aio_complete() 283 + * after started aio request completion or at record__aio_push() 284 + * if the request failed to start. 285 + */ 286 + perf_mmap__get(map); 287 + } 288 + 289 + aio->size += size; 290 + 291 + return size; 292 + } 293 + 294 + static int record__aio_push(struct record *rec, struct perf_mmap *map, off_t *off) 295 + { 296 + int ret, idx; 297 + int trace_fd = rec->session->data->file.fd; 298 + struct record_aio aio = { .rec = rec, .size = 0 }; 299 + 300 + /* 301 + * Call record__aio_sync() to wait till map->aio.data[] buffer 302 + * becomes available after previous aio write operation. 303 + */ 304 + 305 + idx = record__aio_sync(map, false); 306 + aio.data = map->aio.data[idx]; 307 + ret = perf_mmap__push(map, &aio, record__aio_pushfn); 308 + if (ret != 0) /* ret > 0 - no data, ret < 0 - error */ 309 + return ret; 252 310 253 311 rec->samples++; 254 - 255 - ret = record__aio_write(cblock, trace_fd, bf, size, off); 312 + ret = record__aio_write(&(map->aio.cblocks[idx]), trace_fd, aio.data, aio.size, *off); 256 313 if (!ret) { 257 - rec->bytes_written += size; 314 + *off += aio.size; 315 + rec->bytes_written += aio.size; 258 316 if (switch_output_size(rec)) 259 317 trigger_hit(&switch_output_trigger); 318 + } else { 319 + /* 320 + * Decrement map->refcount incremented in record__aio_pushfn() 321 + * back if record__aio_write() operation failed to start, otherwise 322 + * map->refcount is decremented in record__aio_complete() after 323 + * aio write operation finishes successfully. 324 + */ 325 + perf_mmap__put(map); 260 326 } 261 327 262 328 return ret; ··· 349 273 struct perf_evlist *evlist = rec->evlist; 350 274 struct perf_mmap *maps = evlist->mmap; 351 275 352 - if (!rec->opts.nr_cblocks) 276 + if (!record__aio_enabled(rec)) 353 277 return; 354 278 355 279 for (i = 0; i < evlist->nr_mmaps; i++) { ··· 383 307 #else /* HAVE_AIO_SUPPORT */ 384 308 static int nr_cblocks_max = 0; 385 309 386 - static int record__aio_sync(struct perf_mmap *md __maybe_unused, bool sync_all __maybe_unused) 387 - { 388 - return -1; 389 - } 390 - 391 - static int record__aio_pushfn(void *to __maybe_unused, struct aiocb *cblock __maybe_unused, 392 - void *bf __maybe_unused, size_t size __maybe_unused, off_t off __maybe_unused) 310 + static int record__aio_push(struct record *rec __maybe_unused, struct perf_mmap *map __maybe_unused, 311 + off_t *off __maybe_unused) 393 312 { 394 313 return -1; 395 314 } ··· 443 372 return 0; 444 373 } 445 374 375 + #ifdef HAVE_ZSTD_SUPPORT 376 + static unsigned int comp_level_default = 1; 377 + 378 + static int record__parse_comp_level(const struct option *opt, const char *str, int unset) 379 + { 380 + struct record_opts *opts = opt->value; 381 + 382 + if (unset) { 383 + opts->comp_level = 0; 384 + } else { 385 + if (str) 386 + opts->comp_level = strtol(str, NULL, 0); 387 + if (!opts->comp_level) 388 + opts->comp_level = comp_level_default; 389 + } 390 + 391 + return 0; 392 + } 393 + #endif 394 + static unsigned int comp_level_max = 22; 395 + 396 + static int record__comp_enabled(struct record *rec) 397 + { 398 + return rec->opts.comp_level > 0; 399 + } 400 + 446 401 static int process_synthesized_event(struct perf_tool *tool, 447 402 union perf_event *event, 448 403 struct perf_sample *sample __maybe_unused, ··· 481 384 static int record__pushfn(struct perf_mmap *map, void *to, void *bf, size_t size) 482 385 { 483 386 struct record *rec = to; 387 + 388 + if (record__comp_enabled(rec)) { 389 + size = zstd_compress(rec->session, map->data, perf_mmap__mmap_len(map), bf, size); 390 + bf = map->data; 391 + } 484 392 485 393 rec->samples++; 486 394 return record__write(rec, map, bf, size); ··· 684 582 opts->auxtrace_mmap_pages, 685 583 opts->auxtrace_snapshot_mode, 686 584 opts->nr_cblocks, opts->affinity, 687 - opts->mmap_flush) < 0) { 585 + opts->mmap_flush, opts->comp_level) < 0) { 688 586 if (errno == EPERM) { 689 587 pr_err("Permission error mapping pages.\n" 690 588 "Consider increasing " ··· 873 771 } 874 772 } 875 773 774 + static size_t process_comp_header(void *record, size_t increment) 775 + { 776 + struct compressed_event *event = record; 777 + size_t size = sizeof(*event); 778 + 779 + if (increment) { 780 + event->header.size += increment; 781 + return increment; 782 + } 783 + 784 + event->header.type = PERF_RECORD_COMPRESSED; 785 + event->header.size = size; 786 + 787 + return size; 788 + } 789 + 790 + static size_t zstd_compress(struct perf_session *session, void *dst, size_t dst_size, 791 + void *src, size_t src_size) 792 + { 793 + size_t compressed; 794 + size_t max_record_size = PERF_SAMPLE_MAX_SIZE - sizeof(struct compressed_event) - 1; 795 + 796 + compressed = zstd_compress_stream_to_records(&session->zstd_data, dst, dst_size, src, src_size, 797 + max_record_size, process_comp_header); 798 + 799 + session->bytes_transferred += src_size; 800 + session->bytes_compressed += compressed; 801 + 802 + return compressed; 803 + } 804 + 876 805 static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, 877 806 bool overwrite, bool synch) 878 807 { ··· 912 779 int rc = 0; 913 780 struct perf_mmap *maps; 914 781 int trace_fd = rec->data.file.fd; 915 - off_t off; 782 + off_t off = 0; 916 783 917 784 if (!evlist) 918 785 return 0; ··· 938 805 map->flush = 1; 939 806 } 940 807 if (!record__aio_enabled(rec)) { 941 - if (perf_mmap__push(map, rec, record__pushfn) != 0) { 808 + if (perf_mmap__push(map, rec, record__pushfn) < 0) { 942 809 if (synch) 943 810 map->flush = flush; 944 811 rc = -1; 945 812 goto out; 946 813 } 947 814 } else { 948 - int idx; 949 - /* 950 - * Call record__aio_sync() to wait till map->data buffer 951 - * becomes available after previous aio write request. 952 - */ 953 - idx = record__aio_sync(map, false); 954 - if (perf_mmap__aio_push(map, rec, idx, record__aio_pushfn, &off) != 0) { 815 + if (record__aio_push(rec, map, &off) < 0) { 955 816 record__aio_set_pos(trace_fd, off); 956 817 if (synch) 957 818 map->flush = flush; ··· 1015 888 perf_header__clear_feat(&session->header, HEADER_CLOCKID); 1016 889 1017 890 perf_header__clear_feat(&session->header, HEADER_DIR_FORMAT); 891 + if (!record__comp_enabled(rec)) 892 + perf_header__clear_feat(&session->header, HEADER_COMPRESSED); 1018 893 1019 894 perf_header__clear_feat(&session->header, HEADER_STAT); 1020 895 } ··· 1315 1186 bool disabled = false, draining = false; 1316 1187 struct perf_evlist *sb_evlist = NULL; 1317 1188 int fd; 1189 + float ratio = 0; 1318 1190 1319 1191 atexit(record__sig_exit); 1320 1192 signal(SIGCHLD, sig_handler); ··· 1344 1214 1345 1215 fd = perf_data__fd(data); 1346 1216 rec->session = session; 1217 + 1218 + if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) { 1219 + pr_err("Compression initialization failed.\n"); 1220 + return -1; 1221 + } 1222 + 1223 + session->header.env.comp_type = PERF_COMP_ZSTD; 1224 + session->header.env.comp_level = rec->opts.comp_level; 1347 1225 1348 1226 record__init_features(rec); 1349 1227 ··· 1382 1244 err = -1; 1383 1245 goto out_child; 1384 1246 } 1247 + session->header.env.comp_mmap_len = session->evlist->mmap_len; 1385 1248 1386 1249 err = bpf__apply_obj_config(); 1387 1250 if (err) { ··· 1630 1491 record__mmap_read_all(rec, true); 1631 1492 record__aio_mmap_read_sync(rec); 1632 1493 1494 + if (rec->session->bytes_transferred && rec->session->bytes_compressed) { 1495 + ratio = (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed; 1496 + session->header.env.comp_ratio = ratio + 0.5; 1497 + } 1498 + 1633 1499 if (forks) { 1634 1500 int exit_status; 1635 1501 ··· 1681 1537 else 1682 1538 samples[0] = '\0'; 1683 1539 1684 - fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", 1540 + fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s", 1685 1541 perf_data__size(data) / 1024.0 / 1024.0, 1686 1542 data->path, postfix, samples); 1543 + if (ratio) { 1544 + fprintf(stderr, ", compressed (original %.3f MB, ratio is %.3f)", 1545 + rec->session->bytes_transferred / 1024.0 / 1024.0, 1546 + ratio); 1547 + } 1548 + fprintf(stderr, " ]\n"); 1687 1549 } 1688 1550 1689 1551 out_delete_session: 1552 + zstd_fini(&session->zstd_data); 1690 1553 perf_session__delete(session); 1691 1554 1692 1555 if (!opts->no_bpf_event) ··· 2168 2017 "use per-thread mmaps"), 2169 2018 OPT_CALLBACK_OPTARG('I', "intr-regs", &record.opts.sample_intr_regs, NULL, "any register", 2170 2019 "sample selected machine registers on interrupt," 2171 - " use -I ? to list register names", parse_regs), 2020 + " use '-I?' to list register names", parse_intr_regs), 2172 2021 OPT_CALLBACK_OPTARG(0, "user-regs", &record.opts.sample_user_regs, NULL, "any register", 2173 2022 "sample selected machine registers on interrupt," 2174 - " use -I ? to list register names", parse_regs), 2023 + " use '--user-regs=?' to list register names", parse_user_regs), 2175 2024 OPT_BOOLEAN(0, "running-time", &record.opts.running_time, 2176 2025 "Record running/enabled time of read (:S) events"), 2177 2026 OPT_CALLBACK('k', "clockid", &record.opts, ··· 2219 2068 OPT_CALLBACK(0, "affinity", &record.opts, "node|cpu", 2220 2069 "Set affinity mask of trace reading thread to NUMA node cpu mask or cpu of processed mmap buffer", 2221 2070 record__parse_affinity), 2071 + #ifdef HAVE_ZSTD_SUPPORT 2072 + OPT_CALLBACK_OPTARG('z', "compression-level", &record.opts, &comp_level_default, 2073 + "n", "Compressed records using specified level (default: 1 - fastest compression, 22 - greatest compression)", 2074 + record__parse_comp_level), 2075 + #endif 2222 2076 OPT_END() 2223 2077 }; 2224 2078 ··· 2283 2127 "cgroup monitoring only available in system-wide mode"); 2284 2128 2285 2129 } 2130 + 2131 + if (rec->opts.comp_level != 0) { 2132 + pr_debug("Compression enabled, disabling build id collection at the end of the session.\n"); 2133 + rec->no_buildid = true; 2134 + } 2135 + 2286 2136 if (rec->opts.record_switch_events && 2287 2137 !perf_can_record_switch_events()) { 2288 2138 ui__error("kernel does not support recording context switch events\n"); ··· 2434 2272 2435 2273 if (rec->opts.nr_cblocks > nr_cblocks_max) 2436 2274 rec->opts.nr_cblocks = nr_cblocks_max; 2437 - if (verbose > 0) 2438 - pr_info("nr_cblocks: %d\n", rec->opts.nr_cblocks); 2275 + pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks); 2439 2276 2440 2277 pr_debug("affinity: %s\n", affinity_tags[rec->opts.affinity]); 2441 2278 pr_debug("mmap flush: %d\n", rec->opts.mmap_flush); 2279 + 2280 + if (rec->opts.comp_level > comp_level_max) 2281 + rec->opts.comp_level = comp_level_max; 2282 + pr_debug("comp level: %d\n", rec->opts.comp_level); 2442 2283 2443 2284 err = __cmd_record(&record, argc, argv); 2444 2285 out:
+9 -7
tools/perf/builtin-report.c
··· 136 136 if (!ui__has_annotation() && !rep->symbol_ipc) 137 137 return 0; 138 138 139 - hist__account_cycles(sample->branch_stack, al, sample, 140 - rep->nonany_branch_mode); 141 - 142 139 if (sort__mode == SORT_MODE__BRANCH) { 143 140 bi = he->branch_info; 144 141 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); ··· 177 180 178 181 if (!ui__has_annotation() && !rep->symbol_ipc) 179 182 return 0; 180 - 181 - hist__account_cycles(sample->branch_stack, al, sample, 182 - rep->nonany_branch_mode); 183 183 184 184 bi = he->branch_info; 185 185 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); ··· 275 281 276 282 if (al.map != NULL) 277 283 al.map->dso->hit = 1; 284 + 285 + if (ui__has_annotation() || rep->symbol_ipc) { 286 + hist__account_cycles(sample->branch_stack, &al, sample, 287 + rep->nonany_branch_mode); 288 + } 278 289 279 290 ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep); 280 291 if (ret < 0) ··· 1258 1259 if (session == NULL) 1259 1260 return -1; 1260 1261 1262 + if (zstd_init(&(session->zstd_data), 0) < 0) 1263 + pr_warning("Decompression initialization failed. Reported data may be incomplete.\n"); 1264 + 1261 1265 if (report.queue_size) { 1262 1266 ordered_events__set_alloc_size(&session->ordered_events, 1263 1267 report.queue_size); ··· 1451 1449 error: 1452 1450 if (report.ptime_range) 1453 1451 zfree(&report.ptime_range); 1454 - 1452 + zstd_fini(&(session->zstd_data)); 1455 1453 perf_session__delete(session); 1456 1454 return ret; 1457 1455 }
+21
tools/perf/builtin-stat.c
··· 847 847 return perf_stat__get_aggr(config, perf_stat__get_core, map, idx); 848 848 } 849 849 850 + static bool term_percore_set(void) 851 + { 852 + struct perf_evsel *counter; 853 + 854 + evlist__for_each_entry(evsel_list, counter) { 855 + if (counter->percore) 856 + return true; 857 + } 858 + 859 + return false; 860 + } 861 + 850 862 static int perf_stat_init_aggr_mode(void) 851 863 { 852 864 int nr; ··· 879 867 stat_config.aggr_get_id = perf_stat__get_core_cached; 880 868 break; 881 869 case AGGR_NONE: 870 + if (term_percore_set()) { 871 + if (cpu_map__build_core_map(evsel_list->cpus, 872 + &stat_config.aggr_map)) { 873 + perror("cannot build core map"); 874 + return -1; 875 + } 876 + stat_config.aggr_get_id = perf_stat__get_core_cached; 877 + } 878 + break; 882 879 case AGGR_GLOBAL: 883 880 case AGGR_THREAD: 884 881 case AGGR_UNSET:
+1
tools/perf/perf.h
··· 86 86 int nr_cblocks; 87 87 int affinity; 88 88 int mmap_flush; 89 + unsigned int comp_level; 89 90 }; 90 91 91 92 enum perf_affinity {
+179
tools/perf/pmu-events/arch/arm64/arm/cortex-a57-a72/core-imp-def.json
··· 1 + [ 2 + { 3 + "ArchStdEvent": "L1D_CACHE_RD", 4 + }, 5 + { 6 + "ArchStdEvent": "L1D_CACHE_WR", 7 + }, 8 + { 9 + "ArchStdEvent": "L1D_CACHE_REFILL_RD", 10 + }, 11 + { 12 + "ArchStdEvent": "L1D_CACHE_REFILL_WR", 13 + }, 14 + { 15 + "ArchStdEvent": "L1D_CACHE_WB_VICTIM", 16 + }, 17 + { 18 + "ArchStdEvent": "L1D_CACHE_WB_CLEAN", 19 + }, 20 + { 21 + "ArchStdEvent": "L1D_CACHE_INVAL", 22 + }, 23 + { 24 + "ArchStdEvent": "L1D_TLB_REFILL_RD", 25 + }, 26 + { 27 + "ArchStdEvent": "L1D_TLB_REFILL_WR", 28 + }, 29 + { 30 + "ArchStdEvent": "L2D_CACHE_RD", 31 + }, 32 + { 33 + "ArchStdEvent": "L2D_CACHE_WR", 34 + }, 35 + { 36 + "ArchStdEvent": "L2D_CACHE_REFILL_RD", 37 + }, 38 + { 39 + "ArchStdEvent": "L2D_CACHE_REFILL_WR", 40 + }, 41 + { 42 + "ArchStdEvent": "L2D_CACHE_WB_VICTIM", 43 + }, 44 + { 45 + "ArchStdEvent": "L2D_CACHE_WB_CLEAN", 46 + }, 47 + { 48 + "ArchStdEvent": "L2D_CACHE_INVAL", 49 + }, 50 + { 51 + "ArchStdEvent": "BUS_ACCESS_RD", 52 + }, 53 + { 54 + "ArchStdEvent": "BUS_ACCESS_WR", 55 + }, 56 + { 57 + "ArchStdEvent": "BUS_ACCESS_SHARED", 58 + }, 59 + { 60 + "ArchStdEvent": "BUS_ACCESS_NOT_SHARED", 61 + }, 62 + { 63 + "ArchStdEvent": "BUS_ACCESS_NORMAL", 64 + }, 65 + { 66 + "ArchStdEvent": "BUS_ACCESS_PERIPH", 67 + }, 68 + { 69 + "ArchStdEvent": "MEM_ACCESS_RD", 70 + }, 71 + { 72 + "ArchStdEvent": "MEM_ACCESS_WR", 73 + }, 74 + { 75 + "ArchStdEvent": "UNALIGNED_LD_SPEC", 76 + }, 77 + { 78 + "ArchStdEvent": "UNALIGNED_ST_SPEC", 79 + }, 80 + { 81 + "ArchStdEvent": "UNALIGNED_LDST_SPEC", 82 + }, 83 + { 84 + "ArchStdEvent": "LDREX_SPEC", 85 + }, 86 + { 87 + "ArchStdEvent": "STREX_PASS_SPEC", 88 + }, 89 + { 90 + "ArchStdEvent": "STREX_FAIL_SPEC", 91 + }, 92 + { 93 + "ArchStdEvent": "LD_SPEC", 94 + }, 95 + { 96 + "ArchStdEvent": "ST_SPEC", 97 + }, 98 + { 99 + "ArchStdEvent": "LDST_SPEC", 100 + }, 101 + { 102 + "ArchStdEvent": "DP_SPEC", 103 + }, 104 + { 105 + "ArchStdEvent": "ASE_SPEC", 106 + }, 107 + { 108 + "ArchStdEvent": "VFP_SPEC", 109 + }, 110 + { 111 + "ArchStdEvent": "PC_WRITE_SPEC", 112 + }, 113 + { 114 + "ArchStdEvent": "CRYPTO_SPEC", 115 + }, 116 + { 117 + "ArchStdEvent": "BR_IMMED_SPEC", 118 + }, 119 + { 120 + "ArchStdEvent": "BR_RETURN_SPEC", 121 + }, 122 + { 123 + "ArchStdEvent": "BR_INDIRECT_SPEC", 124 + }, 125 + { 126 + "ArchStdEvent": "ISB_SPEC", 127 + }, 128 + { 129 + "ArchStdEvent": "DSB_SPEC", 130 + }, 131 + { 132 + "ArchStdEvent": "DMB_SPEC", 133 + }, 134 + { 135 + "ArchStdEvent": "EXC_UNDEF", 136 + }, 137 + { 138 + "ArchStdEvent": "EXC_SVC", 139 + }, 140 + { 141 + "ArchStdEvent": "EXC_PABORT", 142 + }, 143 + { 144 + "ArchStdEvent": "EXC_DABORT", 145 + }, 146 + { 147 + "ArchStdEvent": "EXC_IRQ", 148 + }, 149 + { 150 + "ArchStdEvent": "EXC_FIQ", 151 + }, 152 + { 153 + "ArchStdEvent": "EXC_SMC", 154 + }, 155 + { 156 + "ArchStdEvent": "EXC_HVC", 157 + }, 158 + { 159 + "ArchStdEvent": "EXC_TRAP_PABORT", 160 + }, 161 + { 162 + "ArchStdEvent": "EXC_TRAP_DABORT", 163 + }, 164 + { 165 + "ArchStdEvent": "EXC_TRAP_OTHER", 166 + }, 167 + { 168 + "ArchStdEvent": "EXC_TRAP_IRQ", 169 + }, 170 + { 171 + "ArchStdEvent": "EXC_TRAP_FIQ", 172 + }, 173 + { 174 + "ArchStdEvent": "RC_LD_SPEC", 175 + }, 176 + { 177 + "ArchStdEvent": "RC_ST_SPEC", 178 + }, 179 + ]
+4 -1
tools/perf/pmu-events/arch/arm64/mapfile.csv
··· 12 12 # 13 13 # 14 14 #Family-model,Version,Filename,EventType 15 - 0x00000000410fd03[[:xdigit:]],v1,arm/cortex-a53,core 15 + 0x00000000410fd030,v1,arm/cortex-a53,core 16 + 0x00000000420f1000,v1,arm/cortex-a53,core 17 + 0x00000000410fd070,v1,arm/cortex-a57-a72,core 18 + 0x00000000410fd080,v1,arm/cortex-a57-a72,core 16 19 0x00000000420f5160,v1,cavium/thunderx2,core 17 20 0x00000000430f0af0,v1,cavium/thunderx2,core 18 21 0x00000000480fd010,v1,hisilicon/hip08,core
+1 -1
tools/perf/pmu-events/jevents.c
··· 235 235 { "iMPH-U", "uncore_arb" }, 236 236 { "CPU-M-CF", "cpum_cf" }, 237 237 { "CPU-M-SF", "cpum_sf" }, 238 + { "UPI LL", "uncore_upi" }, 238 239 {} 239 240 }; 240 241 ··· 415 414 char *metric_name, char *metric_group) 416 415 { 417 416 struct event_struct *es; 418 - struct stat *sb = data; 419 417 420 418 es = malloc(sizeof(*es)); 421 419 if (!es)
+333 -7
tools/perf/scripts/python/exported-sql-viewer.py
··· 456 456 self.query_done = False; 457 457 self.child_count = 0 458 458 self.child_items = [] 459 + if parent_item: 460 + self.level = parent_item.level + 1 461 + else: 462 + self.level = 0 459 463 460 464 def getChildItem(self, row): 461 465 return self.child_items[row] ··· 881 877 super(TreeWindowBase, self).__init__(parent) 882 878 883 879 self.model = None 884 - self.view = None 885 880 self.find_bar = None 881 + 882 + self.view = QTreeView() 883 + self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) 884 + self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard 885 + 886 + self.context_menu = TreeContextMenu(self.view) 886 887 887 888 def DisplayFound(self, ids): 888 889 if not len(ids): ··· 930 921 931 922 self.model = LookupCreateModel("Context-Sensitive Call Graph", lambda x=glb: CallGraphModel(x)) 932 923 933 - self.view = QTreeView() 934 924 self.view.setModel(self.model) 935 925 936 926 for c, w in ((0, 250), (1, 100), (2, 60), (3, 70), (4, 70), (5, 100)): ··· 952 944 953 945 self.model = LookupCreateModel("Call Tree", lambda x=glb: CallTreeModel(x)) 954 946 955 - self.view = QTreeView() 956 947 self.view.setModel(self.model) 957 948 958 949 for c, w in ((0, 230), (1, 100), (2, 100), (3, 70), (4, 70), (5, 100)): ··· 1656 1649 1657 1650 self.view = QTreeView() 1658 1651 self.view.setUniformRowHeights(True) 1652 + self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) 1653 + self.view.CopyCellsToClipboard = CopyTreeCellsToClipboard 1659 1654 self.view.setModel(self.model) 1660 1655 1661 1656 self.ResizeColumnsToContents() 1657 + 1658 + self.context_menu = TreeContextMenu(self.view) 1662 1659 1663 1660 self.find_bar = FindBar(self, self, True) 1664 1661 ··· 2272 2261 self.data_model.rowsInserted.disconnect(self.UpdateColumnWidths) 2273 2262 self.ResizeColumnsToContents() 2274 2263 2264 + # Convert value to CSV 2265 + 2266 + def ToCSValue(val): 2267 + if '"' in val: 2268 + val = val.replace('"', '""') 2269 + if "," in val or '"' in val: 2270 + val = '"' + val + '"' 2271 + return val 2272 + 2273 + # Key to sort table model indexes by row / column, assuming fewer than 1000 columns 2274 + 2275 + glb_max_cols = 1000 2276 + 2277 + def RowColumnKey(a): 2278 + return a.row() * glb_max_cols + a.column() 2279 + 2280 + # Copy selected table cells to clipboard 2281 + 2282 + def CopyTableCellsToClipboard(view, as_csv=False, with_hdr=False): 2283 + indexes = sorted(view.selectedIndexes(), key=RowColumnKey) 2284 + idx_cnt = len(indexes) 2285 + if not idx_cnt: 2286 + return 2287 + if idx_cnt == 1: 2288 + with_hdr=False 2289 + min_row = indexes[0].row() 2290 + max_row = indexes[0].row() 2291 + min_col = indexes[0].column() 2292 + max_col = indexes[0].column() 2293 + for i in indexes: 2294 + min_row = min(min_row, i.row()) 2295 + max_row = max(max_row, i.row()) 2296 + min_col = min(min_col, i.column()) 2297 + max_col = max(max_col, i.column()) 2298 + if max_col > glb_max_cols: 2299 + raise RuntimeError("glb_max_cols is too low") 2300 + max_width = [0] * (1 + max_col - min_col) 2301 + for i in indexes: 2302 + c = i.column() - min_col 2303 + max_width[c] = max(max_width[c], len(str(i.data()))) 2304 + text = "" 2305 + pad = "" 2306 + sep = "" 2307 + if with_hdr: 2308 + model = indexes[0].model() 2309 + for col in range(min_col, max_col + 1): 2310 + val = model.headerData(col, Qt.Horizontal) 2311 + if as_csv: 2312 + text += sep + ToCSValue(val) 2313 + sep = "," 2314 + else: 2315 + c = col - min_col 2316 + max_width[c] = max(max_width[c], len(val)) 2317 + width = max_width[c] 2318 + align = model.headerData(col, Qt.Horizontal, Qt.TextAlignmentRole) 2319 + if align & Qt.AlignRight: 2320 + val = val.rjust(width) 2321 + text += pad + sep + val 2322 + pad = " " * (width - len(val)) 2323 + sep = " " 2324 + text += "\n" 2325 + pad = "" 2326 + sep = "" 2327 + last_row = min_row 2328 + for i in indexes: 2329 + if i.row() > last_row: 2330 + last_row = i.row() 2331 + text += "\n" 2332 + pad = "" 2333 + sep = "" 2334 + if as_csv: 2335 + text += sep + ToCSValue(str(i.data())) 2336 + sep = "," 2337 + else: 2338 + width = max_width[i.column() - min_col] 2339 + if i.data(Qt.TextAlignmentRole) & Qt.AlignRight: 2340 + val = str(i.data()).rjust(width) 2341 + else: 2342 + val = str(i.data()) 2343 + text += pad + sep + val 2344 + pad = " " * (width - len(val)) 2345 + sep = " " 2346 + QApplication.clipboard().setText(text) 2347 + 2348 + def CopyTreeCellsToClipboard(view, as_csv=False, with_hdr=False): 2349 + indexes = view.selectedIndexes() 2350 + if not len(indexes): 2351 + return 2352 + 2353 + selection = view.selectionModel() 2354 + 2355 + first = None 2356 + for i in indexes: 2357 + above = view.indexAbove(i) 2358 + if not selection.isSelected(above): 2359 + first = i 2360 + break 2361 + 2362 + if first is None: 2363 + raise RuntimeError("CopyTreeCellsToClipboard internal error") 2364 + 2365 + model = first.model() 2366 + row_cnt = 0 2367 + col_cnt = model.columnCount(first) 2368 + max_width = [0] * col_cnt 2369 + 2370 + indent_sz = 2 2371 + indent_str = " " * indent_sz 2372 + 2373 + expanded_mark_sz = 2 2374 + if sys.version_info[0] == 3: 2375 + expanded_mark = "\u25BC " 2376 + not_expanded_mark = "\u25B6 " 2377 + else: 2378 + expanded_mark = unicode(chr(0xE2) + chr(0x96) + chr(0xBC) + " ", "utf-8") 2379 + not_expanded_mark = unicode(chr(0xE2) + chr(0x96) + chr(0xB6) + " ", "utf-8") 2380 + leaf_mark = " " 2381 + 2382 + if not as_csv: 2383 + pos = first 2384 + while True: 2385 + row_cnt += 1 2386 + row = pos.row() 2387 + for c in range(col_cnt): 2388 + i = pos.sibling(row, c) 2389 + if c: 2390 + n = len(str(i.data())) 2391 + else: 2392 + n = len(str(i.data()).strip()) 2393 + n += (i.internalPointer().level - 1) * indent_sz 2394 + n += expanded_mark_sz 2395 + max_width[c] = max(max_width[c], n) 2396 + pos = view.indexBelow(pos) 2397 + if not selection.isSelected(pos): 2398 + break 2399 + 2400 + text = "" 2401 + pad = "" 2402 + sep = "" 2403 + if with_hdr: 2404 + for c in range(col_cnt): 2405 + val = model.headerData(c, Qt.Horizontal, Qt.DisplayRole).strip() 2406 + if as_csv: 2407 + text += sep + ToCSValue(val) 2408 + sep = "," 2409 + else: 2410 + max_width[c] = max(max_width[c], len(val)) 2411 + width = max_width[c] 2412 + align = model.headerData(c, Qt.Horizontal, Qt.TextAlignmentRole) 2413 + if align & Qt.AlignRight: 2414 + val = val.rjust(width) 2415 + text += pad + sep + val 2416 + pad = " " * (width - len(val)) 2417 + sep = " " 2418 + text += "\n" 2419 + pad = "" 2420 + sep = "" 2421 + 2422 + pos = first 2423 + while True: 2424 + row = pos.row() 2425 + for c in range(col_cnt): 2426 + i = pos.sibling(row, c) 2427 + val = str(i.data()) 2428 + if not c: 2429 + if model.hasChildren(i): 2430 + if view.isExpanded(i): 2431 + mark = expanded_mark 2432 + else: 2433 + mark = not_expanded_mark 2434 + else: 2435 + mark = leaf_mark 2436 + val = indent_str * (i.internalPointer().level - 1) + mark + val.strip() 2437 + if as_csv: 2438 + text += sep + ToCSValue(val) 2439 + sep = "," 2440 + else: 2441 + width = max_width[c] 2442 + if c and i.data(Qt.TextAlignmentRole) & Qt.AlignRight: 2443 + val = val.rjust(width) 2444 + text += pad + sep + val 2445 + pad = " " * (width - len(val)) 2446 + sep = " " 2447 + pos = view.indexBelow(pos) 2448 + if not selection.isSelected(pos): 2449 + break 2450 + text = text.rstrip() + "\n" 2451 + pad = "" 2452 + sep = "" 2453 + 2454 + QApplication.clipboard().setText(text) 2455 + 2456 + def CopyCellsToClipboard(view, as_csv=False, with_hdr=False): 2457 + view.CopyCellsToClipboard(view, as_csv, with_hdr) 2458 + 2459 + def CopyCellsToClipboardHdr(view): 2460 + CopyCellsToClipboard(view, False, True) 2461 + 2462 + def CopyCellsToClipboardCSV(view): 2463 + CopyCellsToClipboard(view, True, True) 2464 + 2465 + # Context menu 2466 + 2467 + class ContextMenu(object): 2468 + 2469 + def __init__(self, view): 2470 + self.view = view 2471 + self.view.setContextMenuPolicy(Qt.CustomContextMenu) 2472 + self.view.customContextMenuRequested.connect(self.ShowContextMenu) 2473 + 2474 + def ShowContextMenu(self, pos): 2475 + menu = QMenu(self.view) 2476 + self.AddActions(menu) 2477 + menu.exec_(self.view.mapToGlobal(pos)) 2478 + 2479 + def AddCopy(self, menu): 2480 + menu.addAction(CreateAction("&Copy selection", "Copy to clipboard", lambda: CopyCellsToClipboardHdr(self.view), self.view)) 2481 + menu.addAction(CreateAction("Copy selection as CS&V", "Copy to clipboard as CSV", lambda: CopyCellsToClipboardCSV(self.view), self.view)) 2482 + 2483 + def AddActions(self, menu): 2484 + self.AddCopy(menu) 2485 + 2486 + class TreeContextMenu(ContextMenu): 2487 + 2488 + def __init__(self, view): 2489 + super(TreeContextMenu, self).__init__(view) 2490 + 2491 + def AddActions(self, menu): 2492 + i = self.view.currentIndex() 2493 + text = str(i.data()).strip() 2494 + if len(text): 2495 + menu.addAction(CreateAction('Copy "' + text + '"', "Copy to clipboard", lambda: QApplication.clipboard().setText(text), self.view)) 2496 + self.AddCopy(menu) 2497 + 2275 2498 # Table window 2276 2499 2277 2500 class TableWindow(QMdiSubWindow, ResizeColumnsToContentsBase): ··· 2524 2279 self.view.verticalHeader().setVisible(False) 2525 2280 self.view.sortByColumn(-1, Qt.AscendingOrder) 2526 2281 self.view.setSortingEnabled(True) 2282 + self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) 2283 + self.view.CopyCellsToClipboard = CopyTableCellsToClipboard 2527 2284 2528 2285 self.ResizeColumnsToContents() 2286 + 2287 + self.context_menu = ContextMenu(self.view) 2529 2288 2530 2289 self.find_bar = FindBar(self, self, True) 2531 2290 ··· 2644 2395 self.view.setModel(self.model) 2645 2396 self.view.setEditTriggers(QAbstractItemView.NoEditTriggers) 2646 2397 self.view.verticalHeader().setVisible(False) 2398 + self.view.setSelectionMode(QAbstractItemView.ContiguousSelection) 2399 + self.view.CopyCellsToClipboard = CopyTableCellsToClipboard 2400 + 2401 + self.context_menu = ContextMenu(self.view) 2647 2402 2648 2403 self.ResizeColumnsToContents() 2649 2404 ··· 2913 2660 2914 2661 self.setCentralWidget(self.text) 2915 2662 2663 + # PostqreSQL server version 2664 + 2665 + def PostqreSQLServerVersion(db): 2666 + query = QSqlQuery(db) 2667 + QueryExec(query, "SELECT VERSION()") 2668 + if query.next(): 2669 + v_str = query.value(0) 2670 + v_list = v_str.strip().split(" ") 2671 + if v_list[0] == "PostgreSQL" and v_list[2] == "on": 2672 + return v_list[1] 2673 + return v_str 2674 + return "Unknown" 2675 + 2676 + # SQLite version 2677 + 2678 + def SQLiteVersion(db): 2679 + query = QSqlQuery(db) 2680 + QueryExec(query, "SELECT sqlite_version()") 2681 + if query.next(): 2682 + return query.value(0) 2683 + return "Unknown" 2684 + 2685 + # About dialog 2686 + 2687 + class AboutDialog(QDialog): 2688 + 2689 + def __init__(self, glb, parent=None): 2690 + super(AboutDialog, self).__init__(parent) 2691 + 2692 + self.setWindowTitle("About Exported SQL Viewer") 2693 + self.setMinimumWidth(300) 2694 + 2695 + pyside_version = "1" if pyside_version_1 else "2" 2696 + 2697 + text = "<pre>" 2698 + text += "Python version: " + sys.version.split(" ")[0] + "\n" 2699 + text += "PySide version: " + pyside_version + "\n" 2700 + text += "Qt version: " + qVersion() + "\n" 2701 + if glb.dbref.is_sqlite3: 2702 + text += "SQLite version: " + SQLiteVersion(glb.db) + "\n" 2703 + else: 2704 + text += "PostqreSQL version: " + PostqreSQLServerVersion(glb.db) + "\n" 2705 + text += "</pre>" 2706 + 2707 + self.text = QTextBrowser() 2708 + self.text.setHtml(text) 2709 + self.text.setReadOnly(True) 2710 + self.text.setOpenExternalLinks(True) 2711 + 2712 + self.vbox = QVBoxLayout() 2713 + self.vbox.addWidget(self.text) 2714 + 2715 + self.setLayout(self.vbox); 2716 + 2916 2717 # Font resize 2917 2718 2918 2719 def ResizeFont(widget, diff): ··· 3039 2732 file_menu.addAction(CreateExitAction(glb.app, self)) 3040 2733 3041 2734 edit_menu = menu.addMenu("&Edit") 2735 + edit_menu.addAction(CreateAction("&Copy", "Copy to clipboard", self.CopyToClipboard, self, QKeySequence.Copy)) 2736 + edit_menu.addAction(CreateAction("Copy as CS&V", "Copy to clipboard as CSV", self.CopyToClipboardCSV, self)) 3042 2737 edit_menu.addAction(CreateAction("&Find...", "Find items", self.Find, self, QKeySequence.Find)) 3043 2738 edit_menu.addAction(CreateAction("Fetch &more records...", "Fetch more records", self.FetchMoreRecords, self, [QKeySequence(Qt.Key_F8)])) 3044 2739 edit_menu.addAction(CreateAction("&Shrink Font", "Make text smaller", self.ShrinkFont, self, [QKeySequence("Ctrl+-")])) ··· 3064 2755 3065 2756 help_menu = menu.addMenu("&Help") 3066 2757 help_menu.addAction(CreateAction("&Exported SQL Viewer Help", "Helpful information", self.Help, self, QKeySequence.HelpContents)) 2758 + help_menu.addAction(CreateAction("&About Exported SQL Viewer", "About this application", self.About, self)) 2759 + 2760 + def Try(self, fn): 2761 + win = self.mdi_area.activeSubWindow() 2762 + if win: 2763 + try: 2764 + fn(win.view) 2765 + except: 2766 + pass 2767 + 2768 + def CopyToClipboard(self): 2769 + self.Try(CopyCellsToClipboardHdr) 2770 + 2771 + def CopyToClipboardCSV(self): 2772 + self.Try(CopyCellsToClipboardCSV) 3067 2773 3068 2774 def Find(self): 3069 2775 win = self.mdi_area.activeSubWindow() ··· 3097 2773 pass 3098 2774 3099 2775 def ShrinkFont(self): 3100 - win = self.mdi_area.activeSubWindow() 3101 - ShrinkFont(win.view) 2776 + self.Try(ShrinkFont) 3102 2777 3103 2778 def EnlargeFont(self): 3104 - win = self.mdi_area.activeSubWindow() 3105 - EnlargeFont(win.view) 2779 + self.Try(EnlargeFont) 3106 2780 3107 2781 def EventMenu(self, events, reports_menu): 3108 2782 branches_events = 0 ··· 3149 2827 3150 2828 def Help(self): 3151 2829 HelpWindow(self.glb, self) 2830 + 2831 + def About(self): 2832 + dialog = AboutDialog(self.glb, self) 2833 + dialog.exec_() 3152 2834 3153 2835 # XED Disassembler 3154 2836
+2 -2
tools/perf/tests/dso-data.c
··· 304 304 /* Make sure we did not leak any file descriptor. */ 305 305 nr_end = open_files_cnt(); 306 306 pr_debug("nr start %ld, nr stop %ld\n", nr, nr_end); 307 - TEST_ASSERT_VAL("failed leadking files", nr == nr_end); 307 + TEST_ASSERT_VAL("failed leaking files", nr == nr_end); 308 308 return 0; 309 309 } 310 310 ··· 380 380 /* Make sure we did not leak any file descriptor. */ 381 381 nr_end = open_files_cnt(); 382 382 pr_debug("nr start %ld, nr stop %ld\n", nr, nr_end); 383 - TEST_ASSERT_VAL("failed leadking files", nr == nr_end); 383 + TEST_ASSERT_VAL("failed leaking files", nr == nr_end); 384 384 return 0; 385 385 }
+1 -1
tools/perf/tests/make
··· 107 107 make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 108 108 make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 109 109 make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 110 - make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1 110 + make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1 NO_LIBZSTD=1 111 111 112 112 # $(run) contains all available tests 113 113 run := make_pure
+34
tools/perf/tests/shell/record+zstd_comp_decomp.sh
··· 1 + #!/bin/sh 2 + # Zstd perf.data compression/decompression 3 + 4 + trace_file=$(mktemp /tmp/perf.data.XXX) 5 + perf_tool=perf 6 + 7 + skip_if_no_z_record() { 8 + $perf_tool record -h 2>&1 | grep -q '\-z, \-\-compression\-level' 9 + } 10 + 11 + collect_z_record() { 12 + echo "Collecting compressed record file:" 13 + $perf_tool record -o $trace_file -g -z -F 5000 -- \ 14 + dd count=500 if=/dev/random of=/dev/null 15 + } 16 + 17 + check_compressed_stats() { 18 + echo "Checking compressed events stats:" 19 + $perf_tool report -i $trace_file --header --stats | \ 20 + grep -E "(# compressed : Zstd,)|(COMPRESSED events:)" 21 + } 22 + 23 + check_compressed_output() { 24 + $perf_tool inject -i $trace_file -o $trace_file.decomp && 25 + $perf_tool report -i $trace_file --stdio | head -n -3 > $trace_file.comp.output && 26 + $perf_tool report -i $trace_file.decomp --stdio | head -n -3 > $trace_file.decomp.output && 27 + diff $trace_file.comp.output $trace_file.decomp.output 28 + } 29 + 30 + skip_if_no_z_record || exit 2 31 + collect_z_record && check_compressed_stats && check_compressed_output 32 + err=$? 33 + rm -f $trace_file* 34 + exit $err
+2
tools/perf/util/Build
··· 145 145 146 146 perf-$(CONFIG_ZLIB) += zlib.o 147 147 perf-$(CONFIG_LZMA) += lzma.o 148 + perf-$(CONFIG_ZSTD) += zstd.o 149 + 148 150 perf-y += demangle-java.o 149 151 perf-y += demangle-rust.o 150 152
+1 -1
tools/perf/util/annotate.c
··· 1021 1021 float ipc = n_insn / ((double)ch->cycles / (double)ch->num); 1022 1022 1023 1023 /* Hide data when there are too many overlaps. */ 1024 - if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2) 1024 + if (ch->reset >= 0x7fff) 1025 1025 return; 1026 1026 1027 1027 for (offset = start; offset <= end; offset++) {
+53
tools/perf/util/compress.h
··· 2 2 #ifndef PERF_COMPRESS_H 3 3 #define PERF_COMPRESS_H 4 4 5 + #include <stdbool.h> 6 + #ifdef HAVE_ZSTD_SUPPORT 7 + #include <zstd.h> 8 + #endif 9 + 5 10 #ifdef HAVE_ZLIB_SUPPORT 6 11 int gzip_decompress_to_file(const char *input, int output_fd); 7 12 bool gzip_is_compressed(const char *input); ··· 15 10 #ifdef HAVE_LZMA_SUPPORT 16 11 int lzma_decompress_to_file(const char *input, int output_fd); 17 12 bool lzma_is_compressed(const char *input); 13 + #endif 14 + 15 + struct zstd_data { 16 + #ifdef HAVE_ZSTD_SUPPORT 17 + ZSTD_CStream *cstream; 18 + ZSTD_DStream *dstream; 19 + #endif 20 + }; 21 + 22 + #ifdef HAVE_ZSTD_SUPPORT 23 + 24 + int zstd_init(struct zstd_data *data, int level); 25 + int zstd_fini(struct zstd_data *data); 26 + 27 + size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t dst_size, 28 + void *src, size_t src_size, size_t max_record_size, 29 + size_t process_header(void *record, size_t increment)); 30 + 31 + size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size, 32 + void *dst, size_t dst_size); 33 + #else /* !HAVE_ZSTD_SUPPORT */ 34 + 35 + static inline int zstd_init(struct zstd_data *data __maybe_unused, int level __maybe_unused) 36 + { 37 + return 0; 38 + } 39 + 40 + static inline int zstd_fini(struct zstd_data *data __maybe_unused) 41 + { 42 + return 0; 43 + } 44 + 45 + static inline 46 + size_t zstd_compress_stream_to_records(struct zstd_data *data __maybe_unused, 47 + void *dst __maybe_unused, size_t dst_size __maybe_unused, 48 + void *src __maybe_unused, size_t src_size __maybe_unused, 49 + size_t max_record_size __maybe_unused, 50 + size_t process_header(void *record, size_t increment) __maybe_unused) 51 + { 52 + return 0; 53 + } 54 + 55 + static inline size_t zstd_decompress_stream(struct zstd_data *data __maybe_unused, void *src __maybe_unused, 56 + size_t src_size __maybe_unused, void *dst __maybe_unused, 57 + size_t dst_size __maybe_unused) 58 + { 59 + return 0; 60 + } 18 61 #endif 19 62 20 63 #endif /* PERF_COMPRESS_H */
+11
tools/perf/util/env.h
··· 62 62 struct cpu_topology_map *cpu; 63 63 struct cpu_cache_level *caches; 64 64 int caches_cnt; 65 + u32 comp_ratio; 66 + u32 comp_ver; 67 + u32 comp_type; 68 + u32 comp_level; 69 + u32 comp_mmap_len; 65 70 struct numa_node *numa_nodes; 66 71 struct memory_node *memory_nodes; 67 72 unsigned long long memory_bsize; ··· 83 78 struct rb_root btfs; 84 79 u32 btfs_cnt; 85 80 } bpf_progs; 81 + }; 82 + 83 + enum perf_compress_type { 84 + PERF_COMP_NONE = 0, 85 + PERF_COMP_ZSTD, 86 + PERF_COMP_MAX 86 87 }; 87 88 88 89 struct bpf_prog_info_node;
+1
tools/perf/util/event.c
··· 68 68 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", 69 69 [PERF_RECORD_TIME_CONV] = "TIME_CONV", 70 70 [PERF_RECORD_HEADER_FEATURE] = "FEATURE", 71 + [PERF_RECORD_COMPRESSED] = "COMPRESSED", 71 72 }; 72 73 73 74 static const char *perf_ns__names[] = {
+7
tools/perf/util/event.h
··· 255 255 PERF_RECORD_EVENT_UPDATE = 78, 256 256 PERF_RECORD_TIME_CONV = 79, 257 257 PERF_RECORD_HEADER_FEATURE = 80, 258 + PERF_RECORD_COMPRESSED = 81, 258 259 PERF_RECORD_HEADER_MAX 259 260 }; 260 261 ··· 628 627 char data[]; 629 628 }; 630 629 630 + struct compressed_event { 631 + struct perf_event_header header; 632 + char data[]; 633 + }; 634 + 631 635 union perf_event { 632 636 struct perf_event_header header; 633 637 struct mmap_event mmap; ··· 666 660 struct feature_event feat; 667 661 struct ksymbol_event ksymbol_event; 668 662 struct bpf_event bpf_event; 663 + struct compressed_event pack; 669 664 }; 670 665 671 666 void perf_event__print_totals(void);
+5 -3
tools/perf/util/evlist.c
··· 1009 1009 */ 1010 1010 int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, 1011 1011 unsigned int auxtrace_pages, 1012 - bool auxtrace_overwrite, int nr_cblocks, int affinity, int flush) 1012 + bool auxtrace_overwrite, int nr_cblocks, int affinity, int flush, 1013 + int comp_level) 1013 1014 { 1014 1015 struct perf_evsel *evsel; 1015 1016 const struct cpu_map *cpus = evlist->cpus; ··· 1020 1019 * Its value is decided by evsel's write_backward. 1021 1020 * So &mp should not be passed through const pointer. 1022 1021 */ 1023 - struct mmap_params mp = { .nr_cblocks = nr_cblocks, .affinity = affinity, .flush = flush }; 1022 + struct mmap_params mp = { .nr_cblocks = nr_cblocks, .affinity = affinity, .flush = flush, 1023 + .comp_level = comp_level }; 1024 1024 1025 1025 if (!evlist->mmap) 1026 1026 evlist->mmap = perf_evlist__alloc_mmap(evlist, false); ··· 1053 1051 1054 1052 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages) 1055 1053 { 1056 - return perf_evlist__mmap_ex(evlist, pages, 0, false, 0, PERF_AFFINITY_SYS, 1); 1054 + return perf_evlist__mmap_ex(evlist, pages, 0, false, 0, PERF_AFFINITY_SYS, 1, 0); 1057 1055 } 1058 1056 1059 1057 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
+1 -1
tools/perf/util/evlist.h
··· 178 178 int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, 179 179 unsigned int auxtrace_pages, 180 180 bool auxtrace_overwrite, int nr_cblocks, 181 - int affinity, int flush); 181 + int affinity, int flush, int comp_level); 182 182 int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages); 183 183 void perf_evlist__munmap(struct perf_evlist *evlist); 184 184
+2
tools/perf/util/evsel.c
··· 813 813 break; 814 814 case PERF_EVSEL__CONFIG_TERM_DRV_CFG: 815 815 break; 816 + case PERF_EVSEL__CONFIG_TERM_PERCORE: 817 + break; 816 818 default: 817 819 break; 818 820 }
+3
tools/perf/util/evsel.h
··· 50 50 PERF_EVSEL__CONFIG_TERM_OVERWRITE, 51 51 PERF_EVSEL__CONFIG_TERM_DRV_CFG, 52 52 PERF_EVSEL__CONFIG_TERM_BRANCH, 53 + PERF_EVSEL__CONFIG_TERM_PERCORE, 53 54 }; 54 55 55 56 struct perf_evsel_config_term { ··· 68 67 bool overwrite; 69 68 char *branch; 70 69 unsigned long max_events; 70 + bool percore; 71 71 } val; 72 72 bool weak; 73 73 }; ··· 160 158 struct perf_evsel **metric_events; 161 159 bool collect_stat; 162 160 bool weak_group; 161 + bool percore; 163 162 const char *pmu_name; 164 163 struct { 165 164 perf_evsel__sb_cb_t *cb;
+53
tools/perf/util/header.c
··· 1344 1344 return ret; 1345 1345 } 1346 1346 1347 + static int write_compressed(struct feat_fd *ff __maybe_unused, 1348 + struct perf_evlist *evlist __maybe_unused) 1349 + { 1350 + int ret; 1351 + 1352 + ret = do_write(ff, &(ff->ph->env.comp_ver), sizeof(ff->ph->env.comp_ver)); 1353 + if (ret) 1354 + return ret; 1355 + 1356 + ret = do_write(ff, &(ff->ph->env.comp_type), sizeof(ff->ph->env.comp_type)); 1357 + if (ret) 1358 + return ret; 1359 + 1360 + ret = do_write(ff, &(ff->ph->env.comp_level), sizeof(ff->ph->env.comp_level)); 1361 + if (ret) 1362 + return ret; 1363 + 1364 + ret = do_write(ff, &(ff->ph->env.comp_ratio), sizeof(ff->ph->env.comp_ratio)); 1365 + if (ret) 1366 + return ret; 1367 + 1368 + return do_write(ff, &(ff->ph->env.comp_mmap_len), sizeof(ff->ph->env.comp_mmap_len)); 1369 + } 1370 + 1347 1371 static void print_hostname(struct feat_fd *ff, FILE *fp) 1348 1372 { 1349 1373 fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname); ··· 1710 1686 fprintf(fp, "# "); 1711 1687 cpu_cache_level__fprintf(fp, &ff->ph->env.caches[i]); 1712 1688 } 1689 + } 1690 + 1691 + static void print_compressed(struct feat_fd *ff, FILE *fp) 1692 + { 1693 + fprintf(fp, "# compressed : %s, level = %d, ratio = %d\n", 1694 + ff->ph->env.comp_type == PERF_COMP_ZSTD ? "Zstd" : "Unknown", 1695 + ff->ph->env.comp_level, ff->ph->env.comp_ratio); 1713 1696 } 1714 1697 1715 1698 static void print_pmu_mappings(struct feat_fd *ff, FILE *fp) ··· 2698 2667 return err; 2699 2668 } 2700 2669 2670 + static int process_compressed(struct feat_fd *ff, 2671 + void *data __maybe_unused) 2672 + { 2673 + if (do_read_u32(ff, &(ff->ph->env.comp_ver))) 2674 + return -1; 2675 + 2676 + if (do_read_u32(ff, &(ff->ph->env.comp_type))) 2677 + return -1; 2678 + 2679 + if (do_read_u32(ff, &(ff->ph->env.comp_level))) 2680 + return -1; 2681 + 2682 + if (do_read_u32(ff, &(ff->ph->env.comp_ratio))) 2683 + return -1; 2684 + 2685 + if (do_read_u32(ff, &(ff->ph->env.comp_mmap_len))) 2686 + return -1; 2687 + 2688 + return 0; 2689 + } 2690 + 2701 2691 struct feature_ops { 2702 2692 int (*write)(struct feat_fd *ff, struct perf_evlist *evlist); 2703 2693 void (*print)(struct feat_fd *ff, FILE *fp); ··· 2782 2730 FEAT_OPN(DIR_FORMAT, dir_format, false), 2783 2731 FEAT_OPR(BPF_PROG_INFO, bpf_prog_info, false), 2784 2732 FEAT_OPR(BPF_BTF, bpf_btf, false), 2733 + FEAT_OPR(COMPRESSED, compressed, false), 2785 2734 }; 2786 2735 2787 2736 struct header_print_data {
+1
tools/perf/util/header.h
··· 42 42 HEADER_DIR_FORMAT, 43 43 HEADER_BPF_PROG_INFO, 44 44 HEADER_BPF_BTF, 45 + HEADER_COMPRESSED, 45 46 HEADER_LAST_FEATURE, 46 47 HEADER_FEAT_BITS = 256, 47 48 };
+24 -7
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
··· 58 58 INTEL_PT_STATE_NO_IP, 59 59 INTEL_PT_STATE_ERR_RESYNC, 60 60 INTEL_PT_STATE_IN_SYNC, 61 + INTEL_PT_STATE_TNT_CONT, 61 62 INTEL_PT_STATE_TNT, 62 63 INTEL_PT_STATE_TIP, 63 64 INTEL_PT_STATE_TIP_PGD, ··· 73 72 case INTEL_PT_STATE_NO_IP: 74 73 case INTEL_PT_STATE_ERR_RESYNC: 75 74 case INTEL_PT_STATE_IN_SYNC: 76 - case INTEL_PT_STATE_TNT: 75 + case INTEL_PT_STATE_TNT_CONT: 77 76 return true; 77 + case INTEL_PT_STATE_TNT: 78 78 case INTEL_PT_STATE_TIP: 79 79 case INTEL_PT_STATE_TIP_PGD: 80 80 case INTEL_PT_STATE_FUP: ··· 890 888 timestamp = decoder->timestamp + decoder->timestamp_insn_cnt; 891 889 masked_timestamp = timestamp & decoder->period_mask; 892 890 if (decoder->continuous_period) { 893 - if (masked_timestamp != decoder->last_masked_timestamp) 891 + if (masked_timestamp > decoder->last_masked_timestamp) 894 892 return 1; 895 893 } else { 896 894 timestamp += 1; 897 895 masked_timestamp = timestamp & decoder->period_mask; 898 - if (masked_timestamp != decoder->last_masked_timestamp) { 896 + if (masked_timestamp > decoder->last_masked_timestamp) { 899 897 decoder->last_masked_timestamp = masked_timestamp; 900 898 decoder->continuous_period = true; 901 899 } 902 900 } 901 + 902 + if (masked_timestamp < decoder->last_masked_timestamp) 903 + return decoder->period_ticks; 904 + 903 905 return decoder->period_ticks - (timestamp - masked_timestamp); 904 906 } 905 907 ··· 932 926 case INTEL_PT_PERIOD_TICKS: 933 927 timestamp = decoder->timestamp + decoder->timestamp_insn_cnt; 934 928 masked_timestamp = timestamp & decoder->period_mask; 935 - decoder->last_masked_timestamp = masked_timestamp; 929 + if (masked_timestamp > decoder->last_masked_timestamp) 930 + decoder->last_masked_timestamp = masked_timestamp; 931 + else 932 + decoder->last_masked_timestamp += decoder->period_ticks; 936 933 break; 937 934 case INTEL_PT_PERIOD_NONE: 938 935 case INTEL_PT_PERIOD_MTC: ··· 1263 1254 return -ENOENT; 1264 1255 } 1265 1256 decoder->tnt.count -= 1; 1266 - if (!decoder->tnt.count) 1257 + if (decoder->tnt.count) 1258 + decoder->pkt_state = INTEL_PT_STATE_TNT_CONT; 1259 + else 1267 1260 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1268 1261 decoder->tnt.payload <<= 1; 1269 1262 decoder->state.from_ip = decoder->ip; ··· 1296 1285 1297 1286 if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) { 1298 1287 decoder->tnt.count -= 1; 1299 - if (!decoder->tnt.count) 1288 + if (decoder->tnt.count) 1289 + decoder->pkt_state = INTEL_PT_STATE_TNT_CONT; 1290 + else 1300 1291 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1301 1292 if (decoder->tnt.payload & BIT63) { 1302 1293 decoder->tnt.payload <<= 1; ··· 1318 1305 return 0; 1319 1306 } 1320 1307 decoder->ip += intel_pt_insn.length; 1321 - if (!decoder->tnt.count) 1308 + if (!decoder->tnt.count) { 1309 + decoder->sample_timestamp = decoder->timestamp; 1310 + decoder->sample_insn_cnt = decoder->timestamp_insn_cnt; 1322 1311 return -EAGAIN; 1312 + } 1323 1313 decoder->tnt.payload <<= 1; 1324 1314 continue; 1325 1315 } ··· 2381 2365 err = intel_pt_walk_trace(decoder); 2382 2366 break; 2383 2367 case INTEL_PT_STATE_TNT: 2368 + case INTEL_PT_STATE_TNT_CONT: 2384 2369 err = intel_pt_walk_tnt(decoder); 2385 2370 if (err == -EAGAIN) 2386 2371 err = intel_pt_walk_trace(decoder);
+2 -1
tools/perf/util/machine.c
··· 1234 1234 if (!file) 1235 1235 return NULL; 1236 1236 1237 - version[0] = '\0'; 1238 1237 tmp = fgets(version, sizeof(version), file); 1238 + if (!tmp) 1239 + *version = '\0'; 1239 1240 fclose(file); 1240 1241 1241 1242 name = strstr(version, prefix);
+27 -75
tools/perf/util/mmap.c
··· 157 157 } 158 158 159 159 #ifdef HAVE_AIO_SUPPORT 160 + static int perf_mmap__aio_enabled(struct perf_mmap *map) 161 + { 162 + return map->aio.nr_cblocks > 0; 163 + } 160 164 161 165 #ifdef HAVE_LIBNUMA_SUPPORT 162 166 static int perf_mmap__aio_alloc(struct perf_mmap *map, int idx) ··· 202 198 203 199 return 0; 204 200 } 205 - #else 201 + #else /* !HAVE_LIBNUMA_SUPPORT */ 206 202 static int perf_mmap__aio_alloc(struct perf_mmap *map, int idx) 207 203 { 208 204 map->aio.data[idx] = malloc(perf_mmap__mmap_len(map)); ··· 289 285 zfree(&map->aio.cblocks); 290 286 zfree(&map->aio.aiocb); 291 287 } 292 - 293 - int perf_mmap__aio_push(struct perf_mmap *md, void *to, int idx, 294 - int push(void *to, struct aiocb *cblock, void *buf, size_t size, off_t off), 295 - off_t *off) 288 + #else /* !HAVE_AIO_SUPPORT */ 289 + static int perf_mmap__aio_enabled(struct perf_mmap *map __maybe_unused) 296 290 { 297 - u64 head = perf_mmap__read_head(md); 298 - unsigned char *data = md->base + page_size; 299 - unsigned long size, size0 = 0; 300 - void *buf; 301 - int rc = 0; 302 - 303 - rc = perf_mmap__read_init(md); 304 - if (rc < 0) 305 - return (rc == -EAGAIN) ? 0 : -1; 306 - 307 - /* 308 - * md->base data is copied into md->data[idx] buffer to 309 - * release space in the kernel buffer as fast as possible, 310 - * thru perf_mmap__consume() below. 311 - * 312 - * That lets the kernel to proceed with storing more 313 - * profiling data into the kernel buffer earlier than other 314 - * per-cpu kernel buffers are handled. 315 - * 316 - * Coping can be done in two steps in case the chunk of 317 - * profiling data crosses the upper bound of the kernel buffer. 318 - * In this case we first move part of data from md->start 319 - * till the upper bound and then the reminder from the 320 - * beginning of the kernel buffer till the end of 321 - * the data chunk. 322 - */ 323 - 324 - size = md->end - md->start; 325 - 326 - if ((md->start & md->mask) + size != (md->end & md->mask)) { 327 - buf = &data[md->start & md->mask]; 328 - size = md->mask + 1 - (md->start & md->mask); 329 - md->start += size; 330 - memcpy(md->aio.data[idx], buf, size); 331 - size0 = size; 332 - } 333 - 334 - buf = &data[md->start & md->mask]; 335 - size = md->end - md->start; 336 - md->start += size; 337 - memcpy(md->aio.data[idx] + size0, buf, size); 338 - 339 - /* 340 - * Increment md->refcount to guard md->data[idx] buffer 341 - * from premature deallocation because md object can be 342 - * released earlier than aio write request started 343 - * on mmap->data[idx] is complete. 344 - * 345 - * perf_mmap__put() is done at record__aio_complete() 346 - * after started request completion. 347 - */ 348 - perf_mmap__get(md); 349 - 350 - md->prev = head; 351 - perf_mmap__consume(md); 352 - 353 - rc = push(to, &md->aio.cblocks[idx], md->aio.data[idx], size0 + size, *off); 354 - if (!rc) { 355 - *off += size0 + size; 356 - } else { 357 - /* 358 - * Decrement md->refcount back if aio write 359 - * operation failed to start. 360 - */ 361 - perf_mmap__put(md); 362 - } 363 - 364 - return rc; 291 + return 0; 365 292 } 366 - #else 293 + 367 294 static int perf_mmap__aio_mmap(struct perf_mmap *map __maybe_unused, 368 295 struct mmap_params *mp __maybe_unused) 369 296 { ··· 309 374 void perf_mmap__munmap(struct perf_mmap *map) 310 375 { 311 376 perf_mmap__aio_munmap(map); 377 + if (map->data != NULL) { 378 + munmap(map->data, perf_mmap__mmap_len(map)); 379 + map->data = NULL; 380 + } 312 381 if (map->base != NULL) { 313 382 munmap(map->base, perf_mmap__mmap_len(map)); 314 383 map->base = NULL; ··· 380 441 perf_mmap__setup_affinity_mask(map, mp); 381 442 382 443 map->flush = mp->flush; 444 + 445 + map->comp_level = mp->comp_level; 446 + 447 + if (map->comp_level && !perf_mmap__aio_enabled(map)) { 448 + map->data = mmap(NULL, perf_mmap__mmap_len(map), PROT_READ|PROT_WRITE, 449 + MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 450 + if (map->data == MAP_FAILED) { 451 + pr_debug2("failed to mmap data buffer, error %d\n", 452 + errno); 453 + map->data = NULL; 454 + return -1; 455 + } 456 + } 383 457 384 458 if (auxtrace_mmap__mmap(&map->auxtrace_mmap, 385 459 &mp->auxtrace_mp, map->base, fd)) ··· 492 540 493 541 rc = perf_mmap__read_init(md); 494 542 if (rc < 0) 495 - return (rc == -EAGAIN) ? 0 : -1; 543 + return (rc == -EAGAIN) ? 1 : -1; 496 544 497 545 size = md->end - md->start; 498 546
+3 -13
tools/perf/util/mmap.h
··· 40 40 #endif 41 41 cpu_set_t affinity_mask; 42 42 u64 flush; 43 + void *data; 44 + int comp_level; 43 45 }; 44 46 45 47 /* ··· 73 71 }; 74 72 75 73 struct mmap_params { 76 - int prot, mask, nr_cblocks, affinity, flush; 74 + int prot, mask, nr_cblocks, affinity, flush, comp_level; 77 75 struct auxtrace_mmap_params auxtrace_mp; 78 76 }; 79 77 ··· 101 99 102 100 int perf_mmap__push(struct perf_mmap *md, void *to, 103 101 int push(struct perf_mmap *map, void *to, void *buf, size_t size)); 104 - #ifdef HAVE_AIO_SUPPORT 105 - int perf_mmap__aio_push(struct perf_mmap *md, void *to, int idx, 106 - int push(void *to, struct aiocb *cblock, void *buf, size_t size, off_t off), 107 - off_t *off); 108 - #else 109 - static inline int perf_mmap__aio_push(struct perf_mmap *md __maybe_unused, void *to __maybe_unused, int idx __maybe_unused, 110 - int push(void *to, struct aiocb *cblock, void *buf, size_t size, off_t off) __maybe_unused, 111 - off_t *off __maybe_unused) 112 - { 113 - return 0; 114 - } 115 - #endif 116 102 117 103 size_t perf_mmap__mmap_len(struct perf_mmap *map); 118 104
+27
tools/perf/util/parse-events.c
··· 950 950 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", 951 951 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", 952 952 [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", 953 + [PARSE_EVENTS__TERM_TYPE_PERCORE] = "percore", 953 954 }; 954 955 955 956 static bool config_term_shrinked; ··· 971 970 case PARSE_EVENTS__TERM_TYPE_CONFIG2: 972 971 case PARSE_EVENTS__TERM_TYPE_NAME: 973 972 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 973 + case PARSE_EVENTS__TERM_TYPE_PERCORE: 974 974 return true; 975 975 default: 976 976 if (!err) ··· 1062 1060 break; 1063 1061 case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 1064 1062 CHECK_TYPE_VAL(NUM); 1063 + break; 1064 + case PARSE_EVENTS__TERM_TYPE_PERCORE: 1065 + CHECK_TYPE_VAL(NUM); 1066 + if ((unsigned int)term->val.num > 1) { 1067 + err->str = strdup("expected 0 or 1"); 1068 + err->idx = term->err_val; 1069 + return -EINVAL; 1070 + } 1065 1071 break; 1066 1072 default: 1067 1073 err->str = strdup("unknown term"); ··· 1209 1199 case PARSE_EVENTS__TERM_TYPE_DRV_CFG: 1210 1200 ADD_CONFIG_TERM(DRV_CFG, drv_cfg, term->val.str); 1211 1201 break; 1202 + case PARSE_EVENTS__TERM_TYPE_PERCORE: 1203 + ADD_CONFIG_TERM(PERCORE, percore, 1204 + term->val.num ? true : false); 1205 + break; 1212 1206 default: 1213 1207 break; 1214 1208 } ··· 1272 1258 enum perf_tool_event tool_event) 1273 1259 { 1274 1260 return add_event_tool(list, &parse_state->idx, tool_event); 1261 + } 1262 + 1263 + static bool config_term_percore(struct list_head *config_terms) 1264 + { 1265 + struct perf_evsel_config_term *term; 1266 + 1267 + list_for_each_entry(term, config_terms, list) { 1268 + if (term->type == PERF_EVSEL__CONFIG_TERM_PERCORE) 1269 + return term->val.percore; 1270 + } 1271 + 1272 + return false; 1275 1273 } 1276 1274 1277 1275 int parse_events_add_pmu(struct parse_events_state *parse_state, ··· 1359 1333 evsel->metric_name = info.metric_name; 1360 1334 evsel->pmu_name = name; 1361 1335 evsel->use_uncore_alias = use_uncore_alias; 1336 + evsel->percore = config_term_percore(&evsel->config_terms); 1362 1337 } 1363 1338 1364 1339 return evsel ? 0 : -ENOMEM;
+1
tools/perf/util/parse-events.h
··· 75 75 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, 76 76 PARSE_EVENTS__TERM_TYPE_OVERWRITE, 77 77 PARSE_EVENTS__TERM_TYPE_DRV_CFG, 78 + PARSE_EVENTS__TERM_TYPE_PERCORE, 78 79 __PARSE_EVENTS__TERM_TYPE_NR, 79 80 }; 80 81
+1
tools/perf/util/parse-events.l
··· 283 283 no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } 284 284 overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } 285 285 no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); } 286 + percore { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PERCORE); } 286 287 , { return ','; } 287 288 "/" { BEGIN(INITIAL); return '/'; } 288 289 {name_minus} { return str(yyscanner, PE_NAME); }
+26 -7
tools/perf/util/parse-regs-options.c
··· 5 5 #include <subcmd/parse-options.h> 6 6 #include "util/parse-regs-options.h" 7 7 8 - int 9 - parse_regs(const struct option *opt, const char *str, int unset) 8 + static int 9 + __parse_regs(const struct option *opt, const char *str, int unset, bool intr) 10 10 { 11 11 uint64_t *mode = (uint64_t *)opt->value; 12 12 const struct sample_reg *r; 13 13 char *s, *os = NULL, *p; 14 14 int ret = -1; 15 + uint64_t mask; 15 16 16 17 if (unset) 17 18 return 0; ··· 22 21 */ 23 22 if (*mode) 24 23 return -1; 24 + 25 + if (intr) 26 + mask = arch__intr_reg_mask(); 27 + else 28 + mask = arch__user_reg_mask(); 25 29 26 30 /* str may be NULL in case no arg is passed to -I */ 27 31 if (str) { ··· 43 37 if (!strcmp(s, "?")) { 44 38 fprintf(stderr, "available registers: "); 45 39 for (r = sample_reg_masks; r->name; r++) { 46 - fprintf(stderr, "%s ", r->name); 40 + if (r->mask & mask) 41 + fprintf(stderr, "%s ", r->name); 47 42 } 48 43 fputc('\n', stderr); 49 44 /* just printing available regs */ 50 45 return -1; 51 46 } 52 47 for (r = sample_reg_masks; r->name; r++) { 53 - if (!strcasecmp(s, r->name)) 48 + if ((r->mask & mask) && !strcasecmp(s, r->name)) 54 49 break; 55 50 } 56 51 if (!r->name) { 57 - ui__warning("unknown register %s," 58 - " check man page\n", s); 52 + ui__warning("Unknown register \"%s\", check man page or run \"perf record %s?\"\n", 53 + s, intr ? "-I" : "--user-regs="); 59 54 goto error; 60 55 } 61 56 ··· 72 65 73 66 /* default to all possible regs */ 74 67 if (*mode == 0) 75 - *mode = PERF_REGS_MASK; 68 + *mode = mask; 76 69 error: 77 70 free(os); 78 71 return ret; 72 + } 73 + 74 + int 75 + parse_user_regs(const struct option *opt, const char *str, int unset) 76 + { 77 + return __parse_regs(opt, str, unset, false); 78 + } 79 + 80 + int 81 + parse_intr_regs(const struct option *opt, const char *str, int unset) 82 + { 83 + return __parse_regs(opt, str, unset, true); 79 84 }
+2 -1
tools/perf/util/parse-regs-options.h
··· 2 2 #ifndef _PERF_PARSE_REGS_OPTIONS_H 3 3 #define _PERF_PARSE_REGS_OPTIONS_H 1 4 4 struct option; 5 - int parse_regs(const struct option *opt, const char *str, int unset); 5 + int parse_user_regs(const struct option *opt, const char *str, int unset); 6 + int parse_intr_regs(const struct option *opt, const char *str, int unset); 6 7 #endif /* _PERF_PARSE_REGS_OPTIONS_H */
+10
tools/perf/util/perf_regs.c
··· 13 13 return SDT_ARG_SKIP; 14 14 } 15 15 16 + uint64_t __weak arch__intr_reg_mask(void) 17 + { 18 + return PERF_REGS_MASK; 19 + } 20 + 21 + uint64_t __weak arch__user_reg_mask(void) 22 + { 23 + return PERF_REGS_MASK; 24 + } 25 + 16 26 #ifdef HAVE_PERF_REGS_SUPPORT 17 27 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) 18 28 {
+3
tools/perf/util/perf_regs.h
··· 12 12 uint64_t mask; 13 13 }; 14 14 #define SMPL_REG(n, b) { .name = #n, .mask = 1ULL << (b) } 15 + #define SMPL_REG2(n, b) { .name = #n, .mask = 3ULL << (b) } 15 16 #define SMPL_REG_END { .name = NULL } 16 17 17 18 extern const struct sample_reg sample_reg_masks[]; ··· 23 22 }; 24 23 25 24 int arch_sdt_arg_parse_op(char *old_op, char **new_op); 25 + uint64_t arch__intr_reg_mask(void); 26 + uint64_t arch__user_reg_mask(void); 26 27 27 28 #ifdef HAVE_PERF_REGS_SUPPORT 28 29 #include <perf_regs.h>
+132 -1
tools/perf/util/session.c
··· 29 29 #include "stat.h" 30 30 #include "arch/common.h" 31 31 32 + #ifdef HAVE_ZSTD_SUPPORT 33 + static int perf_session__process_compressed_event(struct perf_session *session, 34 + union perf_event *event, u64 file_offset) 35 + { 36 + void *src; 37 + size_t decomp_size, src_size; 38 + u64 decomp_last_rem = 0; 39 + size_t decomp_len = session->header.env.comp_mmap_len; 40 + struct decomp *decomp, *decomp_last = session->decomp_last; 41 + 42 + decomp = mmap(NULL, sizeof(struct decomp) + decomp_len, PROT_READ|PROT_WRITE, 43 + MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 44 + if (decomp == MAP_FAILED) { 45 + pr_err("Couldn't allocate memory for decompression\n"); 46 + return -1; 47 + } 48 + 49 + decomp->file_pos = file_offset; 50 + decomp->head = 0; 51 + 52 + if (decomp_last) { 53 + decomp_last_rem = decomp_last->size - decomp_last->head; 54 + memcpy(decomp->data, &(decomp_last->data[decomp_last->head]), decomp_last_rem); 55 + decomp->size = decomp_last_rem; 56 + } 57 + 58 + src = (void *)event + sizeof(struct compressed_event); 59 + src_size = event->pack.header.size - sizeof(struct compressed_event); 60 + 61 + decomp_size = zstd_decompress_stream(&(session->zstd_data), src, src_size, 62 + &(decomp->data[decomp_last_rem]), decomp_len - decomp_last_rem); 63 + if (!decomp_size) { 64 + munmap(decomp, sizeof(struct decomp) + decomp_len); 65 + pr_err("Couldn't decompress data\n"); 66 + return -1; 67 + } 68 + 69 + decomp->size += decomp_size; 70 + 71 + if (session->decomp == NULL) { 72 + session->decomp = decomp; 73 + session->decomp_last = decomp; 74 + } else { 75 + session->decomp_last->next = decomp; 76 + session->decomp_last = decomp; 77 + } 78 + 79 + pr_debug("decomp (B): %ld to %ld\n", src_size, decomp_size); 80 + 81 + return 0; 82 + } 83 + #else /* !HAVE_ZSTD_SUPPORT */ 84 + #define perf_session__process_compressed_event perf_session__process_compressed_event_stub 85 + #endif 86 + 32 87 static int perf_session__deliver_event(struct perf_session *session, 33 88 union perf_event *event, 34 89 struct perf_tool *tool, ··· 252 197 machine__delete_threads(&session->machines.host); 253 198 } 254 199 200 + static void perf_session__release_decomp_events(struct perf_session *session) 201 + { 202 + struct decomp *next, *decomp; 203 + size_t decomp_len; 204 + next = session->decomp; 205 + decomp_len = session->header.env.comp_mmap_len; 206 + do { 207 + decomp = next; 208 + if (decomp == NULL) 209 + break; 210 + next = decomp->next; 211 + munmap(decomp, decomp_len + sizeof(struct decomp)); 212 + } while (1); 213 + } 214 + 255 215 void perf_session__delete(struct perf_session *session) 256 216 { 257 217 if (session == NULL) ··· 275 205 auxtrace_index__free(&session->auxtrace_index); 276 206 perf_session__destroy_kernel_maps(session); 277 207 perf_session__delete_threads(session); 208 + perf_session__release_decomp_events(session); 278 209 perf_env__exit(&session->header.env); 279 210 machines__exit(&session->machines); 280 211 if (session->data) ··· 429 358 return 0; 430 359 } 431 360 361 + static int perf_session__process_compressed_event_stub(struct perf_session *session __maybe_unused, 362 + union perf_event *event __maybe_unused, 363 + u64 file_offset __maybe_unused) 364 + { 365 + dump_printf(": unhandled!\n"); 366 + return 0; 367 + } 368 + 432 369 void perf_tool__fill_defaults(struct perf_tool *tool) 433 370 { 434 371 if (tool->sample == NULL) ··· 509 430 tool->time_conv = process_event_op2_stub; 510 431 if (tool->feature == NULL) 511 432 tool->feature = process_event_op2_stub; 433 + if (tool->compressed == NULL) 434 + tool->compressed = perf_session__process_compressed_event; 512 435 } 513 436 514 437 static void swap_sample_id_all(union perf_event *event, void *data) ··· 1454 1373 int fd = perf_data__fd(session->data); 1455 1374 int err; 1456 1375 1457 - dump_event(session->evlist, event, file_offset, &sample); 1376 + if (event->header.type != PERF_RECORD_COMPRESSED || 1377 + tool->compressed == perf_session__process_compressed_event_stub) 1378 + dump_event(session->evlist, event, file_offset, &sample); 1458 1379 1459 1380 /* These events are processed right away */ 1460 1381 switch (event->header.type) { ··· 1509 1426 return tool->time_conv(session, event); 1510 1427 case PERF_RECORD_HEADER_FEATURE: 1511 1428 return tool->feature(session, event); 1429 + case PERF_RECORD_COMPRESSED: 1430 + err = tool->compressed(session, event, file_offset); 1431 + if (err) 1432 + dump_event(session->evlist, event, file_offset, &sample); 1433 + return err; 1512 1434 default: 1513 1435 return -EINVAL; 1514 1436 } ··· 1796 1708 1797 1709 volatile int session_done; 1798 1710 1711 + static int __perf_session__process_decomp_events(struct perf_session *session); 1712 + 1799 1713 static int __perf_session__process_pipe_events(struct perf_session *session) 1800 1714 { 1801 1715 struct ordered_events *oe = &session->ordered_events; ··· 1878 1788 if (skip > 0) 1879 1789 head += skip; 1880 1790 1791 + err = __perf_session__process_decomp_events(session); 1792 + if (err) 1793 + goto out_err; 1794 + 1881 1795 if (!session_done()) 1882 1796 goto more; 1883 1797 done: ··· 1928 1834 } 1929 1835 1930 1836 return event; 1837 + } 1838 + 1839 + static int __perf_session__process_decomp_events(struct perf_session *session) 1840 + { 1841 + s64 skip; 1842 + u64 size, file_pos = 0; 1843 + struct decomp *decomp = session->decomp_last; 1844 + 1845 + if (!decomp) 1846 + return 0; 1847 + 1848 + while (decomp->head < decomp->size && !session_done()) { 1849 + union perf_event *event = fetch_mmaped_event(session, decomp->head, decomp->size, decomp->data); 1850 + 1851 + if (!event) 1852 + break; 1853 + 1854 + size = event->header.size; 1855 + 1856 + if (size < sizeof(struct perf_event_header) || 1857 + (skip = perf_session__process_event(session, event, file_pos)) < 0) { 1858 + pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1859 + decomp->file_pos + decomp->head, event->header.size, event->header.type); 1860 + return -EINVAL; 1861 + } 1862 + 1863 + if (skip) 1864 + size += skip; 1865 + 1866 + decomp->head += size; 1867 + } 1868 + 1869 + return 0; 1931 1870 } 1932 1871 1933 1872 /* ··· 2071 1944 2072 1945 head += size; 2073 1946 file_pos += size; 1947 + 1948 + err = __perf_session__process_decomp_events(session); 1949 + if (err) 1950 + goto out; 2074 1951 2075 1952 ui_progress__update(prog, size); 2076 1953
+14
tools/perf/util/session.h
··· 8 8 #include "machine.h" 9 9 #include "data.h" 10 10 #include "ordered-events.h" 11 + #include "util/compress.h" 11 12 #include <linux/kernel.h> 12 13 #include <linux/rbtree.h> 13 14 #include <linux/perf_event.h> ··· 36 35 struct ordered_events ordered_events; 37 36 struct perf_data *data; 38 37 struct perf_tool *tool; 38 + u64 bytes_transferred; 39 + u64 bytes_compressed; 40 + struct zstd_data zstd_data; 41 + struct decomp *decomp; 42 + struct decomp *decomp_last; 43 + }; 44 + 45 + struct decomp { 46 + struct decomp *next; 47 + u64 file_pos; 48 + u64 head; 49 + size_t size; 50 + char data[]; 39 51 }; 40 52 41 53 struct perf_tool;
+78 -29
tools/perf/util/stat-display.c
··· 88 88 config->csv_sep); 89 89 break; 90 90 case AGGR_NONE: 91 - fprintf(config->output, "CPU%*d%s", 92 - config->csv_output ? 0 : -4, 93 - perf_evsel__cpus(evsel)->map[id], config->csv_sep); 91 + if (evsel->percore) { 92 + fprintf(config->output, "S%d-C%*d%s", 93 + cpu_map__id_to_socket(id), 94 + config->csv_output ? 0 : -5, 95 + cpu_map__id_to_cpu(id), config->csv_sep); 96 + } else { 97 + fprintf(config->output, "CPU%*d%s ", 98 + config->csv_output ? 0 : -5, 99 + perf_evsel__cpus(evsel)->map[id], 100 + config->csv_sep); 101 + } 94 102 break; 95 103 case AGGR_THREAD: 96 104 fprintf(config->output, "%*s-%*d%s", ··· 602 594 } 603 595 } 604 596 597 + static void print_counter_aggrdata(struct perf_stat_config *config, 598 + struct perf_evsel *counter, int s, 599 + char *prefix, bool metric_only, 600 + bool *first) 601 + { 602 + struct aggr_data ad; 603 + FILE *output = config->output; 604 + u64 ena, run, val; 605 + int id, nr; 606 + double uval; 607 + 608 + ad.id = id = config->aggr_map->map[s]; 609 + ad.val = ad.ena = ad.run = 0; 610 + ad.nr = 0; 611 + if (!collect_data(config, counter, aggr_cb, &ad)) 612 + return; 613 + 614 + nr = ad.nr; 615 + ena = ad.ena; 616 + run = ad.run; 617 + val = ad.val; 618 + if (*first && metric_only) { 619 + *first = false; 620 + aggr_printout(config, counter, id, nr); 621 + } 622 + if (prefix && !metric_only) 623 + fprintf(output, "%s", prefix); 624 + 625 + uval = val * counter->scale; 626 + printout(config, id, nr, counter, uval, prefix, 627 + run, ena, 1.0, &rt_stat); 628 + if (!metric_only) 629 + fputc('\n', output); 630 + } 631 + 605 632 static void print_aggr(struct perf_stat_config *config, 606 633 struct perf_evlist *evlist, 607 634 char *prefix) ··· 644 601 bool metric_only = config->metric_only; 645 602 FILE *output = config->output; 646 603 struct perf_evsel *counter; 647 - int s, id, nr; 648 - double uval; 649 - u64 ena, run, val; 604 + int s; 650 605 bool first; 651 606 652 607 if (!(config->aggr_map || config->aggr_get_id)) ··· 657 616 * Without each counter has its own line. 658 617 */ 659 618 for (s = 0; s < config->aggr_map->nr; s++) { 660 - struct aggr_data ad; 661 619 if (prefix && metric_only) 662 620 fprintf(output, "%s", prefix); 663 621 664 - ad.id = id = config->aggr_map->map[s]; 665 622 first = true; 666 623 evlist__for_each_entry(evlist, counter) { 667 - ad.val = ad.ena = ad.run = 0; 668 - ad.nr = 0; 669 - if (!collect_data(config, counter, aggr_cb, &ad)) 670 - continue; 671 - nr = ad.nr; 672 - ena = ad.ena; 673 - run = ad.run; 674 - val = ad.val; 675 - if (first && metric_only) { 676 - first = false; 677 - aggr_printout(config, counter, id, nr); 678 - } 679 - if (prefix && !metric_only) 680 - fprintf(output, "%s", prefix); 681 - 682 - uval = val * counter->scale; 683 - printout(config, id, nr, counter, uval, prefix, 684 - run, ena, 1.0, &rt_stat); 685 - if (!metric_only) 686 - fputc('\n', output); 624 + print_counter_aggrdata(config, counter, s, 625 + prefix, metric_only, 626 + &first); 687 627 } 688 628 if (metric_only) 689 629 fputc('\n', output); ··· 1111 1089 "the same PMU. Try reorganizing the group.\n"); 1112 1090 } 1113 1091 1092 + static void print_percore(struct perf_stat_config *config, 1093 + struct perf_evsel *counter, char *prefix) 1094 + { 1095 + bool metric_only = config->metric_only; 1096 + FILE *output = config->output; 1097 + int s; 1098 + bool first = true; 1099 + 1100 + if (!(config->aggr_map || config->aggr_get_id)) 1101 + return; 1102 + 1103 + for (s = 0; s < config->aggr_map->nr; s++) { 1104 + if (prefix && metric_only) 1105 + fprintf(output, "%s", prefix); 1106 + 1107 + print_counter_aggrdata(config, counter, s, 1108 + prefix, metric_only, 1109 + &first); 1110 + } 1111 + 1112 + if (metric_only) 1113 + fputc('\n', output); 1114 + } 1115 + 1114 1116 void 1115 1117 perf_evlist__print_counters(struct perf_evlist *evlist, 1116 1118 struct perf_stat_config *config, ··· 1185 1139 print_no_aggr_metric(config, evlist, prefix); 1186 1140 else { 1187 1141 evlist__for_each_entry(evlist, counter) { 1188 - print_counter(config, counter, prefix); 1142 + if (counter->percore) 1143 + print_percore(config, counter, prefix); 1144 + else 1145 + print_counter(config, counter, prefix); 1189 1146 } 1190 1147 } 1191 1148 break;
+5 -3
tools/perf/util/stat.c
··· 277 277 if (!evsel->snapshot) 278 278 perf_evsel__compute_deltas(evsel, cpu, thread, count); 279 279 perf_counts_values__scale(count, config->scale, NULL); 280 - if (config->aggr_mode == AGGR_NONE) 281 - perf_stat__update_shadow_stats(evsel, count->val, cpu, 282 - &rt_stat); 280 + if ((config->aggr_mode == AGGR_NONE) && (!evsel->percore)) { 281 + perf_stat__update_shadow_stats(evsel, count->val, 282 + cpu, &rt_stat); 283 + } 284 + 283 285 if (config->aggr_mode == AGGR_THREAD) { 284 286 if (config->stats) 285 287 perf_stat__update_shadow_stats(evsel,
+2 -1
tools/perf/util/thread.c
··· 15 15 #include "map.h" 16 16 #include "symbol.h" 17 17 #include "unwind.h" 18 + #include "callchain.h" 18 19 19 20 #include <api/fs/fs.h> 20 21 ··· 328 327 { 329 328 int err = 0; 330 329 331 - if (symbol_conf.use_callchain) 330 + if (dwarf_callchain_users) 332 331 err = __thread__prepare_access(thread); 333 332 334 333 return err;
+2
tools/perf/util/tool.h
··· 28 28 29 29 typedef int (*event_op2)(struct perf_session *session, union perf_event *event); 30 30 typedef s64 (*event_op3)(struct perf_session *session, union perf_event *event); 31 + typedef int (*event_op4)(struct perf_session *session, union perf_event *event, u64 data); 31 32 32 33 typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event, 33 34 struct ordered_events *oe); ··· 73 72 stat, 74 73 stat_round, 75 74 feature; 75 + event_op4 compressed; 76 76 event_op3 auxtrace; 77 77 bool ordered_events; 78 78 bool ordering_requires_timestamps;
-6
tools/perf/util/unwind-libunwind-local.c
··· 617 617 618 618 static int _unwind__prepare_access(struct thread *thread) 619 619 { 620 - if (!dwarf_callchain_users) 621 - return 0; 622 620 thread->addr_space = unw_create_addr_space(&accessors, 0); 623 621 if (!thread->addr_space) { 624 622 pr_err("unwind: Can't create unwind address space.\n"); ··· 629 631 630 632 static void _unwind__flush_access(struct thread *thread) 631 633 { 632 - if (!dwarf_callchain_users) 633 - return; 634 634 unw_flush_cache(thread->addr_space, 0, 0); 635 635 } 636 636 637 637 static void _unwind__finish_access(struct thread *thread) 638 638 { 639 - if (!dwarf_callchain_users) 640 - return; 641 639 unw_destroy_addr_space(thread->addr_space); 642 640 } 643 641
+10
tools/perf/util/unwind-libunwind.c
··· 5 5 #include "session.h" 6 6 #include "debug.h" 7 7 #include "env.h" 8 + #include "callchain.h" 8 9 9 10 struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops; 10 11 struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops; ··· 24 23 enum dso_type dso_type; 25 24 struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops; 26 25 int err; 26 + 27 + if (!dwarf_callchain_users) 28 + return 0; 27 29 28 30 if (thread->addr_space) { 29 31 pr_debug("unwind: thread map already set, dso=%s\n", ··· 69 65 70 66 void unwind__flush_access(struct thread *thread) 71 67 { 68 + if (!dwarf_callchain_users) 69 + return; 70 + 72 71 if (thread->unwind_libunwind_ops) 73 72 thread->unwind_libunwind_ops->flush_access(thread); 74 73 } 75 74 76 75 void unwind__finish_access(struct thread *thread) 77 76 { 77 + if (!dwarf_callchain_users) 78 + return; 79 + 78 80 if (thread->unwind_libunwind_ops) 79 81 thread->unwind_libunwind_ops->finish_access(thread); 80 82 }
+111
tools/perf/util/zstd.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <string.h> 4 + 5 + #include "util/compress.h" 6 + #include "util/debug.h" 7 + 8 + int zstd_init(struct zstd_data *data, int level) 9 + { 10 + size_t ret; 11 + 12 + data->dstream = ZSTD_createDStream(); 13 + if (data->dstream == NULL) { 14 + pr_err("Couldn't create decompression stream.\n"); 15 + return -1; 16 + } 17 + 18 + ret = ZSTD_initDStream(data->dstream); 19 + if (ZSTD_isError(ret)) { 20 + pr_err("Failed to initialize decompression stream: %s\n", ZSTD_getErrorName(ret)); 21 + return -1; 22 + } 23 + 24 + if (!level) 25 + return 0; 26 + 27 + data->cstream = ZSTD_createCStream(); 28 + if (data->cstream == NULL) { 29 + pr_err("Couldn't create compression stream.\n"); 30 + return -1; 31 + } 32 + 33 + ret = ZSTD_initCStream(data->cstream, level); 34 + if (ZSTD_isError(ret)) { 35 + pr_err("Failed to initialize compression stream: %s\n", ZSTD_getErrorName(ret)); 36 + return -1; 37 + } 38 + 39 + return 0; 40 + } 41 + 42 + int zstd_fini(struct zstd_data *data) 43 + { 44 + if (data->dstream) { 45 + ZSTD_freeDStream(data->dstream); 46 + data->dstream = NULL; 47 + } 48 + 49 + if (data->cstream) { 50 + ZSTD_freeCStream(data->cstream); 51 + data->cstream = NULL; 52 + } 53 + 54 + return 0; 55 + } 56 + 57 + size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t dst_size, 58 + void *src, size_t src_size, size_t max_record_size, 59 + size_t process_header(void *record, size_t increment)) 60 + { 61 + size_t ret, size, compressed = 0; 62 + ZSTD_inBuffer input = { src, src_size, 0 }; 63 + ZSTD_outBuffer output; 64 + void *record; 65 + 66 + while (input.pos < input.size) { 67 + record = dst; 68 + size = process_header(record, 0); 69 + compressed += size; 70 + dst += size; 71 + dst_size -= size; 72 + output = (ZSTD_outBuffer){ dst, (dst_size > max_record_size) ? 73 + max_record_size : dst_size, 0 }; 74 + ret = ZSTD_compressStream(data->cstream, &output, &input); 75 + ZSTD_flushStream(data->cstream, &output); 76 + if (ZSTD_isError(ret)) { 77 + pr_err("failed to compress %ld bytes: %s\n", 78 + (long)src_size, ZSTD_getErrorName(ret)); 79 + memcpy(dst, src, src_size); 80 + return src_size; 81 + } 82 + size = output.pos; 83 + size = process_header(record, size); 84 + compressed += size; 85 + dst += size; 86 + dst_size -= size; 87 + } 88 + 89 + return compressed; 90 + } 91 + 92 + size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size, 93 + void *dst, size_t dst_size) 94 + { 95 + size_t ret; 96 + ZSTD_inBuffer input = { src, src_size, 0 }; 97 + ZSTD_outBuffer output = { dst, dst_size, 0 }; 98 + 99 + while (input.pos < input.size) { 100 + ret = ZSTD_decompressStream(data->dstream, &output, &input); 101 + if (ZSTD_isError(ret)) { 102 + pr_err("failed to decompress (B): %ld -> %ld : %s\n", 103 + src_size, output.size, ZSTD_getErrorName(ret)); 104 + break; 105 + } 106 + output.dst = dst + output.pos; 107 + output.size = dst_size - output.pos; 108 + } 109 + 110 + return output.pos; 111 + }