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

Merge tag 'perf-core-for-mingo-5.6-20200106' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

perf record:

Alexey Budankov:

- Adapt affinity for machines with #CPUs > 1K to overcome current 1024 CPUs
mask size limitation of cpu_set_t type.

perf report/top TUI:

Arnaldo Carvalho de Melo:

- Make ENTER consistently present the pop up menu with and without call
chains, to eliminate confusion. The menu continues available at all times
use 'm' and '+' can be used to toggle just one call chain level, 'e' for all
the call chains for a top level histogram entry and 'E' to expand all call
chains in all top level entries. Extra info about these options was added to
the pop up menu entries. Pressing 'k' serves as special hotkey to go straight
to the main vmlinux entries, to avoid having to press enter and then select
"Zoom into the kernel DSO".

perf sched timehist:

David Ahern:

- Add support for filtering on CPU.

perf tests:

Arnaldo Carvalho de Melo:

- Show expected versus obtained values in bp_signal test.

libperf:

Jiri Olsa:

- Move to tools/lib/perf.

- Add man pages.

libapi:

Andrey Zhizhikin:

- Fix gcc9 stringop-truncation compilation error.

tools lib:

Vitaly Chikunov:

- Fix builds when glibc contains strlcpy(), which is the case for ALT Linux.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>

+1578 -357
+30
tools/include/linux/bitmap.h
··· 15 15 const unsigned long *bitmap2, int bits); 16 16 int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, 17 17 const unsigned long *bitmap2, unsigned int bits); 18 + int __bitmap_equal(const unsigned long *bitmap1, 19 + const unsigned long *bitmap2, unsigned int bits); 18 20 void bitmap_clear(unsigned long *map, unsigned int start, int len); 19 21 20 22 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) ··· 126 124 } 127 125 128 126 /* 127 + * bitmap_free - Free bitmap 128 + * @bitmap: pointer to bitmap 129 + */ 130 + static inline void bitmap_free(unsigned long *bitmap) 131 + { 132 + free(bitmap); 133 + } 134 + 135 + /* 129 136 * bitmap_scnprintf - print bitmap list into buffer 130 137 * @bitmap: bitmap 131 138 * @nbits: size of bitmap ··· 157 146 if (small_const_nbits(nbits)) 158 147 return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0; 159 148 return __bitmap_and(dst, src1, src2, nbits); 149 + } 150 + 151 + #ifdef __LITTLE_ENDIAN 152 + #define BITMAP_MEM_ALIGNMENT 8 153 + #else 154 + #define BITMAP_MEM_ALIGNMENT (8 * sizeof(unsigned long)) 155 + #endif 156 + #define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1) 157 + #define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) 158 + 159 + static inline int bitmap_equal(const unsigned long *src1, 160 + const unsigned long *src2, unsigned int nbits) 161 + { 162 + if (small_const_nbits(nbits)) 163 + return !((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits)); 164 + if (__builtin_constant_p(nbits & BITMAP_MEM_MASK) && 165 + IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT)) 166 + return !memcmp(src1, src2, nbits / 8); 167 + return __bitmap_equal(src1, src2, nbits); 160 168 } 161 169 162 170 #endif /* _PERF_BITOPS_H */
+8
tools/include/linux/string.h
··· 17 17 * However uClibc headers also define __GLIBC__ hence the hack below 18 18 */ 19 19 #if defined(__GLIBC__) && !defined(__UCLIBC__) 20 + // pragma diagnostic was introduced in gcc 4.6 21 + #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 22 + #pragma GCC diagnostic push 23 + #pragma GCC diagnostic ignored "-Wredundant-decls" 24 + #endif 20 25 extern size_t strlcpy(char *dest, const char *src, size_t size); 26 + #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) 27 + #pragma GCC diagnostic pop 28 + #endif 21 29 #endif 22 30 23 31 char *str_error_r(int errnum, char *buf, size_t buflen);
+3 -1
tools/lib/api/fs/fs.c
··· 210 210 size_t name_len = strlen(fs->name); 211 211 /* name + "_PATH" + '\0' */ 212 212 char upper_name[name_len + 5 + 1]; 213 + 213 214 memcpy(upper_name, fs->name, name_len); 214 215 mem_toupper(upper_name, name_len); 215 216 strcpy(&upper_name[name_len], "_PATH"); ··· 220 219 return false; 221 220 222 221 fs->found = true; 223 - strncpy(fs->path, override_path, sizeof(fs->path)); 222 + strncpy(fs->path, override_path, sizeof(fs->path) - 1); 223 + fs->path[sizeof(fs->path) - 1] = '\0'; 224 224 return true; 225 225 } 226 226
+15
tools/lib/bitmap.c
··· 71 71 BITMAP_LAST_WORD_MASK(bits)); 72 72 return result != 0; 73 73 } 74 + 75 + int __bitmap_equal(const unsigned long *bitmap1, 76 + const unsigned long *bitmap2, unsigned int bits) 77 + { 78 + unsigned int k, lim = bits/BITS_PER_LONG; 79 + for (k = 0; k < lim; ++k) 80 + if (bitmap1[k] != bitmap2[k]) 81 + return 0; 82 + 83 + if (bits % BITS_PER_LONG) 84 + if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) 85 + return 0; 86 + 87 + return 1; 88 + }
+156
tools/lib/perf/Documentation/Makefile
··· 1 + # SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 + # Most of this file is copied from tools/perf/Documentation/Makefile 3 + 4 + include ../../../scripts/Makefile.include 5 + include ../../../scripts/utilities.mak 6 + 7 + MAN3_TXT = libperf.txt 8 + MAN7_TXT = libperf-counting.txt libperf-sampling.txt 9 + MAN_EX = examples/*.c 10 + 11 + MAN_TXT = $(MAN3_TXT) $(MAN7_TXT) 12 + 13 + _MAN_XML = $(patsubst %.txt,%.xml,$(MAN_TXT)) 14 + _MAN_HTML = $(patsubst %.txt,%.html,$(MAN_TXT)) 15 + _MAN_3 = $(patsubst %.txt,%.3,$(MAN3_TXT)) 16 + _MAN_7 = $(patsubst %.txt,%.7,$(MAN7_TXT)) 17 + 18 + MAN_XML = $(addprefix $(OUTPUT),$(_MAN_XML)) 19 + MAN_HTML = $(addprefix $(OUTPUT),$(_MAN_HTML)) 20 + MAN_3 = $(addprefix $(OUTPUT),$(_MAN_3)) 21 + MAN_7 = $(addprefix $(OUTPUT),$(_MAN_7)) 22 + MAN_X = $(MAN_3) $(MAN_7) 23 + 24 + # Make the path relative to DESTDIR, not prefix 25 + ifndef DESTDIR 26 + prefix ?=$(HOME) 27 + endif 28 + 29 + mandir ?= $(prefix)/share/man 30 + man3dir = $(mandir)/man3 31 + man7dir = $(mandir)/man7 32 + 33 + docdir ?= $(prefix)/share/doc/libperf 34 + htmldir = $(docdir)/html 35 + exdir = $(docdir)/examples 36 + 37 + ASCIIDOC = asciidoc 38 + ASCIIDOC_EXTRA = --unsafe -f asciidoc.conf 39 + ASCIIDOC_HTML = xhtml11 40 + MANPAGE_XSL = manpage-normal.xsl 41 + XMLTO_EXTRA = 42 + XMLTO =xmlto 43 + 44 + INSTALL ?= install 45 + RM ?= rm -f 46 + 47 + # For asciidoc ... 48 + # -7.1.2, no extra settings are needed. 49 + # 8.0-, set ASCIIDOC8. 50 + # 51 + 52 + # For docbook-xsl ... 53 + # -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0) 54 + # 1.69.0, no extra settings are needed? 55 + # 1.69.1-1.71.0, set DOCBOOK_SUPPRESS_SP? 56 + # 1.71.1, no extra settings are needed? 57 + # 1.72.0, set DOCBOOK_XSL_172. 58 + # 1.73.0-, set ASCIIDOC_NO_ROFF 59 + 60 + # If you had been using DOCBOOK_XSL_172 in an attempt to get rid 61 + # of 'the ".ft C" problem' in your generated manpages, and you 62 + # instead ended up with weird characters around callouts, try 63 + # using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8). 64 + 65 + ifdef ASCIIDOC8 66 + ASCIIDOC_EXTRA += -a asciidoc7compatible 67 + endif 68 + ifdef DOCBOOK_XSL_172 69 + ASCIIDOC_EXTRA += -a libperf-asciidoc-no-roff 70 + MANPAGE_XSL = manpage-1.72.xsl 71 + else 72 + ifdef ASCIIDOC_NO_ROFF 73 + # docbook-xsl after 1.72 needs the regular XSL, but will not 74 + # pass-thru raw roff codes from asciidoc.conf, so turn them off. 75 + ASCIIDOC_EXTRA += -a libperf-asciidoc-no-roff 76 + endif 77 + endif 78 + ifdef MAN_BOLD_LITERAL 79 + XMLTO_EXTRA += -m manpage-bold-literal.xsl 80 + endif 81 + ifdef DOCBOOK_SUPPRESS_SP 82 + XMLTO_EXTRA += -m manpage-suppress-sp.xsl 83 + endif 84 + 85 + DESTDIR ?= 86 + DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))' 87 + 88 + export DESTDIR DESTDIR_SQ 89 + 90 + # Please note that there is a minor bug in asciidoc. 91 + # The version after 6.0.3 _will_ include the patch found here: 92 + # http://marc.theaimsgroup.com/?l=libtraceevent&m=111558757202243&w=2 93 + # 94 + # Until that version is released you may have to apply the patch 95 + # yourself - yes, all 6 characters of it! 96 + 97 + QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir 98 + QUIET_SUBDIR1 = 99 + 100 + ifneq ($(findstring $(MAKEFLAGS),w),w) 101 + PRINT_DIR = --no-print-directory 102 + else # "make -w" 103 + NO_SUBDIR = : 104 + endif 105 + 106 + ifneq ($(findstring $(MAKEFLAGS),s),s) 107 + ifneq ($(V),1) 108 + QUIET_ASCIIDOC = @echo ' ASCIIDOC '$@; 109 + QUIET_XMLTO = @echo ' XMLTO '$@; 110 + endif 111 + endif 112 + 113 + all: $(MAN_X) $(MAN_HTML) 114 + 115 + $(MAN_HTML) $(MAN_X): asciidoc.conf 116 + 117 + install-man: all 118 + $(call QUIET_INSTALL, man) \ 119 + $(INSTALL) -d -m 755 $(DESTDIR)$(man3dir); \ 120 + $(INSTALL) -m 644 $(MAN_3) $(DESTDIR)$(man3dir); \ 121 + $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir); \ 122 + $(INSTALL) -m 644 $(MAN_7) $(DESTDIR)$(man7dir); 123 + 124 + install-html: 125 + $(call QUIET_INSTALL, html) \ 126 + $(INSTALL) -d -m 755 $(DESTDIR)$(htmldir); \ 127 + $(INSTALL) -m 644 $(MAN_HTML) $(DESTDIR)$(htmldir); \ 128 + 129 + install-examples: 130 + $(call QUIET_INSTALL, examples) \ 131 + $(INSTALL) -d -m 755 $(DESTDIR)$(exdir); \ 132 + $(INSTALL) -m 644 $(MAN_EX) $(DESTDIR)$(exdir); \ 133 + 134 + CLEAN_FILES = \ 135 + $(MAN_XML) $(addsuffix +,$(MAN_XML)) \ 136 + $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \ 137 + $(MAN_X) 138 + 139 + clean: 140 + $(call QUIET_CLEAN, Documentation) $(RM) $(CLEAN_FILES) 141 + 142 + $(MAN_3): $(OUTPUT)%.3: %.xml 143 + $(QUIET_XMLTO)$(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< 144 + 145 + $(MAN_7): $(OUTPUT)%.7: %.xml 146 + $(QUIET_XMLTO)$(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< 147 + 148 + $(MAN_XML): $(OUTPUT)%.xml: %.txt 149 + $(QUIET_ASCIIDOC)$(ASCIIDOC) -b docbook -d manpage \ 150 + $(ASCIIDOC_EXTRA) -alibperf_version=$(EVENT_PARSE_VERSION) -o $@+ $< && \ 151 + mv $@+ $@ 152 + 153 + $(MAN_HTML): $(OUTPUT)%.html: %.txt 154 + $(QUIET_ASCIIDOC)$(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage \ 155 + $(ASCIIDOC_EXTRA) -aperf_version=$(EVENT_PARSE_VERSION) -o $@+ $< && \ 156 + mv $@+ $@
+120
tools/lib/perf/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">libperf</refmiscinfo> 78 + <refmiscinfo class="version">{libperf_version}</refmiscinfo> 79 + <refmiscinfo class="manual">libperf 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[]
+119
tools/lib/perf/Documentation/examples/sampling.c
··· 1 + #include <linux/perf_event.h> 2 + #include <perf/evlist.h> 3 + #include <perf/evsel.h> 4 + #include <perf/cpumap.h> 5 + #include <perf/threadmap.h> 6 + #include <perf/mmap.h> 7 + #include <perf/core.h> 8 + #include <perf/event.h> 9 + #include <stdio.h> 10 + #include <unistd.h> 11 + 12 + static int libperf_print(enum libperf_print_level level, 13 + const char *fmt, va_list ap) 14 + { 15 + return vfprintf(stderr, fmt, ap); 16 + } 17 + 18 + union u64_swap { 19 + __u64 val64; 20 + __u32 val32[2]; 21 + }; 22 + 23 + int main(int argc, char **argv) 24 + { 25 + struct perf_evlist *evlist; 26 + struct perf_evsel *evsel; 27 + struct perf_mmap *map; 28 + struct perf_cpu_map *cpus; 29 + struct perf_event_attr attr = { 30 + .type = PERF_TYPE_HARDWARE, 31 + .config = PERF_COUNT_HW_CPU_CYCLES, 32 + .disabled = 1, 33 + .freq = 1, 34 + .sample_freq = 10, 35 + .sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_CPU|PERF_SAMPLE_PERIOD, 36 + }; 37 + int err = -1; 38 + union perf_event *event; 39 + 40 + libperf_init(libperf_print); 41 + 42 + cpus = perf_cpu_map__new(NULL); 43 + if (!cpus) { 44 + fprintf(stderr, "failed to create cpus\n"); 45 + return -1; 46 + } 47 + 48 + evlist = perf_evlist__new(); 49 + if (!evlist) { 50 + fprintf(stderr, "failed to create evlist\n"); 51 + goto out_cpus; 52 + } 53 + 54 + evsel = perf_evsel__new(&attr); 55 + if (!evsel) { 56 + fprintf(stderr, "failed to create cycles\n"); 57 + goto out_cpus; 58 + } 59 + 60 + perf_evlist__add(evlist, evsel); 61 + 62 + perf_evlist__set_maps(evlist, cpus, NULL); 63 + 64 + err = perf_evlist__open(evlist); 65 + if (err) { 66 + fprintf(stderr, "failed to open evlist\n"); 67 + goto out_evlist; 68 + } 69 + 70 + err = perf_evlist__mmap(evlist, 4); 71 + if (err) { 72 + fprintf(stderr, "failed to mmap evlist\n"); 73 + goto out_evlist; 74 + } 75 + 76 + perf_evlist__enable(evlist); 77 + sleep(3); 78 + perf_evlist__disable(evlist); 79 + 80 + perf_evlist__for_each_mmap(evlist, map, false) { 81 + if (perf_mmap__read_init(map) < 0) 82 + continue; 83 + 84 + while ((event = perf_mmap__read_event(map)) != NULL) { 85 + int cpu, pid, tid; 86 + __u64 ip, period, *array; 87 + union u64_swap u; 88 + 89 + array = event->sample.array; 90 + 91 + ip = *array; 92 + array++; 93 + 94 + u.val64 = *array; 95 + pid = u.val32[0]; 96 + tid = u.val32[1]; 97 + array++; 98 + 99 + u.val64 = *array; 100 + cpu = u.val32[0]; 101 + array++; 102 + 103 + period = *array; 104 + 105 + fprintf(stdout, "cpu %3d, pid %6d, tid %6d, ip %20llx, period %20llu\n", 106 + cpu, pid, tid, ip, period); 107 + 108 + perf_mmap__consume(map); 109 + } 110 + 111 + perf_mmap__read_done(map); 112 + } 113 + 114 + out_evlist: 115 + perf_evlist__delete(evlist); 116 + out_cpus: 117 + perf_cpu_map__put(cpus); 118 + return err; 119 + }
+211
tools/lib/perf/Documentation/libperf-counting.txt
··· 1 + libperf-counting(7) 2 + =================== 3 + 4 + NAME 5 + ---- 6 + libperf-counting - counting interface 7 + 8 + DESCRIPTION 9 + ----------- 10 + The counting interface provides API to meassure and get count for specific perf events. 11 + 12 + The following test tries to explain count on `counting.c` example. 13 + 14 + It is by no means complete guide to counting, but shows libperf basic API for counting. 15 + 16 + The `counting.c` comes with libbperf package and can be compiled and run like: 17 + 18 + [source,bash] 19 + -- 20 + $ gcc -o counting counting.c -lperf 21 + $ sudo ./counting 22 + count 176792, enabled 176944, run 176944 23 + count 176242, enabled 176242, run 176242 24 + -- 25 + 26 + It requires root access, because of the `PERF_COUNT_SW_CPU_CLOCK` event, 27 + which is available only for root. 28 + 29 + The `counting.c` example monitors two events on the current process and displays their count, in a nutshel it: 30 + 31 + * creates events 32 + * adds them to the event list 33 + * opens and enables events through the event list 34 + * does some workload 35 + * disables events 36 + * reads and displays event counts 37 + * destroys the event list 38 + 39 + The first thing you need to do before using libperf is to call init function: 40 + 41 + [source,c] 42 + -- 43 + 8 static int libperf_print(enum libperf_print_level level, 44 + 9 const char *fmt, va_list ap) 45 + 10 { 46 + 11 return vfprintf(stderr, fmt, ap); 47 + 12 } 48 + 49 + 14 int main(int argc, char **argv) 50 + 15 { 51 + ... 52 + 35 libperf_init(libperf_print); 53 + -- 54 + 55 + It will setup the library and sets function for debug output from library. 56 + 57 + The `libperf_print` callback will receive any message with its debug level, 58 + defined as: 59 + 60 + [source,c] 61 + -- 62 + enum libperf_print_level { 63 + LIBPERF_ERR, 64 + LIBPERF_WARN, 65 + LIBPERF_INFO, 66 + LIBPERF_DEBUG, 67 + LIBPERF_DEBUG2, 68 + LIBPERF_DEBUG3, 69 + }; 70 + -- 71 + 72 + Once the setup is complete we start by defining specific events using the `struct perf_event_attr`. 73 + 74 + We create software events for cpu and task: 75 + 76 + [source,c] 77 + -- 78 + 20 struct perf_event_attr attr1 = { 79 + 21 .type = PERF_TYPE_SOFTWARE, 80 + 22 .config = PERF_COUNT_SW_CPU_CLOCK, 81 + 23 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING, 82 + 24 .disabled = 1, 83 + 25 }; 84 + 26 struct perf_event_attr attr2 = { 85 + 27 .type = PERF_TYPE_SOFTWARE, 86 + 28 .config = PERF_COUNT_SW_TASK_CLOCK, 87 + 29 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING, 88 + 30 .disabled = 1, 89 + 31 }; 90 + -- 91 + 92 + The `read_format` setup tells perf to include timing details together with each count. 93 + 94 + Next step is to prepare threads map. 95 + 96 + In this case we will monitor current process, so we create threads map with single pid (0): 97 + 98 + [source,c] 99 + -- 100 + 37 threads = perf_thread_map__new_dummy(); 101 + 38 if (!threads) { 102 + 39 fprintf(stderr, "failed to create threads\n"); 103 + 40 return -1; 104 + 41 } 105 + 42 106 + 43 perf_thread_map__set_pid(threads, 0, 0); 107 + -- 108 + 109 + Now we create libperf's event list, which will serve as holder for the events we want: 110 + 111 + [source,c] 112 + -- 113 + 45 evlist = perf_evlist__new(); 114 + 46 if (!evlist) { 115 + 47 fprintf(stderr, "failed to create evlist\n"); 116 + 48 goto out_threads; 117 + 49 } 118 + -- 119 + 120 + We create libperf's events for the attributes we defined earlier and add them to the list: 121 + 122 + [source,c] 123 + -- 124 + 51 evsel = perf_evsel__new(&attr1); 125 + 52 if (!evsel) { 126 + 53 fprintf(stderr, "failed to create evsel1\n"); 127 + 54 goto out_evlist; 128 + 55 } 129 + 56 130 + 57 perf_evlist__add(evlist, evsel); 131 + 58 132 + 59 evsel = perf_evsel__new(&attr2); 133 + 60 if (!evsel) { 134 + 61 fprintf(stderr, "failed to create evsel2\n"); 135 + 62 goto out_evlist; 136 + 63 } 137 + 64 138 + 65 perf_evlist__add(evlist, evsel); 139 + -- 140 + 141 + Configure event list with the thread map and open events: 142 + 143 + [source,c] 144 + -- 145 + 67 perf_evlist__set_maps(evlist, NULL, threads); 146 + 68 147 + 69 err = perf_evlist__open(evlist); 148 + 70 if (err) { 149 + 71 fprintf(stderr, "failed to open evsel\n"); 150 + 72 goto out_evlist; 151 + 73 } 152 + -- 153 + 154 + Both events are created as disabled (note the `disabled = 1` assignment above), 155 + so we need to enable the whole list explicitely (both events). 156 + 157 + From this moment events are counting and we can do our workload. 158 + 159 + When we are done we disable the events list. 160 + 161 + [source,c] 162 + -- 163 + 75 perf_evlist__enable(evlist); 164 + 76 165 + 77 while (count--); 166 + 78 167 + 79 perf_evlist__disable(evlist); 168 + -- 169 + 170 + Now we need to get the counts from events, following code iterates throught the events list and read counts: 171 + 172 + [source,c] 173 + -- 174 + 81 perf_evlist__for_each_evsel(evlist, evsel) { 175 + 82 perf_evsel__read(evsel, 0, 0, &counts); 176 + 83 fprintf(stdout, "count %llu, enabled %llu, run %llu\n", 177 + 84 counts.val, counts.ena, counts.run); 178 + 85 } 179 + -- 180 + 181 + And finaly cleanup. 182 + 183 + We close the whole events list (both events) and remove it together with the threads map: 184 + 185 + [source,c] 186 + -- 187 + 87 perf_evlist__close(evlist); 188 + 88 189 + 89 out_evlist: 190 + 90 perf_evlist__delete(evlist); 191 + 91 out_threads: 192 + 92 perf_thread_map__put(threads); 193 + 93 return err; 194 + 94 } 195 + -- 196 + 197 + REPORTING BUGS 198 + -------------- 199 + Report bugs to <linux-perf-users@vger.kernel.org>. 200 + 201 + LICENSE 202 + ------- 203 + libperf is Free Software licensed under the GNU LGPL 2.1 204 + 205 + RESOURCES 206 + --------- 207 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 208 + 209 + SEE ALSO 210 + -------- 211 + libperf(3), libperf-sampling(7)
+243
tools/lib/perf/Documentation/libperf-sampling.txt
··· 1 + libperf-sampling(7) 2 + =================== 3 + 4 + NAME 5 + ---- 6 + libperf-sampling - sampling interface 7 + 8 + 9 + DESCRIPTION 10 + ----------- 11 + The sampling interface provides API to meassure and get count for specific perf events. 12 + 13 + The following test tries to explain count on `sampling.c` example. 14 + 15 + It is by no means complete guide to sampling, but shows libperf basic API for sampling. 16 + 17 + The `sampling.c` comes with libbperf package and can be compiled and run like: 18 + 19 + [source,bash] 20 + -- 21 + $ gcc -o sampling sampling.c -lperf 22 + $ sudo ./sampling 23 + cpu 0, pid 0, tid 0, ip ffffffffad06c4e6, period 1 24 + cpu 0, pid 4465, tid 4469, ip ffffffffad118748, period 18322959 25 + cpu 0, pid 0, tid 0, ip ffffffffad115722, period 33544846 26 + cpu 0, pid 4465, tid 4470, ip 7f84fe0cdad6, period 23687474 27 + cpu 0, pid 0, tid 0, ip ffffffffad9e0349, period 34255790 28 + cpu 0, pid 4465, tid 4469, ip ffffffffad136581, period 38664069 29 + cpu 0, pid 0, tid 0, ip ffffffffad9e55e2, period 21922384 30 + cpu 0, pid 4465, tid 4470, ip 7f84fe0ebebf, period 17655175 31 + ... 32 + -- 33 + 34 + It requires root access, because it uses hardware cycles event. 35 + 36 + The `sampling.c` example profiles/samples all CPUs with hardware cycles, in a nutshel it: 37 + 38 + - creates events 39 + - adds them to the event list 40 + - opens and enables events through the event list 41 + - sleeps for 3 seconds 42 + - disables events 43 + - reads and displays recorded samples 44 + - destroys the event list 45 + 46 + The first thing you need to do before using libperf is to call init function: 47 + 48 + [source,c] 49 + -- 50 + 12 static int libperf_print(enum libperf_print_level level, 51 + 13 const char *fmt, va_list ap) 52 + 14 { 53 + 15 return vfprintf(stderr, fmt, ap); 54 + 16 } 55 + 56 + 23 int main(int argc, char **argv) 57 + 24 { 58 + ... 59 + 40 libperf_init(libperf_print); 60 + -- 61 + 62 + It will setup the library and sets function for debug output from library. 63 + 64 + The `libperf_print` callback will receive any message with its debug level, 65 + defined as: 66 + 67 + [source,c] 68 + -- 69 + enum libperf_print_level { 70 + LIBPERF_ERR, 71 + LIBPERF_WARN, 72 + LIBPERF_INFO, 73 + LIBPERF_DEBUG, 74 + LIBPERF_DEBUG2, 75 + LIBPERF_DEBUG3, 76 + }; 77 + -- 78 + 79 + Once the setup is complete we start by defining cycles event using the `struct perf_event_attr`: 80 + 81 + [source,c] 82 + -- 83 + 29 struct perf_event_attr attr = { 84 + 30 .type = PERF_TYPE_HARDWARE, 85 + 31 .config = PERF_COUNT_HW_CPU_CYCLES, 86 + 32 .disabled = 1, 87 + 33 .freq = 1, 88 + 34 .sample_freq = 10, 89 + 35 .sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_CPU|PERF_SAMPLE_PERIOD, 90 + 36 }; 91 + -- 92 + 93 + Next step is to prepare cpus map. 94 + 95 + In this case we will monitor all the available CPUs: 96 + 97 + [source,c] 98 + -- 99 + 42 cpus = perf_cpu_map__new(NULL); 100 + 43 if (!cpus) { 101 + 44 fprintf(stderr, "failed to create cpus\n"); 102 + 45 return -1; 103 + 46 } 104 + -- 105 + 106 + Now we create libperf's event list, which will serve as holder for the cycles event: 107 + 108 + [source,c] 109 + -- 110 + 48 evlist = perf_evlist__new(); 111 + 49 if (!evlist) { 112 + 50 fprintf(stderr, "failed to create evlist\n"); 113 + 51 goto out_cpus; 114 + 52 } 115 + -- 116 + 117 + We create libperf's event for the cycles attribute we defined earlier and add it to the list: 118 + 119 + [source,c] 120 + -- 121 + 54 evsel = perf_evsel__new(&attr); 122 + 55 if (!evsel) { 123 + 56 fprintf(stderr, "failed to create cycles\n"); 124 + 57 goto out_cpus; 125 + 58 } 126 + 59 127 + 60 perf_evlist__add(evlist, evsel); 128 + -- 129 + 130 + Configure event list with the cpus map and open event: 131 + 132 + [source,c] 133 + -- 134 + 62 perf_evlist__set_maps(evlist, cpus, NULL); 135 + 63 136 + 64 err = perf_evlist__open(evlist); 137 + 65 if (err) { 138 + 66 fprintf(stderr, "failed to open evlist\n"); 139 + 67 goto out_evlist; 140 + 68 } 141 + -- 142 + 143 + Once the events list is open, we can create memory maps AKA perf ring buffers: 144 + 145 + [source,c] 146 + -- 147 + 70 err = perf_evlist__mmap(evlist, 4); 148 + 71 if (err) { 149 + 72 fprintf(stderr, "failed to mmap evlist\n"); 150 + 73 goto out_evlist; 151 + 74 } 152 + -- 153 + 154 + The event is created as disabled (note the `disabled = 1` assignment above), 155 + so we need to enable the events list explicitely. 156 + 157 + From this moment the cycles event is sampling. 158 + 159 + We will sleep for 3 seconds while the ring buffers get data from all CPUs, then we disable the events list. 160 + 161 + [source,c] 162 + -- 163 + 76 perf_evlist__enable(evlist); 164 + 77 sleep(3); 165 + 78 perf_evlist__disable(evlist); 166 + -- 167 + 168 + Following code walks through the ring buffers and reads stored events/samples: 169 + 170 + [source,c] 171 + -- 172 + 80 perf_evlist__for_each_mmap(evlist, map, false) { 173 + 81 if (perf_mmap__read_init(map) < 0) 174 + 82 continue; 175 + 83 176 + 84 while ((event = perf_mmap__read_event(map)) != NULL) { 177 + 178 + /* process event */ 179 + 180 + 108 perf_mmap__consume(map); 181 + 109 } 182 + 110 perf_mmap__read_done(map); 183 + 111 } 184 + 185 + -- 186 + 187 + Each sample needs to get parsed: 188 + 189 + [source,c] 190 + -- 191 + 85 int cpu, pid, tid; 192 + 86 __u64 ip, period, *array; 193 + 87 union u64_swap u; 194 + 88 195 + 89 array = event->sample.array; 196 + 90 197 + 91 ip = *array; 198 + 92 array++; 199 + 93 200 + 94 u.val64 = *array; 201 + 95 pid = u.val32[0]; 202 + 96 tid = u.val32[1]; 203 + 97 array++; 204 + 98 205 + 99 u.val64 = *array; 206 + 100 cpu = u.val32[0]; 207 + 101 array++; 208 + 102 209 + 103 period = *array; 210 + 104 211 + 105 fprintf(stdout, "cpu %3d, pid %6d, tid %6d, ip %20llx, period %20llu\n", 212 + 106 cpu, pid, tid, ip, period); 213 + -- 214 + 215 + And finaly cleanup. 216 + 217 + We close the whole events list (both events) and remove it together with the threads map: 218 + 219 + [source,c] 220 + -- 221 + 113 out_evlist: 222 + 114 perf_evlist__delete(evlist); 223 + 115 out_cpus: 224 + 116 perf_cpu_map__put(cpus); 225 + 117 return err; 226 + 118 } 227 + -- 228 + 229 + REPORTING BUGS 230 + -------------- 231 + Report bugs to <linux-perf-users@vger.kernel.org>. 232 + 233 + LICENSE 234 + ------- 235 + libperf is Free Software licensed under the GNU LGPL 2.1 236 + 237 + RESOURCES 238 + --------- 239 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 240 + 241 + SEE ALSO 242 + -------- 243 + libperf(3), libperf-counting(7)
+246
tools/lib/perf/Documentation/libperf.txt
··· 1 + libperf(3) 2 + ========== 3 + 4 + NAME 5 + ---- 6 + libperf - Linux kernel perf event library 7 + 8 + 9 + SYNOPSIS 10 + -------- 11 + *Generic API:* 12 + 13 + [source,c] 14 + -- 15 + #include <perf/core.h> 16 + 17 + enum libperf_print_level { 18 + LIBPERF_ERR, 19 + LIBPERF_WARN, 20 + LIBPERF_INFO, 21 + LIBPERF_DEBUG, 22 + LIBPERF_DEBUG2, 23 + LIBPERF_DEBUG3, 24 + }; 25 + 26 + typedef int (*libperf_print_fn_t)(enum libperf_print_level level, 27 + const char *, va_list ap); 28 + 29 + void libperf_init(libperf_print_fn_t fn); 30 + -- 31 + 32 + *API to handle cpu maps:* 33 + 34 + [source,c] 35 + -- 36 + #include <perf/cpumap.h> 37 + 38 + struct perf_cpu_map; 39 + 40 + struct perf_cpu_map *perf_cpu_map__dummy_new(void); 41 + struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list); 42 + struct perf_cpu_map *perf_cpu_map__read(FILE *file); 43 + struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map); 44 + struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig, 45 + struct perf_cpu_map *other); 46 + void perf_cpu_map__put(struct perf_cpu_map *map); 47 + int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx); 48 + int perf_cpu_map__nr(const struct perf_cpu_map *cpus); 49 + bool perf_cpu_map__empty(const struct perf_cpu_map *map); 50 + int perf_cpu_map__max(struct perf_cpu_map *map); 51 + 52 + #define perf_cpu_map__for_each_cpu(cpu, idx, cpus) 53 + -- 54 + 55 + *API to handle thread maps:* 56 + 57 + [source,c] 58 + -- 59 + #include <perf/threadmap.h> 60 + 61 + struct perf_thread_map; 62 + 63 + struct perf_thread_map *perf_thread_map__new_dummy(void); 64 + 65 + void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid); 66 + char *perf_thread_map__comm(struct perf_thread_map *map, int thread); 67 + int perf_thread_map__nr(struct perf_thread_map *threads); 68 + pid_t perf_thread_map__pid(struct perf_thread_map *map, int thread); 69 + 70 + struct perf_thread_map *perf_thread_map__get(struct perf_thread_map *map); 71 + void perf_thread_map__put(struct perf_thread_map *map); 72 + -- 73 + 74 + *API to handle event lists:* 75 + 76 + [source,c] 77 + -- 78 + #include <perf/evlist.h> 79 + 80 + struct perf_evlist; 81 + 82 + void perf_evlist__add(struct perf_evlist *evlist, 83 + struct perf_evsel *evsel); 84 + void perf_evlist__remove(struct perf_evlist *evlist, 85 + struct perf_evsel *evsel); 86 + struct perf_evlist *perf_evlist__new(void); 87 + void perf_evlist__delete(struct perf_evlist *evlist); 88 + struct perf_evsel* perf_evlist__next(struct perf_evlist *evlist, 89 + struct perf_evsel *evsel); 90 + int perf_evlist__open(struct perf_evlist *evlist); 91 + void perf_evlist__close(struct perf_evlist *evlist); 92 + void perf_evlist__enable(struct perf_evlist *evlist); 93 + void perf_evlist__disable(struct perf_evlist *evlist); 94 + 95 + #define perf_evlist__for_each_evsel(evlist, pos) 96 + 97 + void perf_evlist__set_maps(struct perf_evlist *evlist, 98 + struct perf_cpu_map *cpus, 99 + struct perf_thread_map *threads); 100 + int perf_evlist__poll(struct perf_evlist *evlist, int timeout); 101 + int perf_evlist__filter_pollfd(struct perf_evlist *evlist, 102 + short revents_and_mask); 103 + 104 + int perf_evlist__mmap(struct perf_evlist *evlist, int pages); 105 + void perf_evlist__munmap(struct perf_evlist *evlist); 106 + 107 + struct perf_mmap *perf_evlist__next_mmap(struct perf_evlist *evlist, 108 + struct perf_mmap *map, 109 + bool overwrite); 110 + 111 + #define perf_evlist__for_each_mmap(evlist, pos, overwrite) 112 + -- 113 + 114 + *API to handle events:* 115 + 116 + [source,c] 117 + -- 118 + #include <perf/evsel.h>* 119 + 120 + struct perf_evsel; 121 + 122 + struct perf_counts_values { 123 + union { 124 + struct { 125 + uint64_t val; 126 + uint64_t ena; 127 + uint64_t run; 128 + }; 129 + uint64_t values[3]; 130 + }; 131 + }; 132 + 133 + struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr); 134 + void perf_evsel__delete(struct perf_evsel *evsel); 135 + int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, 136 + struct perf_thread_map *threads); 137 + void perf_evsel__close(struct perf_evsel *evsel); 138 + void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu); 139 + int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, 140 + struct perf_counts_values *count); 141 + int perf_evsel__enable(struct perf_evsel *evsel); 142 + int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu); 143 + int perf_evsel__disable(struct perf_evsel *evsel); 144 + int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu); 145 + struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel); 146 + struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel); 147 + struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel); 148 + -- 149 + 150 + *API to handle maps (perf ring buffers):* 151 + 152 + [source,c] 153 + -- 154 + #include <perf/mmap.h> 155 + 156 + struct perf_mmap; 157 + 158 + void perf_mmap__consume(struct perf_mmap *map); 159 + int perf_mmap__read_init(struct perf_mmap *map); 160 + void perf_mmap__read_done(struct perf_mmap *map); 161 + union perf_event *perf_mmap__read_event(struct perf_mmap *map); 162 + -- 163 + 164 + *Structures to access perf API events:* 165 + 166 + [source,c] 167 + -- 168 + #include <perf/event.h> 169 + 170 + struct perf_record_mmap; 171 + struct perf_record_mmap2; 172 + struct perf_record_comm; 173 + struct perf_record_namespaces; 174 + struct perf_record_fork; 175 + struct perf_record_lost; 176 + struct perf_record_lost_samples; 177 + struct perf_record_read; 178 + struct perf_record_throttle; 179 + struct perf_record_ksymbol; 180 + struct perf_record_bpf_event; 181 + struct perf_record_sample; 182 + struct perf_record_switch; 183 + struct perf_record_header_attr; 184 + struct perf_record_record_cpu_map; 185 + struct perf_record_cpu_map_data; 186 + struct perf_record_cpu_map; 187 + struct perf_record_event_update_cpus; 188 + struct perf_record_event_update_scale; 189 + struct perf_record_event_update; 190 + struct perf_trace_event_type; 191 + struct perf_record_header_event_type; 192 + struct perf_record_header_tracing_data; 193 + struct perf_record_header_build_id; 194 + struct perf_record_id_index; 195 + struct perf_record_auxtrace_info; 196 + struct perf_record_auxtrace; 197 + struct perf_record_auxtrace_error; 198 + struct perf_record_aux; 199 + struct perf_record_itrace_start; 200 + struct perf_record_thread_map_entry; 201 + struct perf_record_thread_map; 202 + struct perf_record_stat_config_entry; 203 + struct perf_record_stat_config; 204 + struct perf_record_stat; 205 + struct perf_record_stat_round; 206 + struct perf_record_time_conv; 207 + struct perf_record_header_feature; 208 + struct perf_record_compressed; 209 + -- 210 + 211 + DESCRIPTION 212 + ----------- 213 + The libperf library provides an API to access the linux kernel perf 214 + events subsystem. 215 + 216 + Following objects are key to the libperf interface: 217 + 218 + [horizontal] 219 + 220 + struct perf_cpu_map:: Provides a cpu list abstraction. 221 + 222 + struct perf_thread_map:: Provides a thread list abstraction. 223 + 224 + struct perf_evsel:: Provides an abstraction for single a perf event. 225 + 226 + struct perf_evlist:: Gathers several struct perf_evsel object and performs functions on all of them. 227 + 228 + struct perf_mmap:: Provides an abstraction for accessing perf ring buffer. 229 + 230 + The exported API functions bind these objects together. 231 + 232 + REPORTING BUGS 233 + -------------- 234 + Report bugs to <linux-perf-users@vger.kernel.org>. 235 + 236 + LICENSE 237 + ------- 238 + libperf is Free Software licensed under the GNU LGPL 2.1 239 + 240 + RESOURCES 241 + --------- 242 + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 243 + 244 + SEE ALSO 245 + -------- 246 + libperf-sampling(7), libperf-counting(7)
+14
tools/lib/perf/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/perf/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/perf/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/perf/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/perf/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>
+7
tools/lib/string.c
··· 96 96 * If libc has strlcpy() then that version will override this 97 97 * implementation: 98 98 */ 99 + #ifdef __clang__ 100 + #pragma clang diagnostic push 101 + #pragma clang diagnostic ignored "-Wignored-attributes" 102 + #endif 99 103 size_t __weak strlcpy(char *dest, const char *src, size_t size) 100 104 { 101 105 size_t ret = strlen(src); ··· 111 107 } 112 108 return ret; 113 109 } 110 + #ifdef __clang__ 111 + #pragma clang diagnostic pop 112 + #endif 114 113 115 114 /** 116 115 * skip_spaces - Removes leading whitespace from @str.
+3 -1
tools/lib/traceevent/parse-filter.c
··· 1228 1228 } 1229 1229 1230 1230 filter_type = add_filter_type(filter, event->id); 1231 - if (filter_type == NULL) 1231 + if (filter_type == NULL) { 1232 + free_arg(arg); 1232 1233 return TEP_ERRNO__MEM_ALLOC_FAILED; 1234 + } 1233 1235 1234 1236 if (filter_type->filter) 1235 1237 free_arg(filter_type->filter);
+4
tools/perf/Documentation/perf-sched.txt
··· 110 110 --max-stack:: 111 111 Maximum number of functions to display in backtrace, default 5. 112 112 113 + -C=:: 114 + --cpu=:: 115 + Only show events for the given CPU(s) (comma separated list). 116 + 113 117 -p=:: 114 118 --pid=:: 115 119 Only show events for given process ID (comma separated list).
+1
tools/perf/MANIFEST
··· 7 7 tools/lib/api 8 8 tools/lib/bpf 9 9 tools/lib/subcmd 10 + tools/lib/perf 10 11 tools/lib/argv_split.c 11 12 tools/lib/ctype.c 12 13 tools/lib/hweight.c
+1 -1
tools/perf/Makefile.config
··· 286 286 endif 287 287 endif 288 288 289 - INC_FLAGS += -I$(src-perf)/lib/include 289 + INC_FLAGS += -I$(srctree)/tools/lib/perf/include 290 290 INC_FLAGS += -I$(src-perf)/util/include 291 291 INC_FLAGS += -I$(src-perf)/arch/$(SRCARCH)/include 292 292 INC_FLAGS += -I$(srctree)/tools/include/
+1 -1
tools/perf/Makefile.perf
··· 230 230 TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ 231 231 BPF_DIR = $(srctree)/tools/lib/bpf/ 232 232 SUBCMD_DIR = $(srctree)/tools/lib/subcmd/ 233 - LIBPERF_DIR = $(srctree)/tools/perf/lib/ 233 + LIBPERF_DIR = $(srctree)/tools/lib/perf/ 234 234 235 235 # Set FEATURE_TESTS to 'all' so all possible feature checkers are executed. 236 236 # Without this setting the output feature dump file misses some features, for
+2 -2
tools/perf/builtin-c2c.c
··· 2384 2384 c2c_browser__update_nr_entries(browser); 2385 2385 2386 2386 while (1) { 2387 - key = hist_browser__run(browser, "? - help", true); 2387 + key = hist_browser__run(browser, "? - help", true, 0); 2388 2388 2389 2389 switch (key) { 2390 2390 case 's': ··· 2453 2453 c2c_browser__update_nr_entries(browser); 2454 2454 2455 2455 while (1) { 2456 - key = hist_browser__run(browser, "? - help", true); 2456 + key = hist_browser__run(browser, "? - help", true, 0); 2457 2457 2458 2458 switch (key) { 2459 2459 case 'q':
+22 -6
tools/perf/builtin-record.c
··· 62 62 #include <linux/string.h> 63 63 #include <linux/time64.h> 64 64 #include <linux/zalloc.h> 65 + #include <linux/bitmap.h> 65 66 66 67 struct switch_output { 67 68 bool enabled; ··· 94 93 bool timestamp_boundary; 95 94 struct switch_output switch_output; 96 95 unsigned long long samples; 97 - cpu_set_t affinity_mask; 96 + struct mmap_cpu_mask affinity_mask; 98 97 unsigned long output_max_size; /* = 0: unlimited */ 99 98 }; 100 99 ··· 962 961 static void record__adjust_affinity(struct record *rec, struct mmap *map) 963 962 { 964 963 if (rec->opts.affinity != PERF_AFFINITY_SYS && 965 - !CPU_EQUAL(&rec->affinity_mask, &map->affinity_mask)) { 966 - CPU_ZERO(&rec->affinity_mask); 967 - CPU_OR(&rec->affinity_mask, &rec->affinity_mask, &map->affinity_mask); 968 - sched_setaffinity(0, sizeof(rec->affinity_mask), &rec->affinity_mask); 964 + !bitmap_equal(rec->affinity_mask.bits, map->affinity_mask.bits, 965 + rec->affinity_mask.nbits)) { 966 + bitmap_zero(rec->affinity_mask.bits, rec->affinity_mask.nbits); 967 + bitmap_or(rec->affinity_mask.bits, rec->affinity_mask.bits, 968 + map->affinity_mask.bits, rec->affinity_mask.nbits); 969 + sched_setaffinity(0, MMAP_CPU_MASK_BYTES(&rec->affinity_mask), 970 + (cpu_set_t *)rec->affinity_mask.bits); 971 + if (verbose == 2) 972 + mmap_cpu_mask__scnprintf(&rec->affinity_mask, "thread"); 969 973 } 970 974 } 971 975 ··· 2439 2433 # undef REASON 2440 2434 #endif 2441 2435 2442 - CPU_ZERO(&rec->affinity_mask); 2443 2436 rec->opts.affinity = PERF_AFFINITY_SYS; 2444 2437 2445 2438 rec->evlist = evlist__new(); ··· 2503 2498 symbol_conf.allow_aliases = true; 2504 2499 2505 2500 symbol__init(NULL); 2501 + 2502 + if (rec->opts.affinity != PERF_AFFINITY_SYS) { 2503 + rec->affinity_mask.nbits = cpu__max_cpu(); 2504 + rec->affinity_mask.bits = bitmap_alloc(rec->affinity_mask.nbits); 2505 + if (!rec->affinity_mask.bits) { 2506 + pr_err("Failed to allocate thread mask for %zd cpus\n", rec->affinity_mask.nbits); 2507 + return -ENOMEM; 2508 + } 2509 + pr_debug2("thread mask[%zd]: empty\n", rec->affinity_mask.nbits); 2510 + } 2506 2511 2507 2512 err = record__auxtrace_init(rec); 2508 2513 if (err) ··· 2628 2613 2629 2614 err = __cmd_record(&record, argc, argv); 2630 2615 out: 2616 + bitmap_free(rec->affinity_mask.bits); 2631 2617 evlist__delete(rec->evlist); 2632 2618 symbol__exit(); 2633 2619 auxtrace_record__free(rec->itr);
+4 -1
tools/perf/builtin-report.c
··· 1076 1076 struct stat st; 1077 1077 bool has_br_stack = false; 1078 1078 int branch_mode = -1; 1079 + int last_key = 0; 1079 1080 bool branch_call_mode = false; 1080 1081 #define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent" 1081 1082 static const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n" ··· 1451 1450 sort_order = sort_tmp; 1452 1451 } 1453 1452 1454 - if (setup_sorting(session->evlist) < 0) { 1453 + if ((last_key != K_SWITCH_INPUT_DATA) && 1454 + (setup_sorting(session->evlist) < 0)) { 1455 1455 if (sort_order) 1456 1456 parse_options_usage(report_usage, options, "s", 1); 1457 1457 if (field_order) ··· 1532 1530 ret = __cmd_report(&report); 1533 1531 if (ret == K_SWITCH_INPUT_DATA) { 1534 1532 perf_session__delete(session); 1533 + last_key = K_SWITCH_INPUT_DATA; 1535 1534 goto repeat; 1536 1535 } else 1537 1536 ret = 0;
+13
tools/perf/builtin-sched.c
··· 51 51 #define SYM_LEN 129 52 52 #define MAX_PID 1024000 53 53 54 + static const char *cpu_list; 55 + static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 56 + 54 57 struct sched_atom; 55 58 56 59 struct task_desc { ··· 2011 2008 char nstr[30]; 2012 2009 u64 wait_time; 2013 2010 2011 + if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 2012 + return; 2013 + 2014 2014 timestamp__scnprintf_usec(t, tstr, sizeof(tstr)); 2015 2015 printf("%15s [%04d] ", tstr, sample->cpu); 2016 2016 ··· 3000 2994 if (IS_ERR(session)) 3001 2995 return PTR_ERR(session); 3002 2996 2997 + if (cpu_list) { 2998 + err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); 2999 + if (err < 0) 3000 + goto out; 3001 + } 3002 + 3003 3003 evlist = session->evlist; 3004 3004 3005 3005 symbol__init(&session->header.env); ··· 3441 3429 "analyze events only for given process id(s)"), 3442 3430 OPT_STRING('t', "tid", &symbol_conf.tid_list_str, "tid[,tid...]", 3443 3431 "analyze events only for given thread id(s)"), 3432 + OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 3444 3433 OPT_PARENT(sched_options) 3445 3434 }; 3446 3435
tools/perf/lib/Build tools/lib/perf/Build
-7
tools/perf/lib/Documentation/Makefile
··· 1 - all: 2 - rst2man man/libperf.rst > man/libperf.7 3 - rst2pdf tutorial/tutorial.rst 4 - 5 - clean: 6 - rm -f man/libperf.7 7 - rm -f tutorial/tutorial.pdf
-100
tools/perf/lib/Documentation/man/libperf.rst
··· 1 - .. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 - 3 - libperf 4 - 5 - The libperf library provides an API to access the linux kernel perf 6 - events subsystem. It provides the following high level objects: 7 - 8 - - struct perf_cpu_map 9 - - struct perf_thread_map 10 - - struct perf_evlist 11 - - struct perf_evsel 12 - 13 - reference 14 - ========= 15 - Function reference by header files: 16 - 17 - perf/core.h 18 - ----------- 19 - .. code-block:: c 20 - 21 - typedef int (\*libperf_print_fn_t)(enum libperf_print_level level, 22 - const char \*, va_list ap); 23 - 24 - void libperf_set_print(libperf_print_fn_t fn); 25 - 26 - perf/cpumap.h 27 - ------------- 28 - .. code-block:: c 29 - 30 - struct perf_cpu_map \*perf_cpu_map__dummy_new(void); 31 - struct perf_cpu_map \*perf_cpu_map__new(const char \*cpu_list); 32 - struct perf_cpu_map \*perf_cpu_map__read(FILE \*file); 33 - struct perf_cpu_map \*perf_cpu_map__get(struct perf_cpu_map \*map); 34 - void perf_cpu_map__put(struct perf_cpu_map \*map); 35 - int perf_cpu_map__cpu(const struct perf_cpu_map \*cpus, int idx); 36 - int perf_cpu_map__nr(const struct perf_cpu_map \*cpus); 37 - perf_cpu_map__for_each_cpu(cpu, idx, cpus) 38 - 39 - perf/threadmap.h 40 - ---------------- 41 - .. code-block:: c 42 - 43 - struct perf_thread_map \*perf_thread_map__new_dummy(void); 44 - void perf_thread_map__set_pid(struct perf_thread_map \*map, int thread, pid_t pid); 45 - char \*perf_thread_map__comm(struct perf_thread_map \*map, int thread); 46 - struct perf_thread_map \*perf_thread_map__get(struct perf_thread_map \*map); 47 - void perf_thread_map__put(struct perf_thread_map \*map); 48 - 49 - perf/evlist.h 50 - ------------- 51 - .. code-block:: 52 - 53 - void perf_evlist__init(struct perf_evlist \*evlist); 54 - void perf_evlist__add(struct perf_evlist \*evlist, 55 - struct perf_evsel \*evsel); 56 - void perf_evlist__remove(struct perf_evlist \*evlist, 57 - struct perf_evsel \*evsel); 58 - struct perf_evlist \*perf_evlist__new(void); 59 - void perf_evlist__delete(struct perf_evlist \*evlist); 60 - struct perf_evsel\* perf_evlist__next(struct perf_evlist \*evlist, 61 - struct perf_evsel \*evsel); 62 - int perf_evlist__open(struct perf_evlist \*evlist); 63 - void perf_evlist__close(struct perf_evlist \*evlist); 64 - void perf_evlist__enable(struct perf_evlist \*evlist); 65 - void perf_evlist__disable(struct perf_evlist \*evlist); 66 - perf_evlist__for_each_evsel(evlist, pos) 67 - void perf_evlist__set_maps(struct perf_evlist \*evlist, 68 - struct perf_cpu_map \*cpus, 69 - struct perf_thread_map \*threads); 70 - 71 - perf/evsel.h 72 - ------------ 73 - .. code-block:: c 74 - 75 - struct perf_counts_values { 76 - union { 77 - struct { 78 - uint64_t val; 79 - uint64_t ena; 80 - uint64_t run; 81 - }; 82 - uint64_t values[3]; 83 - }; 84 - }; 85 - 86 - void perf_evsel__init(struct perf_evsel \*evsel, 87 - struct perf_event_attr \*attr); 88 - struct perf_evsel \*perf_evsel__new(struct perf_event_attr \*attr); 89 - void perf_evsel__delete(struct perf_evsel \*evsel); 90 - int perf_evsel__open(struct perf_evsel \*evsel, struct perf_cpu_map \*cpus, 91 - struct perf_thread_map \*threads); 92 - void perf_evsel__close(struct perf_evsel \*evsel); 93 - int perf_evsel__read(struct perf_evsel \*evsel, int cpu, int thread, 94 - struct perf_counts_values \*count); 95 - int perf_evsel__enable(struct perf_evsel \*evsel); 96 - int perf_evsel__disable(struct perf_evsel \*evsel); 97 - int perf_evsel__apply_filter(struct perf_evsel \*evsel, const char \*filter); 98 - struct perf_cpu_map \*perf_evsel__cpus(struct perf_evsel \*evsel); 99 - struct perf_thread_map \*perf_evsel__threads(struct perf_evsel \*evsel); 100 - struct perf_event_attr \*perf_evsel__attr(struct perf_evsel \*evsel);
-123
tools/perf/lib/Documentation/tutorial/tutorial.rst
··· 1 - .. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 - 3 - libperf tutorial 4 - ================ 5 - 6 - Compile and install libperf from kernel sources 7 - =============================================== 8 - .. code-block:: bash 9 - 10 - git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 11 - cd linux/tools/perf/lib 12 - make 13 - sudo make install prefix=/usr 14 - 15 - Libperf object 16 - ============== 17 - The libperf library provides several high level objects: 18 - 19 - struct perf_cpu_map 20 - Provides a cpu list abstraction. 21 - 22 - struct perf_thread_map 23 - Provides a thread list abstraction. 24 - 25 - struct perf_evsel 26 - Provides an abstraction for single a perf event. 27 - 28 - struct perf_evlist 29 - Gathers several struct perf_evsel object and performs functions on all of them. 30 - 31 - The exported API binds these objects together, 32 - for full reference see the libperf.7 man page. 33 - 34 - Examples 35 - ======== 36 - Examples aim to explain libperf functionality on simple use cases. 37 - They are based in on a checked out linux kernel git tree: 38 - 39 - .. code-block:: bash 40 - 41 - $ cd tools/perf/lib/Documentation/tutorial/ 42 - $ ls -d ex-* 43 - ex-1-compile ex-2-evsel-stat ex-3-evlist-stat 44 - 45 - ex-1-compile example 46 - ==================== 47 - This example shows the basic usage of *struct perf_cpu_map*, 48 - how to create it and display its cpus: 49 - 50 - .. code-block:: bash 51 - 52 - $ cd ex-1-compile/ 53 - $ make 54 - gcc -o test test.c -lperf 55 - $ ./test 56 - 0 1 2 3 4 5 6 7 57 - 58 - 59 - The full code listing is here: 60 - 61 - .. code-block:: c 62 - 63 - 1 #include <perf/cpumap.h> 64 - 2 65 - 3 int main(int argc, char **Argv) 66 - 4 { 67 - 5 struct perf_cpu_map *cpus; 68 - 6 int cpu, tmp; 69 - 7 70 - 8 cpus = perf_cpu_map__new(NULL); 71 - 9 72 - 10 perf_cpu_map__for_each_cpu(cpu, tmp, cpus) 73 - 11 fprintf(stdout, "%d ", cpu); 74 - 12 75 - 13 fprintf(stdout, "\n"); 76 - 14 77 - 15 perf_cpu_map__put(cpus); 78 - 16 return 0; 79 - 17 } 80 - 81 - 82 - First you need to include the proper header to have *struct perf_cpumap* 83 - declaration and functions: 84 - 85 - .. code-block:: c 86 - 87 - 1 #include <perf/cpumap.h> 88 - 89 - 90 - The *struct perf_cpumap* object is created by *perf_cpu_map__new* call. 91 - The *NULL* argument asks it to populate the object with the current online CPUs list: 92 - 93 - .. code-block:: c 94 - 95 - 8 cpus = perf_cpu_map__new(NULL); 96 - 97 - This is paired with a *perf_cpu_map__put*, that drops its reference at the end, possibly deleting it. 98 - 99 - .. code-block:: c 100 - 101 - 15 perf_cpu_map__put(cpus); 102 - 103 - The iteration through the *struct perf_cpumap* CPUs is done using the *perf_cpu_map__for_each_cpu* 104 - macro which requires 3 arguments: 105 - 106 - - cpu - the cpu numer 107 - - tmp - iteration helper variable 108 - - cpus - the *struct perf_cpumap* object 109 - 110 - .. code-block:: c 111 - 112 - 10 perf_cpu_map__for_each_cpu(cpu, tmp, cpus) 113 - 11 fprintf(stdout, "%d ", cpu); 114 - 115 - ex-2-evsel-stat example 116 - ======================= 117 - 118 - TBD 119 - 120 - ex-3-evlist-stat example 121 - ======================== 122 - 123 - TBD
+5 -2
tools/perf/lib/Makefile tools/lib/perf/Makefile
··· 60 60 endif 61 61 62 62 INCLUDES = \ 63 - -I$(srctree)/tools/perf/lib/include \ 63 + -I$(srctree)/tools/lib/perf/include \ 64 64 -I$(srctree)/tools/lib/ \ 65 65 -I$(srctree)/tools/include \ 66 66 -I$(srctree)/tools/arch/$(SRCARCH)/include/ \ ··· 181 181 $(call QUIET_INSTALL, $(LIBPERF_PC)) \ 182 182 $(call do_install,$(LIBPERF_PC),$(libdir_SQ)/pkgconfig,644) 183 183 184 - install: install_lib install_headers install_pkgconfig 184 + install_doc: 185 + $(Q)$(MAKE) -C Documentation install-man install-html install-examples 186 + 187 + install: install_lib install_headers install_pkgconfig install_doc 185 188 186 189 FORCE: 187 190
tools/perf/lib/core.c tools/lib/perf/core.c
tools/perf/lib/cpumap.c tools/lib/perf/cpumap.c
tools/perf/lib/evlist.c tools/lib/perf/evlist.c
tools/perf/lib/evsel.c tools/lib/perf/evsel.c
tools/perf/lib/include/internal/cpumap.h tools/lib/perf/include/internal/cpumap.h
tools/perf/lib/include/internal/evlist.h tools/lib/perf/include/internal/evlist.h
tools/perf/lib/include/internal/evsel.h tools/lib/perf/include/internal/evsel.h
tools/perf/lib/include/internal/lib.h tools/lib/perf/include/internal/lib.h
tools/perf/lib/include/internal/mmap.h tools/lib/perf/include/internal/mmap.h
tools/perf/lib/include/internal/tests.h tools/lib/perf/include/internal/tests.h
tools/perf/lib/include/internal/threadmap.h tools/lib/perf/include/internal/threadmap.h
tools/perf/lib/include/internal/xyarray.h tools/lib/perf/include/internal/xyarray.h
tools/perf/lib/include/perf/core.h tools/lib/perf/include/perf/core.h
tools/perf/lib/include/perf/cpumap.h tools/lib/perf/include/perf/cpumap.h
tools/perf/lib/include/perf/event.h tools/lib/perf/include/perf/event.h
tools/perf/lib/include/perf/evlist.h tools/lib/perf/include/perf/evlist.h
tools/perf/lib/include/perf/evsel.h tools/lib/perf/include/perf/evsel.h
tools/perf/lib/include/perf/mmap.h tools/lib/perf/include/perf/mmap.h
tools/perf/lib/include/perf/threadmap.h tools/lib/perf/include/perf/threadmap.h
tools/perf/lib/internal.h tools/lib/perf/internal.h
tools/perf/lib/lib.c tools/lib/perf/lib.c
tools/perf/lib/libperf.map tools/lib/perf/libperf.map
tools/perf/lib/libperf.pc.template tools/lib/perf/libperf.pc.template
tools/perf/lib/mmap.c tools/lib/perf/mmap.c
+1 -1
tools/perf/lib/tests/Makefile tools/lib/perf/tests/Makefile
··· 16 16 17 17 include $(srctree)/tools/scripts/Makefile.include 18 18 19 - INCLUDE = -I$(srctree)/tools/perf/lib/include -I$(srctree)/tools/include -I$(srctree)/tools/lib 19 + INCLUDE = -I$(srctree)/tools/lib/perf/include -I$(srctree)/tools/include -I$(srctree)/tools/lib 20 20 21 21 $(TESTS_A): FORCE 22 22 $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -o $@ $(subst -a,.c,$@) ../libperf.a $(LIBAPI)
tools/perf/lib/tests/test-cpumap.c tools/lib/perf/tests/test-cpumap.c
tools/perf/lib/tests/test-evlist.c tools/lib/perf/tests/test-evlist.c
tools/perf/lib/tests/test-evsel.c tools/lib/perf/tests/test-evsel.c
tools/perf/lib/tests/test-threadmap.c tools/lib/perf/tests/test-threadmap.c
tools/perf/lib/threadmap.c tools/lib/perf/threadmap.c
tools/perf/lib/xyarray.c tools/lib/perf/xyarray.c
+5 -5
tools/perf/tests/bp_signal.c
··· 263 263 if (count1 == 11) 264 264 pr_debug("failed: RF EFLAG recursion issue detected\n"); 265 265 else 266 - pr_debug("failed: wrong count for bp1%lld\n", count1); 266 + pr_debug("failed: wrong count for bp1: %lld, expected 1\n", count1); 267 267 } 268 268 269 269 if (overflows != 3) 270 - pr_debug("failed: wrong overflow hit\n"); 270 + pr_debug("failed: wrong overflow (%d) hit, expected 3\n", overflows); 271 271 272 272 if (overflows_2 != 3) 273 - pr_debug("failed: wrong overflow_2 hit\n"); 273 + pr_debug("failed: wrong overflow_2 (%d) hit, expected 3\n", overflows_2); 274 274 275 275 if (count2 != 3) 276 - pr_debug("failed: wrong count for bp2\n"); 276 + pr_debug("failed: wrong count for bp2 (%lld), expected 3\n", count2); 277 277 278 278 if (count3 != 2) 279 - pr_debug("failed: wrong count for bp3\n"); 279 + pr_debug("failed: wrong count for bp3 (%lld), expected 2\n", count3); 280 280 281 281 return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ? 282 282 TEST_OK : TEST_FAIL;
+192 -87
tools/perf/ui/browsers/hists.c
··· 18 18 #include "../../util/evlist.h" 19 19 #include "../../util/header.h" 20 20 #include "../../util/hist.h" 21 + #include "../../util/machine.h" 21 22 #include "../../util/map.h" 23 + #include "../../util/maps.h" 22 24 #include "../../util/symbol.h" 23 25 #include "../../util/map_symbol.h" 24 26 #include "../../util/branch.h" ··· 393 391 he->init_have_children = true; 394 392 } 395 393 394 + static bool hist_browser__selection_has_children(struct hist_browser *browser) 395 + { 396 + struct hist_entry *he = browser->he_selection; 397 + struct map_symbol *ms = browser->selection; 398 + 399 + if (!he || !ms) 400 + return false; 401 + 402 + if (ms == &he->ms) 403 + return he->has_children; 404 + 405 + return container_of(ms, struct callchain_list, ms)->has_children; 406 + } 407 + 408 + static bool hist_browser__he_selection_unfolded(struct hist_browser *browser) 409 + { 410 + return browser->he_selection ? browser->he_selection->unfolded : false; 411 + } 412 + 413 + static bool hist_browser__selection_unfolded(struct hist_browser *browser) 414 + { 415 + struct hist_entry *he = browser->he_selection; 416 + struct map_symbol *ms = browser->selection; 417 + 418 + if (!he || !ms) 419 + return false; 420 + 421 + if (ms == &he->ms) 422 + return he->unfolded; 423 + 424 + return container_of(ms, struct callchain_list, ms)->unfolded; 425 + } 426 + 427 + static char *hist_browser__selection_sym_name(struct hist_browser *browser, char *bf, size_t size) 428 + { 429 + struct hist_entry *he = browser->he_selection; 430 + struct map_symbol *ms = browser->selection; 431 + struct callchain_list *callchain_entry; 432 + 433 + if (!he || !ms) 434 + return NULL; 435 + 436 + if (ms == &he->ms) { 437 + hist_entry__sym_snprintf(he, bf, size, 0); 438 + return bf + 4; // skip the level, e.g. '[k] ' 439 + } 440 + 441 + callchain_entry = container_of(ms, struct callchain_list, ms); 442 + return callchain_list__sym_name(callchain_entry, bf, size, browser->show_dso); 443 + } 444 + 396 445 static bool hist_browser__toggle_fold(struct hist_browser *browser) 397 446 { 398 447 struct hist_entry *he = browser->he_selection; ··· 677 624 return browser->title ? browser->title(browser, bf, size) : 0; 678 625 } 679 626 680 - int hist_browser__run(struct hist_browser *browser, const char *help, 681 - bool warn_lost_event) 627 + static int hist_browser__handle_hotkey(struct hist_browser *browser, bool warn_lost_event, char *title, int key) 682 628 { 683 - int key; 629 + switch (key) { 630 + case K_TIMER: { 631 + struct hist_browser_timer *hbt = browser->hbt; 632 + u64 nr_entries; 633 + 634 + WARN_ON_ONCE(!hbt); 635 + 636 + if (hbt) 637 + hbt->timer(hbt->arg); 638 + 639 + if (hist_browser__has_filter(browser) || symbol_conf.report_hierarchy) 640 + hist_browser__update_nr_entries(browser); 641 + 642 + nr_entries = hist_browser__nr_entries(browser); 643 + ui_browser__update_nr_entries(&browser->b, nr_entries); 644 + 645 + if (warn_lost_event && 646 + (browser->hists->stats.nr_lost_warned != 647 + browser->hists->stats.nr_events[PERF_RECORD_LOST])) { 648 + browser->hists->stats.nr_lost_warned = 649 + browser->hists->stats.nr_events[PERF_RECORD_LOST]; 650 + ui_browser__warn_lost_events(&browser->b); 651 + } 652 + 653 + hist_browser__title(browser, title, sizeof(title)); 654 + ui_browser__show_title(&browser->b, title); 655 + break; 656 + } 657 + case 'D': { /* Debug */ 658 + struct hist_entry *h = rb_entry(browser->b.top, struct hist_entry, rb_node); 659 + static int seq; 660 + 661 + ui_helpline__pop(); 662 + ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", 663 + seq++, browser->b.nr_entries, browser->hists->nr_entries, 664 + browser->b.extra_title_lines, browser->b.rows, 665 + browser->b.index, browser->b.top_idx, h->row_offset, h->nr_rows); 666 + } 667 + break; 668 + case 'C': 669 + /* Collapse the whole world. */ 670 + hist_browser__set_folding(browser, false); 671 + break; 672 + case 'c': 673 + /* Collapse the selected entry. */ 674 + hist_browser__set_folding_selected(browser, false); 675 + break; 676 + case 'E': 677 + /* Expand the whole world. */ 678 + hist_browser__set_folding(browser, true); 679 + break; 680 + case 'e': 681 + /* Expand the selected entry. */ 682 + hist_browser__set_folding_selected(browser, !hist_browser__he_selection_unfolded(browser)); 683 + break; 684 + case 'H': 685 + browser->show_headers = !browser->show_headers; 686 + hist_browser__update_rows(browser); 687 + break; 688 + case '+': 689 + if (hist_browser__toggle_fold(browser)) 690 + break; 691 + /* fall thru */ 692 + default: 693 + return -1; 694 + } 695 + 696 + return 0; 697 + } 698 + 699 + int hist_browser__run(struct hist_browser *browser, const char *help, 700 + bool warn_lost_event, int key) 701 + { 684 702 char title[160]; 685 703 struct hist_browser_timer *hbt = browser->hbt; 686 704 int delay_secs = hbt ? hbt->refresh : 0; ··· 764 640 if (ui_browser__show(&browser->b, title, "%s", help) < 0) 765 641 return -1; 766 642 643 + if (key && hist_browser__handle_hotkey(browser, warn_lost_event, title, key)) 644 + goto out; 645 + 767 646 while (1) { 768 647 key = ui_browser__run(&browser->b, delay_secs); 769 648 770 - switch (key) { 771 - case K_TIMER: { 772 - u64 nr_entries; 773 - 774 - WARN_ON_ONCE(!hbt); 775 - 776 - if (hbt) 777 - hbt->timer(hbt->arg); 778 - 779 - if (hist_browser__has_filter(browser) || 780 - symbol_conf.report_hierarchy) 781 - hist_browser__update_nr_entries(browser); 782 - 783 - nr_entries = hist_browser__nr_entries(browser); 784 - ui_browser__update_nr_entries(&browser->b, nr_entries); 785 - 786 - if (warn_lost_event && 787 - (browser->hists->stats.nr_lost_warned != 788 - browser->hists->stats.nr_events[PERF_RECORD_LOST])) { 789 - browser->hists->stats.nr_lost_warned = 790 - browser->hists->stats.nr_events[PERF_RECORD_LOST]; 791 - ui_browser__warn_lost_events(&browser->b); 792 - } 793 - 794 - hist_browser__title(browser, title, sizeof(title)); 795 - ui_browser__show_title(&browser->b, title); 796 - continue; 797 - } 798 - case 'D': { /* Debug */ 799 - static int seq; 800 - struct hist_entry *h = rb_entry(browser->b.top, 801 - struct hist_entry, rb_node); 802 - ui_helpline__pop(); 803 - ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", 804 - seq++, browser->b.nr_entries, 805 - browser->hists->nr_entries, 806 - browser->b.extra_title_lines, 807 - browser->b.rows, 808 - browser->b.index, 809 - browser->b.top_idx, 810 - h->row_offset, h->nr_rows); 811 - } 649 + if (hist_browser__handle_hotkey(browser, warn_lost_event, title, key)) 812 650 break; 813 - case 'C': 814 - /* Collapse the whole world. */ 815 - hist_browser__set_folding(browser, false); 816 - break; 817 - case 'c': 818 - /* Collapse the selected entry. */ 819 - hist_browser__set_folding_selected(browser, false); 820 - break; 821 - case 'E': 822 - /* Expand the whole world. */ 823 - hist_browser__set_folding(browser, true); 824 - break; 825 - case 'e': 826 - /* Expand the selected entry. */ 827 - hist_browser__set_folding_selected(browser, true); 828 - break; 829 - case 'H': 830 - browser->show_headers = !browser->show_headers; 831 - hist_browser__update_rows(browser); 832 - break; 833 - case K_ENTER: 834 - if (hist_browser__toggle_fold(browser)) 835 - break; 836 - /* fall thru */ 837 - default: 838 - goto out; 839 - } 840 651 } 841 652 out: 842 653 ui_browser__hide(&browser->b); ··· 2398 2339 closedir(pwd_dir); 2399 2340 2400 2341 if (nr_options) { 2401 - choice = ui__popup_menu(nr_options, options); 2342 + choice = ui__popup_menu(nr_options, options, NULL); 2402 2343 if (choice < nr_options && choice >= 0) { 2403 2344 tmp = strdup(abs_path[choice]); 2404 2345 if (tmp) { ··· 2470 2411 struct popup_action *act, char **optstr, 2471 2412 struct map_symbol *ms) 2472 2413 { 2473 - if (ms->sym == NULL || ms->map->dso->annotate_warned) 2414 + if (ms->sym == NULL || ms->map->dso->annotate_warned || 2415 + symbol__annotation(ms->sym)->src == NULL) 2474 2416 return 0; 2475 2417 2476 2418 if (asprintf(optstr, "Annotate %s", ms->sym->name) < 0) ··· 2544 2484 return 1; 2545 2485 } 2546 2486 2547 - static int 2548 - do_zoom_dso(struct hist_browser *browser, struct popup_action *act) 2487 + static int hists_browser__zoom_map(struct hist_browser *browser, struct map *map) 2549 2488 { 2550 - struct map *map = act->ms.map; 2551 - 2552 2489 if (!hists__has(browser->hists, dso) || map == NULL) 2553 2490 return 0; 2554 2491 ··· 2568 2511 } 2569 2512 2570 2513 static int 2514 + do_zoom_dso(struct hist_browser *browser, struct popup_action *act) 2515 + { 2516 + return hists_browser__zoom_map(browser, act->ms.map); 2517 + } 2518 + 2519 + static int 2571 2520 add_dso_opt(struct hist_browser *browser, struct popup_action *act, 2572 2521 char **optstr, struct map *map) 2573 2522 { 2574 2523 if (!hists__has(browser->hists, dso) || map == NULL) 2575 2524 return 0; 2576 2525 2577 - if (asprintf(optstr, "Zoom %s %s DSO", 2526 + if (asprintf(optstr, "Zoom %s %s DSO (use the 'k' hotkey to zoom directly into the kernel)", 2578 2527 browser->hists->dso_filter ? "out of" : "into", 2579 2528 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name) < 0) 2580 2529 return 0; 2581 2530 2582 2531 act->ms.map = map; 2583 2532 act->fn = do_zoom_dso; 2533 + return 1; 2534 + } 2535 + 2536 + static int do_toggle_callchain(struct hist_browser *browser, struct popup_action *act __maybe_unused) 2537 + { 2538 + hist_browser__toggle_fold(browser); 2539 + return 0; 2540 + } 2541 + 2542 + static int add_callchain_toggle_opt(struct hist_browser *browser, struct popup_action *act, char **optstr) 2543 + { 2544 + char sym_name[512]; 2545 + 2546 + if (!hist_browser__selection_has_children(browser)) 2547 + return 0; 2548 + 2549 + if (asprintf(optstr, "%s [%s] callchain (one level, same as '+' hotkey, use 'e'/'c' for the whole main level entry)", 2550 + hist_browser__selection_unfolded(browser) ? "Collapse" : "Expand", 2551 + hist_browser__selection_sym_name(browser, sym_name, sizeof(sym_name))) < 0) 2552 + return 0; 2553 + 2554 + act->fn = do_toggle_callchain; 2584 2555 return 1; 2585 2556 } 2586 2557 ··· 2943 2858 "For symbolic views (--sort has sym):\n\n" \ 2944 2859 "ENTER Zoom into DSO/Threads & Annotate current symbol\n" \ 2945 2860 "ESC Zoom out\n" \ 2861 + "+ Expand/Collapse one callchain level\n" \ 2946 2862 "a Annotate current symbol\n" \ 2947 2863 "C Collapse all callchains\n" \ 2948 2864 "d Zoom into current DSO\n" \ 2865 + "e Expand/Collapse main entry callchains\n" \ 2949 2866 "E Expand all callchains\n" \ 2950 2867 "F Toggle percentage of filtered entries\n" \ 2951 2868 "H Display column headers\n" \ 2869 + "k Zoom into the kernel map\n" \ 2952 2870 "L Change percent limit\n" \ 2953 2871 "m Display context menu\n" \ 2954 2872 "S Zoom into current Processor Socket\n" \ ··· 3002 2914 while (1) { 3003 2915 struct thread *thread = NULL; 3004 2916 struct map *map = NULL; 3005 - int choice = 0; 2917 + int choice; 3006 2918 int socked_id = -1; 3007 2919 3008 - nr_options = 0; 3009 - 3010 - key = hist_browser__run(browser, helpline, 3011 - warn_lost_event); 2920 + key = 0; // reset key 2921 + do_hotkey: // key came straight from options ui__popup_menu() 2922 + choice = nr_options = 0; 2923 + key = hist_browser__run(browser, helpline, warn_lost_event, key); 3012 2924 3013 2925 if (browser->he_selection != NULL) { 3014 2926 thread = hist_browser__selected_thread(browser); ··· 3038 2950 browser->selection->map->dso->annotate_warned) 3039 2951 continue; 3040 2952 2953 + if (symbol__annotation(browser->selection->sym)->src == NULL) { 2954 + ui_browser__warning(&browser->b, delay_secs * 2, 2955 + "No samples for the \"%s\" symbol.\n\n" 2956 + "Probably appeared just in a callchain", 2957 + browser->selection->sym->name); 2958 + continue; 2959 + } 2960 + 3041 2961 actions->ms.map = browser->selection->map; 3042 2962 actions->ms.sym = browser->selection->sym; 3043 2963 do_annotate(browser, actions); ··· 3056 2960 case 'd': 3057 2961 actions->ms.map = map; 3058 2962 do_zoom_dso(browser, actions); 2963 + continue; 2964 + case 'k': 2965 + if (browser->selection != NULL) 2966 + hists_browser__zoom_map(browser, browser->selection->maps->machine->vmlinux_map); 3059 2967 continue; 3060 2968 case 'V': 3061 2969 verbose = (verbose + 1) % 4; ··· 3162 3062 3163 3063 continue; 3164 3064 } 3065 + actions->ms.map = map; 3165 3066 top = pstack__peek(browser->pstack); 3166 3067 if (top == &browser->hists->dso_filter) { 3167 3068 /* ··· 3236 3135 &options[nr_options], thread); 3237 3136 nr_options += add_dso_opt(browser, &actions[nr_options], 3238 3137 &options[nr_options], map); 3138 + nr_options += add_callchain_toggle_opt(browser, &actions[nr_options], &options[nr_options]); 3239 3139 nr_options += add_map_opt(browser, &actions[nr_options], 3240 3140 &options[nr_options], 3241 3141 browser->selection ? ··· 3295 3193 do { 3296 3194 struct popup_action *act; 3297 3195 3298 - choice = ui__popup_menu(nr_options, options); 3299 - if (choice == -1 || choice >= nr_options) 3196 + choice = ui__popup_menu(nr_options, options, &key); 3197 + if (choice == -1) 3300 3198 break; 3199 + 3200 + if (choice == nr_options) 3201 + goto do_hotkey; 3301 3202 3302 3203 act = &actions[choice]; 3303 3204 key = act->fn(browser, act); ··· 3597 3492 memset(&action, 0, sizeof(action)); 3598 3493 3599 3494 while (1) { 3600 - key = hist_browser__run(browser, "? - help", true); 3495 + key = hist_browser__run(browser, "? - help", true, 0); 3601 3496 3602 3497 switch (key) { 3603 3498 case 'q':
+1 -1
tools/perf/ui/browsers/hists.h
··· 34 34 struct hist_browser *hist_browser__new(struct hists *hists); 35 35 void hist_browser__delete(struct hist_browser *browser); 36 36 int hist_browser__run(struct hist_browser *browser, const char *help, 37 - bool warn_lost_event); 37 + bool warn_lost_event, int key); 38 38 void hist_browser__init(struct hist_browser *browser, 39 39 struct hists *hists); 40 40 #endif /* _PERF_UI_BROWSER_HISTS_H_ */
+1 -1
tools/perf/ui/browsers/res_sample.c
··· 56 56 return -1; 57 57 } 58 58 } 59 - choice = ui__popup_menu(num_res, names); 59 + choice = ui__popup_menu(num_res, names, NULL); 60 60 for (i = 0; i < num_res; i++) 61 61 zfree(&names[i]); 62 62 free(names);
+1 -1
tools/perf/ui/browsers/scripts.c
··· 126 126 SCRIPT_FULLPATH_LEN); 127 127 if (num < 0) 128 128 num = 0; 129 - choice = ui__popup_menu(num + max_std, (char * const *)names); 129 + choice = ui__popup_menu(num + max_std, (char * const *)names, NULL); 130 130 if (choice < 0) { 131 131 ret = -1; 132 132 goto out;
+8 -4
tools/perf/ui/tui/util.c
··· 23 23 ui_browser__write_nstring(browser, *arg, browser->width); 24 24 } 25 25 26 - static int popup_menu__run(struct ui_browser *menu) 26 + static int popup_menu__run(struct ui_browser *menu, int *keyp) 27 27 { 28 28 int key; 29 29 ··· 45 45 key = -1; 46 46 break; 47 47 default: 48 + if (keyp) { 49 + *keyp = key; 50 + key = menu->nr_entries; 51 + break; 52 + } 48 53 continue; 49 54 } 50 55 ··· 60 55 return key; 61 56 } 62 57 63 - int ui__popup_menu(int argc, char * const argv[]) 58 + int ui__popup_menu(int argc, char * const argv[], int *keyp) 64 59 { 65 60 struct ui_browser menu = { 66 61 .entries = (void *)argv, ··· 69 64 .write = ui_browser__argv_write, 70 65 .nr_entries = argc, 71 66 }; 72 - 73 - return popup_menu__run(&menu); 67 + return popup_menu__run(&menu, keyp); 74 68 } 75 69 76 70 int ui_browser__input_window(const char *title, const char *text, char *input,
+1 -1
tools/perf/ui/util.h
··· 5 5 #include <stdarg.h> 6 6 7 7 int ui__getch(int delay_secs); 8 - int ui__popup_menu(int argc, char * const argv[]); 8 + int ui__popup_menu(int argc, char * const argv[], int *keyp); 9 9 int ui__help_window(const char *text); 10 10 int ui__dialog_yesno(const char *msg); 11 11 void __ui__info_window(const char *title, const char *text, const char *exit_msg);
+2 -2
tools/perf/util/hist.h
··· 339 339 list_for_each_entry_safe(format, tmp, &(_list)->sorts, sort_list) 340 340 341 341 #define hists__for_each_format(hists, format) \ 342 - perf_hpp_list__for_each_format((hists)->hpp_list, fmt) 342 + perf_hpp_list__for_each_format((hists)->hpp_list, format) 343 343 344 344 #define hists__for_each_sort_list(hists, format) \ 345 - perf_hpp_list__for_each_sort_list((hists)->hpp_list, fmt) 345 + perf_hpp_list__for_each_sort_list((hists)->hpp_list, format) 346 346 347 347 extern struct perf_hpp_fmt perf_hpp__format[]; 348 348
+34 -6
tools/perf/util/mmap.c
··· 23 23 #include "mmap.h" 24 24 #include "../perf.h" 25 25 #include <internal/lib.h> /* page_size */ 26 + #include <linux/bitmap.h> 27 + 28 + #define MASK_SIZE 1023 29 + void mmap_cpu_mask__scnprintf(struct mmap_cpu_mask *mask, const char *tag) 30 + { 31 + char buf[MASK_SIZE + 1]; 32 + size_t len; 33 + 34 + len = bitmap_scnprintf(mask->bits, mask->nbits, buf, MASK_SIZE); 35 + buf[len] = '\0'; 36 + pr_debug("%p: %s mask[%zd]: %s\n", mask, tag, mask->nbits, buf); 37 + } 26 38 27 39 size_t mmap__mmap_len(struct mmap *map) 28 40 { ··· 219 207 220 208 void mmap__munmap(struct mmap *map) 221 209 { 210 + bitmap_free(map->affinity_mask.bits); 211 + 222 212 perf_mmap__aio_munmap(map); 223 213 if (map->data != NULL) { 224 214 munmap(map->data, mmap__mmap_len(map)); ··· 229 215 auxtrace_mmap__munmap(&map->auxtrace_mmap); 230 216 } 231 217 232 - static void build_node_mask(int node, cpu_set_t *mask) 218 + static void build_node_mask(int node, struct mmap_cpu_mask *mask) 233 219 { 234 220 int c, cpu, nr_cpus; 235 221 const struct perf_cpu_map *cpu_map = NULL; ··· 242 228 for (c = 0; c < nr_cpus; c++) { 243 229 cpu = cpu_map->map[c]; /* map c index to online cpu index */ 244 230 if (cpu__get_node(cpu) == node) 245 - CPU_SET(cpu, mask); 231 + set_bit(cpu, mask->bits); 246 232 } 247 233 } 248 234 249 - static void perf_mmap__setup_affinity_mask(struct mmap *map, struct mmap_params *mp) 235 + static int perf_mmap__setup_affinity_mask(struct mmap *map, struct mmap_params *mp) 250 236 { 251 - CPU_ZERO(&map->affinity_mask); 237 + map->affinity_mask.nbits = cpu__max_cpu(); 238 + map->affinity_mask.bits = bitmap_alloc(map->affinity_mask.nbits); 239 + if (!map->affinity_mask.bits) 240 + return -1; 241 + 252 242 if (mp->affinity == PERF_AFFINITY_NODE && cpu__max_node() > 1) 253 243 build_node_mask(cpu__get_node(map->core.cpu), &map->affinity_mask); 254 244 else if (mp->affinity == PERF_AFFINITY_CPU) 255 - CPU_SET(map->core.cpu, &map->affinity_mask); 245 + set_bit(map->core.cpu, map->affinity_mask.bits); 246 + 247 + return 0; 256 248 } 257 249 258 250 int mmap__mmap(struct mmap *map, struct mmap_params *mp, int fd, int cpu) ··· 269 249 return -1; 270 250 } 271 251 272 - perf_mmap__setup_affinity_mask(map, mp); 252 + if (mp->affinity != PERF_AFFINITY_SYS && 253 + perf_mmap__setup_affinity_mask(map, mp)) { 254 + pr_debug2("failed to alloc mmap affinity mask, error %d\n", 255 + errno); 256 + return -1; 257 + } 258 + 259 + if (verbose == 2) 260 + mmap_cpu_mask__scnprintf(&map->affinity_mask, "mmap"); 273 261 274 262 map->core.flush = mp->flush; 275 263
+12 -1
tools/perf/util/mmap.h
··· 15 15 #include "event.h" 16 16 17 17 struct aiocb; 18 + 19 + struct mmap_cpu_mask { 20 + unsigned long *bits; 21 + size_t nbits; 22 + }; 23 + 24 + #define MMAP_CPU_MASK_BYTES(m) \ 25 + (BITS_TO_LONGS(((struct mmap_cpu_mask *)m)->nbits) * sizeof(unsigned long)) 26 + 18 27 /** 19 28 * struct mmap - perf's ring buffer mmap details 20 29 * ··· 40 31 int nr_cblocks; 41 32 } aio; 42 33 #endif 43 - cpu_set_t affinity_mask; 34 + struct mmap_cpu_mask affinity_mask; 44 35 void *data; 45 36 int comp_level; 46 37 }; ··· 60 51 int push(struct mmap *map, void *to, void *buf, size_t size)); 61 52 62 53 size_t mmap__mmap_len(struct mmap *map); 54 + 55 + void mmap_cpu_mask__scnprintf(struct mmap_cpu_mask *mask, const char *tag); 63 56 64 57 #endif /*__PERF_MMAP_H */
+1 -2
tools/perf/util/sort.c
··· 324 324 return ret; 325 325 } 326 326 327 - static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, 328 - size_t size, unsigned int width) 327 + int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width) 329 328 { 330 329 return _hist_entry__sym_snprintf(&he->ms, he->ip, 331 330 he->level, bf, size, width);
+2
tools/perf/util/sort.h
··· 164 164 return he->callchain_size != 0; 165 165 } 166 166 167 + int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width); 168 + 167 169 static inline bool hist_entry__has_pairs(struct hist_entry *he) 168 170 { 169 171 return !list_empty(&he->pairs.node);
+3
tools/perf/util/symbol-elf.c
··· 920 920 if (curr_map == NULL) 921 921 return -1; 922 922 923 + if (curr_dso->kernel) 924 + map__kmap(curr_map)->kmaps = kmaps; 925 + 923 926 if (adjust_kernel_syms) { 924 927 curr_map->start = shdr->sh_addr + ref_reloc(kmap); 925 928 curr_map->end = curr_map->start + shdr->sh_size;