Pull more perf updates from Thomas Gleixner: "A rather large set of perf updates: Kernel: - Fix various initialization issues - Prevent creating [ku]probes for not CAP_SYS_ADMIN users Tooling: - Show only failing syscalls with 'perf trace --failure' (Arnaldo Carvalho de Melo) e.g: See what 'openat' syscalls are failing: # perf trace --failure -e openat 762.323 ( 0.007 ms): VideoCapture/4566 openat(dfd: CWD, filename: /dev/video2) = -1 ENOENT No such file or directory <SNIP N /dev/videoN open attempts... sigh, where is that improvised camera lid?!? > 790.228 ( 0.008 ms): VideoCapture/4566 openat(dfd: CWD, filename: /dev/video63) = -1 ENOENT No such file or directory ^C# - Show information about the event (freq, nr_samples, total period/nr_events) in the annotate --tui and --stdio2 'perf annotate' output, similar to the first line in the 'perf report --tui', but just for the samples for a the annotated symbol (Arnaldo Carvalho de Melo) - Introduce 'perf version --build-options' to show what features were linked, aliased as well as a shorter 'perf -vv' (Jin Yao) - Add a "dso_size" sort order (Kim Phillips) - Remove redundant ')' in the tracepoint output in 'perf trace' (Changbin Du) - Synchronize x86's cpufeatures.h, no effect on toolss (Arnaldo Carvalho de Melo) - Show group details on the title line in the annotate browser and 'perf annotate --stdio2' output, so that the per-event columns can have headers (Arnaldo Carvalho de Melo) - Fixup vertical line separating metrics from instructions and cleaning unused lines at the bottom, both in the annotate TUI browser (Arnaldo Carvalho de Melo) - Remove duplicated 'samples' in lost samples warning in 'perf report' (Arnaldo Carvalho de Melo) - Synchronize i915_drm.h, silencing the perf build process, automagically adding support for the new DRM_I915_QUERY ioctl (Arnaldo Carvalho de Melo) - Make auxtrace_queues__add_buffer() allocate struct buffer, from a patchkit already applied (Adrian Hunter) - Fix the --stdio2/TUI annotate output to include group details, be it for a recorded '{a,b,f}' explicit event group or when forcing group display using 'perf report --group' for a set of events not recorded as a group (Arnaldo Carvalho de Melo) - Fix display artifacts in the ui browser (base class for the annotate and main report/top TUI browser) related to the extra title lines work (Arnaldo Carvalho de Melo) - perf auxtrace refactorings, leftovers from a previously partially processed patchset (Adrian Hunter) - Fix the builtin clang build (Sandipan Das, Arnaldo Carvalho de Melo) - Synchronize i915_drm.h, silencing a perf build warning and in the process automagically adding support for a new ioctl command (Arnaldo Carvalho de Melo) - Fix a strncpy issue in uprobe tracing" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (36 commits) perf/core: Need CAP_SYS_ADMIN to create k/uprobe with perf_event_open() tracing/uprobe_event: Fix strncpy corner case perf/core: Fix perf_uprobe_init() perf/core: Fix perf_kprobe_init() perf/core: Fix use-after-free in uprobe_perf_close() perf tests clang: Fix function name for clang IR test perf clang: Add support for recent clang versions perf tools: Fix perf builds with clang support perf tools: No need to include namespaces.h in util.h perf hists browser: Remove leftover from row returned from refresh perf hists browser: Show extra_title_lines in the 'D' debug hotkey perf auxtrace: Make auxtrace_queues__add_buffer() do CPU filtering tools headers uapi: Synchronize i915_drm.h perf report: Remove duplicated 'samples' in lost samples warning perf ui browser: Fixup cleaning unused lines at the bottom perf annotate browser: Fixup vertical line separating metrics from instructions perf annotate: Show group details on the title line perf auxtrace: Make auxtrace_queues__add_buffer() allocate struct buffer perf/x86/intel: Move regs->flags EXACT bit init perf trace: Remove redundant ')' ...
Unified · Split
| @@ -1153,7 +1153,6 @@ static void setup_pebs_sample_data(struct perf_event *event, · 1152 unmodified lines | |||
| 1153 | if (pebs == NULL) | 1153 | if (pebs == NULL) |
| 1154 | return; | 1154 | return; |
| 1155 | 1155 | ||
| 1156 | regs->flags &= ~PERF_EFLAGS_EXACT; | ||
| 1157 | sample_type = event->attr.sample_type; | 1156 | sample_type = event->attr.sample_type; |
| 1158 | dsrc = sample_type & PERF_SAMPLE_DATA_SRC; | 1157 | dsrc = sample_type & PERF_SAMPLE_DATA_SRC; |
| 1159 | 1158 | ||
| @@ -1197,7 +1196,13 @@ static void setup_pebs_sample_data(struct perf_event *event, · 37 unmodified lines | |||
| 1197 | * and PMI. | 1196 | * and PMI. |
| 1198 | */ | 1197 | */ |
| 1199 | *regs = *iregs; | 1198 | *regs = *iregs; |
| 1200 | regs->flags = pebs->flags; | 1199 | |
| 1200 | /* | ||
| 1201 | * Initialize regs_>flags from PEBS, | ||
| 1202 | * Clear exact bit (which uses x86 EFLAGS Reserved bit 3), | ||
| 1203 | * i.e., do not rely on it being zero: | ||
| 1204 | */ | ||
| 1205 | regs->flags = pebs->flags & ~PERF_EFLAGS_EXACT; | ||
| 1201 | 1206 | ||
| 1202 | if (sample_type & PERF_SAMPLE_REGS_INTR) { | 1207 | if (sample_type & PERF_SAMPLE_REGS_INTR) { |
| 1203 | regs->ax = pebs->ax; | 1208 | regs->ax = pebs->ax; |
| @@ -1217,10 +1222,6 @@ static void setup_pebs_sample_data(struct perf_event *event, · 13 unmodified lines | |||
| 1217 | regs->sp = pebs->sp; | 1222 | regs->sp = pebs->sp; |
| 1218 | } | 1223 | } |
| 1219 | 1224 | ||
| 1220 | /* | ||
| 1221 | * Preserve PERF_EFLAGS_VM from set_linear_ip(). | ||
| 1222 | */ | ||
| 1223 | regs->flags = pebs->flags | (regs->flags & PERF_EFLAGS_VM); | ||
| 1224 | #ifndef CONFIG_X86_32 | 1225 | #ifndef CONFIG_X86_32 |
| 1225 | regs->r8 = pebs->r8; | 1226 | regs->r8 = pebs->r8; |
| 1226 | regs->r9 = pebs->r9; | 1227 | regs->r9 = pebs->r9; |
| @@ -1234,20 +1235,33 @@ static void setup_pebs_sample_data(struct perf_event *event, · 7 unmodified lines | |||
| 1234 | } | 1235 | } |
| 1235 | 1236 | ||
| 1236 | if (event->attr.precise_ip > 1) { | 1237 | if (event->attr.precise_ip > 1) { |
| 1237 | /* Haswell and later have the eventing IP, so use it: */ | 1238 | /* |
| 1239 | * Haswell and later processors have an 'eventing IP' | ||
| 1240 | * (real IP) which fixes the off-by-1 skid in hardware. | ||
| 1241 | * Use it when precise_ip >= 2 : | ||
| 1242 | */ | ||
| 1238 | if (x86_pmu.intel_cap.pebs_format >= 2) { | 1243 | if (x86_pmu.intel_cap.pebs_format >= 2) { |
| 1239 | set_linear_ip(regs, pebs->real_ip); | 1244 | set_linear_ip(regs, pebs->real_ip); |
| 1240 | regs->flags |= PERF_EFLAGS_EXACT; | 1245 | regs->flags |= PERF_EFLAGS_EXACT; |
| 1241 | } else { | 1246 | } else { |
| 1242 | /* Otherwise use PEBS off-by-1 IP: */ | 1247 | /* Otherwise, use PEBS off-by-1 IP: */ |
| 1243 | set_linear_ip(regs, pebs->ip); | 1248 | set_linear_ip(regs, pebs->ip); |
| 1244 | 1249 | ||
| 1245 | /* ... and try to fix it up using the LBR entries: */ | 1250 | /* |
| 1251 | * With precise_ip >= 2, try to fix up the off-by-1 IP | ||
| 1252 | * using the LBR. If successful, the fixup function | ||
| 1253 | * corrects regs->ip and calls set_linear_ip() on regs: | ||
| 1254 | */ | ||
| 1246 | if (intel_pmu_pebs_fixup_ip(regs)) | 1255 | if (intel_pmu_pebs_fixup_ip(regs)) |
| 1247 | regs->flags |= PERF_EFLAGS_EXACT; | 1256 | regs->flags |= PERF_EFLAGS_EXACT; |
| 1248 | } | 1257 | } |
| 1249 | } else | 1258 | } else { |
| 1259 | /* | ||
| 1260 | * When precise_ip == 1, return the PEBS off-by-1 IP, | ||
| 1261 | * no fixup attempted: | ||
| 1262 | */ | ||
| 1250 | set_linear_ip(regs, pebs->ip); | 1263 | set_linear_ip(regs, pebs->ip); |
| 1264 | } | ||
| 1251 | 1265 | ||
| 1252 | 1266 | ||
| 1253 | if ((sample_type & (PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR)) && | 1267 | if ((sample_type & (PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR)) && |
| @@ -4447,6 +4447,9 @@ static void _free_event(struct perf_event *event) · 4446 unmodified lines | |||
| 4447 | if (event->ctx) | 4447 | if (event->ctx) |
| 4448 | put_ctx(event->ctx); | 4448 | put_ctx(event->ctx); |
| 4449 | 4449 | ||
| 4450 | if (event->hw.target) | ||
| 4451 | put_task_struct(event->hw.target); | ||
| 4452 | |||
| 4450 | exclusive_event_destroy(event); | 4453 | exclusive_event_destroy(event); |
| 4451 | module_put(event->pmu->module); | 4454 | module_put(event->pmu->module); |
| 4452 | 4455 | ||
| @@ -8397,6 +8400,10 @@ static int perf_kprobe_event_init(struct perf_event *event) · 3944 unmodified lines | |||
| 8397 | 8400 | ||
| 8398 | if (event->attr.type != perf_kprobe.type) | 8401 | if (event->attr.type != perf_kprobe.type) |
| 8399 | return -ENOENT; | 8402 | return -ENOENT; |
| 8403 | |||
| 8404 | if (!capable(CAP_SYS_ADMIN)) | ||
| 8405 | return -EACCES; | ||
| 8406 | |||
| 8400 | /* | 8407 | /* |
| 8401 | * no branch sampling for probe events | 8408 | * no branch sampling for probe events |
| 8402 | */ | 8409 | */ |
| @@ -8434,6 +8441,10 @@ static int perf_uprobe_event_init(struct perf_event *event) · 31 unmodified lines | |||
| 8434 | 8441 | ||
| 8435 | if (event->attr.type != perf_uprobe.type) | 8442 | if (event->attr.type != perf_uprobe.type) |
| 8436 | return -ENOENT; | 8443 | return -ENOENT; |
| 8444 | |||
| 8445 | if (!capable(CAP_SYS_ADMIN)) | ||
| 8446 | return -EACCES; | ||
| 8447 | |||
| 8437 | /* | 8448 | /* |
| 8438 | * no branch sampling for probe events | 8449 | * no branch sampling for probe events |
| 8439 | */ | 8450 | */ |
| @@ -9955,6 +9966,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, · 1515 unmodified lines | |||
| 9955 | * and we cannot use the ctx information because we need the | 9966 | * and we cannot use the ctx information because we need the |
| 9956 | * pmu before we get a ctx. | 9967 | * pmu before we get a ctx. |
| 9957 | */ | 9968 | */ |
| 9969 | get_task_struct(task); | ||
| 9958 | event->hw.target = task; | 9970 | event->hw.target = task; |
| 9959 | } | 9971 | } |
| 9960 | 9972 | ||
| @@ -10070,6 +10082,8 @@ err_ns: · 109 unmodified lines | |||
| 10070 | perf_detach_cgroup(event); | 10082 | perf_detach_cgroup(event); |
| 10071 | if (event->ns) | 10083 | if (event->ns) |
| 10072 | put_pid_ns(event->ns); | 10084 | put_pid_ns(event->ns); |
| 10085 | if (event->hw.target) | ||
| 10086 | put_task_struct(event->hw.target); | ||
| 10073 | kfree(event); | 10087 | kfree(event); |
| 10074 | 10088 | ||
| 10075 | return ERR_PTR(err); | 10089 | return ERR_PTR(err); |
| @@ -252,6 +252,8 @@ int perf_kprobe_init(struct perf_event *p_event, bool is_retprobe) · 251 unmodified lines | |||
| 252 | ret = strncpy_from_user( | 252 | ret = strncpy_from_user( |
| 253 | func, u64_to_user_ptr(p_event->attr.kprobe_func), | 253 | func, u64_to_user_ptr(p_event->attr.kprobe_func), |
| 254 | KSYM_NAME_LEN); | 254 | KSYM_NAME_LEN); |
| 255 | if (ret == KSYM_NAME_LEN) | ||
| 256 | ret = -E2BIG; | ||
| 255 | if (ret < 0) | 257 | if (ret < 0) |
| 256 | goto out; | 258 | goto out; |
| 257 | 259 | ||
| @@ -300,6 +302,8 @@ int perf_uprobe_init(struct perf_event *p_event, bool is_retprobe) · 42 unmodified lines | |||
| 300 | return -ENOMEM; | 302 | return -ENOMEM; |
| 301 | ret = strncpy_from_user( | 303 | ret = strncpy_from_user( |
| 302 | path, u64_to_user_ptr(p_event->attr.uprobe_path), PATH_MAX); | 304 | path, u64_to_user_ptr(p_event->attr.uprobe_path), PATH_MAX); |
| 305 | if (ret == PATH_MAX) | ||
| 306 | return -E2BIG; | ||
| 303 | if (ret < 0) | 307 | if (ret < 0) |
| 304 | goto out; | 308 | goto out; |
| 305 | if (path[0] == '\0') { | 309 | if (path[0] == '\0') { |
| @@ -151,6 +151,8 @@ static void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs, · 150 unmodified lines | |||
| 151 | return; | 151 | return; |
| 152 | 152 | ||
| 153 | ret = strncpy_from_user(dst, src, maxlen); | 153 | ret = strncpy_from_user(dst, src, maxlen); |
| 154 | if (ret == maxlen) | ||
| 155 | dst[--ret] = '\0'; | ||
| 154 | 156 | ||
| 155 | if (ret < 0) { /* Failed to fetch string */ | 157 | if (ret < 0) { /* Failed to fetch string */ |
| 156 | ((u8 *)get_rloc_data(dest))[0] = '\0'; | 158 | ((u8 *)get_rloc_data(dest))[0] = '\0'; |
| @@ -316,6 +316,7 @@ · 315 unmodified lines | |||
| 316 | #define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */ | 316 | #define X86_FEATURE_VPCLMULQDQ (16*32+10) /* Carry-Less Multiplication Double Quadword */ |
| 317 | #define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */ | 317 | #define X86_FEATURE_AVX512_VNNI (16*32+11) /* Vector Neural Network Instructions */ |
| 318 | #define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */ | 318 | #define X86_FEATURE_AVX512_BITALG (16*32+12) /* Support for VPOPCNT[B,W] and VPSHUF-BITQMB instructions */ |
| 319 | #define X86_FEATURE_TME (16*32+13) /* Intel Total Memory Encryption */ | ||
| 319 | #define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */ | 320 | #define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */ |
| 320 | #define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */ | 321 | #define X86_FEATURE_LA57 (16*32+16) /* 5-level page tables */ |
| 321 | #define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */ | 322 | #define X86_FEATURE_RDPID (16*32+22) /* RDPID instruction */ |
| @@ -328,6 +329,7 @@ · 6 unmodified lines | |||
| 328 | /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ | 329 | /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ |
| 329 | #define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ | 330 | #define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ |
| 330 | #define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ | 331 | #define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ |
| 332 | #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ | ||
| 331 | #define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ | 333 | #define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */ |
| 332 | #define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ | 334 | #define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */ |
| 333 | #define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ | 335 | #define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */ |
| @@ -0,0 +1,34 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef _TOOLS_CONFIG_H | ||
| 3 | #define _TOOLS_CONFIG_H | ||
| 4 | |||
| 5 | /* Subset of include/linux/kconfig.h */ | ||
| 6 | |||
| 7 | #define __ARG_PLACEHOLDER_1 0, | ||
| 8 | #define __take_second_arg(__ignored, val, ...) val | ||
| 9 | |||
| 10 | /* | ||
| 11 | * Helper macros to use CONFIG_ options in C/CPP expressions. Note that | ||
| 12 | * these only work with boolean and tristate options. | ||
| 13 | */ | ||
| 14 | |||
| 15 | /* | ||
| 16 | * Getting something that works in C and CPP for an arg that may or may | ||
| 17 | * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1" | ||
| 18 | * we match on the placeholder define, insert the "0," for arg1 and generate | ||
| 19 | * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one). | ||
| 20 | * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when | ||
| 21 | * the last step cherry picks the 2nd arg, we get a zero. | ||
| 22 | */ | ||
| 23 | #define __is_defined(x) ___is_defined(x) | ||
| 24 | #define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val) | ||
| 25 | #define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0) | ||
| 26 | |||
| 27 | /* | ||
| 28 | * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0 | ||
| 29 | * otherwise. For boolean options, this is equivalent to | ||
| 30 | * IS_ENABLED(CONFIG_FOO). | ||
| 31 | */ | ||
| 32 | #define IS_BUILTIN(option) __is_defined(option) | ||
| 33 | |||
| 34 | #endif /* _TOOLS_CONFIG_H */ | ||
| @@ -318,6 +318,7 @@ typedef struct _drm_i915_sarea { · 317 unmodified lines | |||
| 318 | #define DRM_I915_PERF_OPEN 0x36 | 318 | #define DRM_I915_PERF_OPEN 0x36 |
| 319 | #define DRM_I915_PERF_ADD_CONFIG 0x37 | 319 | #define DRM_I915_PERF_ADD_CONFIG 0x37 |
| 320 | #define DRM_I915_PERF_REMOVE_CONFIG 0x38 | 320 | #define DRM_I915_PERF_REMOVE_CONFIG 0x38 |
| 321 | #define DRM_I915_QUERY 0x39 | ||
| 321 | 322 | ||
| 322 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) | 323 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) |
| 323 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) | 324 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) |
| @@ -375,6 +376,7 @@ typedef struct _drm_i915_sarea { · 51 unmodified lines | |||
| 375 | #define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) | 376 | #define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) |
| 376 | #define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) | 377 | #define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) |
| 377 | #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) | 378 | #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) |
| 379 | #define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) | ||
| 378 | 380 | ||
| 379 | /* Allow drivers to submit batchbuffers directly to hardware, relying | 381 | /* Allow drivers to submit batchbuffers directly to hardware, relying |
| 380 | * on the security mechanisms provided by hardware. | 382 | * on the security mechanisms provided by hardware. |
| @@ -1358,7 +1360,9 @@ struct drm_intel_overlay_attrs { · 977 unmodified lines | |||
| 1358 | * active on a given plane. | 1360 | * active on a given plane. |
| 1359 | */ | 1361 | */ |
| 1360 | 1362 | ||
| 1361 | #define I915_SET_COLORKEY_NONE (1<<0) /* disable color key matching */ | 1363 | #define I915_SET_COLORKEY_NONE (1<<0) /* Deprecated. Instead set |
| 1364 | * flags==0 to disable colorkeying. | ||
| 1365 | */ | ||
| 1362 | #define I915_SET_COLORKEY_DESTINATION (1<<1) | 1366 | #define I915_SET_COLORKEY_DESTINATION (1<<1) |
| 1363 | #define I915_SET_COLORKEY_SOURCE (1<<2) | 1367 | #define I915_SET_COLORKEY_SOURCE (1<<2) |
| 1364 | struct drm_intel_sprite_colorkey { | 1368 | struct drm_intel_sprite_colorkey { |
| @@ -1604,15 +1608,115 @@ struct drm_i915_perf_oa_config { · 239 unmodified lines | |||
| 1604 | __u32 n_flex_regs; | 1608 | __u32 n_flex_regs; |
| 1605 | 1609 | ||
| 1606 | /* | 1610 | /* |
| 1607 | * These fields are pointers to tuples of u32 values (register | 1611 | * These fields are pointers to tuples of u32 values (register address, |
| 1608 | * address, value). For example the expected length of the buffer | 1612 | * value). For example the expected length of the buffer pointed by |
| 1609 | * pointed by mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). | 1613 | * mux_regs_ptr is (2 * sizeof(u32) * n_mux_regs). |
| 1610 | */ | 1614 | */ |
| 1611 | __u64 mux_regs_ptr; | 1615 | __u64 mux_regs_ptr; |
| 1612 | __u64 boolean_regs_ptr; | 1616 | __u64 boolean_regs_ptr; |
| 1613 | __u64 flex_regs_ptr; | 1617 | __u64 flex_regs_ptr; |
| 1614 | }; | 1618 | }; |
| 1615 | 1619 | ||
| 1620 | struct drm_i915_query_item { | ||
| 1621 | __u64 query_id; | ||
| 1622 | #define DRM_I915_QUERY_TOPOLOGY_INFO 1 | ||
| 1623 | |||
| 1624 | /* | ||
| 1625 | * When set to zero by userspace, this is filled with the size of the | ||
| 1626 | * data to be written at the data_ptr pointer. The kernel sets this | ||
| 1627 | * value to a negative value to signal an error on a particular query | ||
| 1628 | * item. | ||
| 1629 | */ | ||
| 1630 | __s32 length; | ||
| 1631 | |||
| 1632 | /* | ||
| 1633 | * Unused for now. Must be cleared to zero. | ||
| 1634 | */ | ||
| 1635 | __u32 flags; | ||
| 1636 | |||
| 1637 | /* | ||
| 1638 | * Data will be written at the location pointed by data_ptr when the | ||
| 1639 | * value of length matches the length of the data to be written by the | ||
| 1640 | * kernel. | ||
| 1641 | */ | ||
| 1642 | __u64 data_ptr; | ||
| 1643 | }; | ||
| 1644 | |||
| 1645 | struct drm_i915_query { | ||
| 1646 | __u32 num_items; | ||
| 1647 | |||
| 1648 | /* | ||
| 1649 | * Unused for now. Must be cleared to zero. | ||
| 1650 | */ | ||
| 1651 | __u32 flags; | ||
| 1652 | |||
| 1653 | /* | ||
| 1654 | * This points to an array of num_items drm_i915_query_item structures. | ||
| 1655 | */ | ||
| 1656 | __u64 items_ptr; | ||
| 1657 | }; | ||
| 1658 | |||
| 1659 | /* | ||
| 1660 | * Data written by the kernel with query DRM_I915_QUERY_TOPOLOGY_INFO : | ||
| 1661 | * | ||
| 1662 | * data: contains the 3 pieces of information : | ||
| 1663 | * | ||
| 1664 | * - the slice mask with one bit per slice telling whether a slice is | ||
| 1665 | * available. The availability of slice X can be queried with the following | ||
| 1666 | * formula : | ||
| 1667 | * | ||
| 1668 | * (data[X / 8] >> (X % 8)) & 1 | ||
| 1669 | * | ||
| 1670 | * - the subslice mask for each slice with one bit per subslice telling | ||
| 1671 | * whether a subslice is available. The availability of subslice Y in slice | ||
| 1672 | * X can be queried with the following formula : | ||
| 1673 | * | ||
| 1674 | * (data[subslice_offset + | ||
| 1675 | * X * subslice_stride + | ||
| 1676 | * Y / 8] >> (Y % 8)) & 1 | ||
| 1677 | * | ||
| 1678 | * - the EU mask for each subslice in each slice with one bit per EU telling | ||
| 1679 | * whether an EU is available. The availability of EU Z in subslice Y in | ||
| 1680 | * slice X can be queried with the following formula : | ||
| 1681 | * | ||
| 1682 | * (data[eu_offset + | ||
| 1683 | * (X * max_subslices + Y) * eu_stride + | ||
| 1684 | * Z / 8] >> (Z % 8)) & 1 | ||
| 1685 | */ | ||
| 1686 | struct drm_i915_query_topology_info { | ||
| 1687 | /* | ||
| 1688 | * Unused for now. Must be cleared to zero. | ||
| 1689 | */ | ||
| 1690 | __u16 flags; | ||
| 1691 | |||
| 1692 | __u16 max_slices; | ||
| 1693 | __u16 max_subslices; | ||
| 1694 | __u16 max_eus_per_subslice; | ||
| 1695 | |||
| 1696 | /* | ||
| 1697 | * Offset in data[] at which the subslice masks are stored. | ||
| 1698 | */ | ||
| 1699 | __u16 subslice_offset; | ||
| 1700 | |||
| 1701 | /* | ||
| 1702 | * Stride at which each of the subslice masks for each slice are | ||
| 1703 | * stored. | ||
| 1704 | */ | ||
| 1705 | __u16 subslice_stride; | ||
| 1706 | |||
| 1707 | /* | ||
| 1708 | * Offset in data[] at which the EU masks are stored. | ||
| 1709 | */ | ||
| 1710 | __u16 eu_offset; | ||
| 1711 | |||
| 1712 | /* | ||
| 1713 | * Stride at which each of the EU masks for each subslice are stored. | ||
| 1714 | */ | ||
| 1715 | __u16 eu_stride; | ||
| 1716 | |||
| 1717 | __u8 data[]; | ||
| 1718 | }; | ||
| 1719 | |||
| 1616 | #if defined(__cplusplus) | 1720 | #if defined(__cplusplus) |
| 1617 | } | 1721 | } |
| 1618 | #endif | 1722 | #endif |
| @@ -80,6 +80,7 @@ OPTIONS · 79 unmodified lines | |||
| 80 | - comm: command (name) of the task which can be read via /proc/<pid>/comm | 80 | - comm: command (name) of the task which can be read via /proc/<pid>/comm |
| 81 | - pid: command and tid of the task | 81 | - pid: command and tid of the task |
| 82 | - dso: name of library or module executed at the time of sample | 82 | - dso: name of library or module executed at the time of sample |
| 83 | - dso_size: size of library or module executed at the time of sample | ||
| 83 | - symbol: name of function executed at the time of sample | 84 | - symbol: name of function executed at the time of sample |
| 84 | - symbol_size: size of function executed at the time of sample | 85 | - symbol_size: size of function executed at the time of sample |
| 85 | - parent: name of function matched to the parent regex filter. Unmatched | 86 | - parent: name of function matched to the parent regex filter. Unmatched |
| @@ -117,6 +117,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. · 116 unmodified lines | |||
| 117 | --sched:: | 117 | --sched:: |
| 118 | Accrue thread runtime and provide a summary at the end of the session. | 118 | Accrue thread runtime and provide a summary at the end of the session. |
| 119 | 119 | ||
| 120 | --failure:: | ||
| 121 | Show only syscalls that failed, i.e. that returned < 0. | ||
| 122 | |||
| 120 | -i:: | 123 | -i:: |
| 121 | --input:: | 124 | --input:: |
| 122 | Process events from a given perf data file. | 125 | Process events from a given perf data file. |
| @@ -0,0 +1,24 @@ | |||
| 1 | perf-version(1) | ||
| 2 | =============== | ||
| 3 | |||
| 4 | NAME | ||
| 5 | ---- | ||
| 6 | perf-version - display the version of perf binary | ||
| 7 | |||
| 8 | SYNOPSIS | ||
| 9 | -------- | ||
| 10 | 'perf version' [--build-options] | ||
| 11 | |||
| 12 | DESCRIPTION | ||
| 13 | ----------- | ||
| 14 | With no options given, the 'perf version' prints the perf version | ||
| 15 | on the standard output. | ||
| 16 | |||
| 17 | If the option '--build-options' is given, then the status of | ||
| 18 | compiled-in libraries are printed on the standard output. | ||
| 19 | |||
| 20 | OPTIONS | ||
| 21 | ------- | ||
| 22 | --build-options:: | ||
| 23 | Prints the status of compiled-in libraries on the | ||
| 24 | standard output. | ||
| @@ -346,12 +346,16 @@ else · 345 unmodified lines | |||
| 346 | ifneq ($(feature-dwarf_getlocations), 1) | 346 | ifneq ($(feature-dwarf_getlocations), 1) |
| 347 | msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157); | 347 | msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157); |
| 348 | else | 348 | else |
| 349 | CFLAGS += -DHAVE_DWARF_GETLOCATIONS | 349 | CFLAGS += -DHAVE_DWARF_GETLOCATIONS_SUPPORT |
| 350 | endif # dwarf_getlocations | 350 | endif # dwarf_getlocations |
| 351 | endif # Dwarf support | 351 | endif # Dwarf support |
| 352 | endif # libelf support | 352 | endif # libelf support |
| 353 | endif # NO_LIBELF | 353 | endif # NO_LIBELF |
| 354 | 354 | ||
| 355 | ifeq ($(feature-glibc), 1) | ||
| 356 | CFLAGS += -DHAVE_GLIBC_SUPPORT | ||
| 357 | endif | ||
| 358 | |||
| 355 | ifdef NO_DWARF | 359 | ifdef NO_DWARF |
| 356 | NO_LIBDW_DWARF_UNWIND := 1 | 360 | NO_LIBDW_DWARF_UNWIND := 1 |
| 357 | endif | 361 | endif |
| @@ -635,6 +639,7 @@ else · 277 unmodified lines | |||
| 635 | else | 639 | else |
| 636 | LDFLAGS += $(PERL_EMBED_LDFLAGS) | 640 | LDFLAGS += $(PERL_EMBED_LDFLAGS) |
| 637 | EXTLIBS += $(PERL_EMBED_LIBADD) | 641 | EXTLIBS += $(PERL_EMBED_LIBADD) |
| 642 | CFLAGS += -DHAVE_LIBPERL_SUPPORT | ||
| 638 | $(call detected,CONFIG_LIBPERL) | 643 | $(call detected,CONFIG_LIBPERL) |
| 639 | endif | 644 | endif |
| 640 | endif | 645 | endif |
| @@ -671,6 +676,7 @@ else · 30 unmodified lines | |||
| 671 | LDFLAGS += $(PYTHON_EMBED_LDFLAGS) | 676 | LDFLAGS += $(PYTHON_EMBED_LDFLAGS) |
| 672 | EXTLIBS += $(PYTHON_EMBED_LIBADD) | 677 | EXTLIBS += $(PYTHON_EMBED_LIBADD) |
| 673 | LANG_BINDINGS += $(obj-perf)python/perf.so | 678 | LANG_BINDINGS += $(obj-perf)python/perf.so |
| 679 | CFLAGS += -DHAVE_LIBPYTHON_SUPPORT | ||
| 674 | $(call detected,CONFIG_LIBPYTHON) | 680 | $(call detected,CONFIG_LIBPYTHON) |
| 675 | endif | 681 | endif |
| 676 | endif | 682 | endif |
| @@ -364,7 +364,8 @@ LIBS = -Wl,--whole-archive $(PERFLIBS) $(EXTRA_PERFLIBS) -Wl,--no-whole-archive · 363 unmodified lines | |||
| 364 | 364 | ||
| 365 | ifeq ($(USE_CLANG), 1) | 365 | ifeq ($(USE_CLANG), 1) |
| 366 | CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization | 366 | CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization |
| 367 | LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a)) | 367 | CLANGLIBS_NOEXT_LIST = $(foreach l,$(CLANGLIBS_LIST),$(shell $(LLVM_CONFIG) --libdir)/libclang$(l)) |
| 368 | LIBCLANG = $(foreach l,$(CLANGLIBS_NOEXT_LIST),$(wildcard $(l).a $(l).so)) | ||
| 368 | LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group | 369 | LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group |
| 369 | endif | 370 | endif |
| 370 | 371 | ||
| @@ -112,6 +112,7 @@ struct trace { · 111 unmodified lines | |||
| 112 | bool multiple_threads; | 112 | bool multiple_threads; |
| 113 | bool summary; | 113 | bool summary; |
| 114 | bool summary_only; | 114 | bool summary_only; |
| 115 | bool failure_only; | ||
| 115 | bool show_comm; | 116 | bool show_comm; |
| 116 | bool print_sample; | 117 | bool print_sample; |
| 117 | bool show_tool_stats; | 118 | bool show_tool_stats; |
| @@ -1565,7 +1566,7 @@ static int trace__printf_interrupted_entry(struct trace *trace) · 1447 unmodified lines | |||
| 1565 | struct thread_trace *ttrace; | 1566 | struct thread_trace *ttrace; |
| 1566 | size_t printed; | 1567 | size_t printed; |
| 1567 | 1568 | ||
| 1568 | if (trace->current == NULL) | 1569 | if (trace->failure_only || trace->current == NULL) |
| 1569 | return 0; | 1570 | return 0; |
| 1570 | 1571 | ||
| 1571 | ttrace = thread__priv(trace->current); | 1572 | ttrace = thread__priv(trace->current); |
| @@ -1638,7 +1639,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, · 66 unmodified lines | |||
| 1638 | args, trace, thread); | 1639 | args, trace, thread); |
| 1639 | 1640 | ||
| 1640 | if (sc->is_exit) { | 1641 | if (sc->is_exit) { |
| 1641 | if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) { | 1642 | if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) { |
| 1642 | trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output); | 1643 | trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output); |
| 1643 | fprintf(trace->output, "%-70s)\n", ttrace->entry_str); | 1644 | fprintf(trace->output, "%-70s)\n", ttrace->entry_str); |
| 1644 | } | 1645 | } |
| @@ -1742,7 +1743,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, · 97 unmodified lines | |||
| 1742 | } | 1743 | } |
| 1743 | } | 1744 | } |
| 1744 | 1745 | ||
| 1745 | if (trace->summary_only) | 1746 | if (trace->summary_only || (ret >= 0 && trace->failure_only)) |
| 1746 | goto out; | 1747 | goto out; |
| 1747 | 1748 | ||
| 1748 | trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output); | 1749 | trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output); |
| @@ -1961,7 +1962,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, · 212 unmodified lines | |||
| 1961 | trace->output); | 1962 | trace->output); |
| 1962 | } | 1963 | } |
| 1963 | 1964 | ||
| 1964 | fprintf(trace->output, ")\n"); | 1965 | fprintf(trace->output, "\n"); |
| 1965 | 1966 | ||
| 1966 | if (callchain_ret > 0) | 1967 | if (callchain_ret > 0) |
| 1967 | trace__fprintf_callchain(trace, sample); | 1968 | trace__fprintf_callchain(trace, sample); |
| @@ -3087,6 +3088,8 @@ int cmd_trace(int argc, const char **argv) · 1119 unmodified lines | |||
| 3087 | OPT_INCR('v', "verbose", &verbose, "be more verbose"), | 3088 | OPT_INCR('v', "verbose", &verbose, "be more verbose"), |
| 3088 | OPT_BOOLEAN('T', "time", &trace.full_time, | 3089 | OPT_BOOLEAN('T', "time", &trace.full_time, |
| 3089 | "Show full timestamp, not time relative to first start"), | 3090 | "Show full timestamp, not time relative to first start"), |
| 3091 | OPT_BOOLEAN(0, "failure", &trace.failure_only, | ||
| 3092 | "Show only syscalls that failed"), | ||
| 3090 | OPT_BOOLEAN('s', "summary", &trace.summary_only, | 3093 | OPT_BOOLEAN('s', "summary", &trace.summary_only, |
| 3091 | "Show only syscall summary with statistics"), | 3094 | "Show only syscall summary with statistics"), |
| 3092 | OPT_BOOLEAN('S', "with-summary", &trace.summary, | 3095 | OPT_BOOLEAN('S', "with-summary", &trace.summary, |
| @@ -1,11 +1,91 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | #include "builtin.h" | 2 | #include "builtin.h" |
| 3 | #include "perf.h" | 3 | #include "perf.h" |
| 4 | #include "color.h" | ||
| 4 | #include <linux/compiler.h> | 5 | #include <linux/compiler.h> |
| 6 | #include <tools/config.h> | ||
| 5 | #include <stdio.h> | 7 | #include <stdio.h> |
| 8 | #include <string.h> | ||
| 9 | #include <subcmd/parse-options.h> | ||
| 6 | 10 | ||
| 7 | int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused) | 11 | int version_verbose; |
| 12 | |||
| 13 | struct version { | ||
| 14 | bool build_options; | ||
| 15 | }; | ||
| 16 | |||
| 17 | static struct version version; | ||
| 18 | |||
| 19 | static struct option version_options[] = { | ||
| 20 | OPT_BOOLEAN(0, "build-options", &version.build_options, | ||
| 21 | "display the build options"), | ||
| 22 | }; | ||
| 23 | |||
| 24 | static const char * const version_usage[] = { | ||
| 25 | "perf version [<options>]", | ||
| 26 | NULL | ||
| 27 | }; | ||
| 28 | |||
| 29 | static void on_off_print(const char *status) | ||
| 30 | { | ||
| 31 | printf("[ "); | ||
| 32 | |||
| 33 | if (!strcmp(status, "OFF")) | ||
| 34 | color_fprintf(stdout, PERF_COLOR_RED, "%-3s", status); | ||
| 35 | else | ||
| 36 | color_fprintf(stdout, PERF_COLOR_GREEN, "%-3s", status); | ||
| 37 | |||
| 38 | printf(" ]"); | ||
| 39 | } | ||
| 40 | |||
| 41 | static void status_print(const char *name, const char *macro, | ||
| 42 | const char *status) | ||
| 8 | { | 43 | { |
| 44 | printf("%22s: ", name); | ||
| 45 | on_off_print(status); | ||
| 46 | printf(" # %s\n", macro); | ||
| 47 | } | ||
| 48 | |||
| 49 | #define STATUS(__d, __m) \ | ||
| 50 | do { \ | ||
| 51 | if (IS_BUILTIN(__d)) \ | ||
| 52 | status_print(#__m, #__d, "on"); \ | ||
| 53 | else \ | ||
| 54 | status_print(#__m, #__d, "OFF"); \ | ||
| 55 | } while (0) | ||
| 56 | |||
| 57 | static void library_status(void) | ||
| 58 | { | ||
| 59 | STATUS(HAVE_DWARF_SUPPORT, dwarf); | ||
| 60 | STATUS(HAVE_DWARF_GETLOCATIONS_SUPPORT, dwarf_getlocations); | ||
| 61 | STATUS(HAVE_GLIBC_SUPPORT, glibc); | ||
| 62 | STATUS(HAVE_GTK2_SUPPORT, gtk2); | ||
| 63 | STATUS(HAVE_LIBAUDIT_SUPPORT, libaudit); | ||
| 64 | STATUS(HAVE_LIBBFD_SUPPORT, libbfd); | ||
| 65 | STATUS(HAVE_LIBELF_SUPPORT, libelf); | ||
| 66 | STATUS(HAVE_LIBNUMA_SUPPORT, libnuma); | ||
| 67 | STATUS(HAVE_LIBNUMA_SUPPORT, numa_num_possible_cpus); | ||
| 68 | STATUS(HAVE_LIBPERL_SUPPORT, libperl); | ||
| 69 | STATUS(HAVE_LIBPYTHON_SUPPORT, libpython); | ||
| 70 | STATUS(HAVE_SLANG_SUPPORT, libslang); | ||
| 71 | STATUS(HAVE_LIBCRYPTO_SUPPORT, libcrypto); | ||
| 72 | STATUS(HAVE_LIBUNWIND_SUPPORT, libunwind); | ||
| 73 | STATUS(HAVE_DWARF_SUPPORT, libdw-dwarf-unwind); | ||
| 74 | STATUS(HAVE_ZLIB_SUPPORT, zlib); | ||
| 75 | STATUS(HAVE_LZMA_SUPPORT, lzma); | ||
| 76 | STATUS(HAVE_AUXTRACE_SUPPORT, get_cpuid); | ||
| 77 | STATUS(HAVE_LIBBPF_SUPPORT, bpf); | ||
| 78 | } | ||
| 79 | |||
| 80 | int cmd_version(int argc, const char **argv) | ||
| 81 | { | ||
| 82 | argc = parse_options(argc, argv, version_options, version_usage, | ||
| 83 | PARSE_OPT_STOP_AT_NON_OPTION); | ||
| 84 | |||
| 9 | printf("perf version %s\n", perf_version_string); | 85 | printf("perf version %s\n", perf_version_string); |
| 86 | |||
| 87 | if (version.build_options || version_verbose == 1) | ||
| 88 | library_status(); | ||
| 89 | |||
| 10 | return 0; | 90 | return 0; |
| 11 | } | 91 | } |
| @@ -190,6 +190,12 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) · 189 unmodified lines | |||
| 190 | break; | 190 | break; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | if (!strcmp(cmd, "-vv")) { | ||
| 194 | (*argv)[0] = "version"; | ||
| 195 | version_verbose = 1; | ||
| 196 | break; | ||
| 197 | } | ||
| 198 | |||
| 193 | /* | 199 | /* |
| 194 | * Check remaining flags. | 200 | * Check remaining flags. |
| 195 | */ | 201 | */ |
| @@ -84,6 +84,7 @@ struct record_opts { · 83 unmodified lines | |||
| 84 | struct option; | 84 | struct option; |
| 85 | extern const char * const *record_usage; | 85 | extern const char * const *record_usage; |
| 86 | extern struct option *record_options; | 86 | extern struct option *record_options; |
| 87 | extern int version_verbose; | ||
| 87 | 88 | ||
| 88 | int record__parse_freq(const struct option *opt, const char *str, int unset); | 89 | int record__parse_freq(const struct option *opt, const char *str, int unset); |
| 89 | #endif | 90 | #endif |
| @@ -45,11 +45,16 @@ void ui_browser__set_percent_color(struct ui_browser *browser, · 44 unmodified lines | |||
| 45 | ui_browser__set_color(browser, color); | 45 | ui_browser__set_color(browser, color); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | void ui_browser__gotorc(struct ui_browser *browser, int y, int x) | 48 | void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x) |
| 49 | { | 49 | { |
| 50 | SLsmg_gotorc(browser->y + y, browser->x + x); | 50 | SLsmg_gotorc(browser->y + y, browser->x + x); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | void ui_browser__gotorc(struct ui_browser *browser, int y, int x) | ||
| 54 | { | ||
| 55 | SLsmg_gotorc(browser->y + y + browser->extra_title_lines, browser->x + x); | ||
| 56 | } | ||
| 57 | |||
| 53 | void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg, | 58 | void ui_browser__write_nstring(struct ui_browser *browser __maybe_unused, const char *msg, |
| 54 | unsigned int width) | 59 | unsigned int width) |
| 55 | { | 60 | { |
| @@ -191,6 +196,7 @@ void ui_browser__refresh_dimensions(struct ui_browser *browser) · 135 unmodified lines | |||
| 191 | { | 196 | { |
| 192 | browser->width = SLtt_Screen_Cols - 1; | 197 | browser->width = SLtt_Screen_Cols - 1; |
| 193 | browser->height = browser->rows = SLtt_Screen_Rows - 2; | 198 | browser->height = browser->rows = SLtt_Screen_Rows - 2; |
| 199 | browser->rows -= browser->extra_title_lines; | ||
| 194 | browser->y = 1; | 200 | browser->y = 1; |
| 195 | browser->x = 0; | 201 | browser->x = 0; |
| 196 | } | 202 | } |
| @@ -337,8 +343,8 @@ static int __ui_browser__refresh(struct ui_browser *browser) · 140 unmodified lines | |||
| 337 | else | 343 | else |
| 338 | width += 1; | 344 | width += 1; |
| 339 | 345 | ||
| 340 | SLsmg_fill_region(browser->y + row, browser->x, | 346 | SLsmg_fill_region(browser->y + row + browser->extra_title_lines, browser->x, |
| 341 | browser->height - row, width, ' '); | 347 | browser->rows - row, width, ' '); |
| 342 | 348 | ||
| 343 | return 0; | 349 | return 0; |
| 344 | } | 350 | } |
| @@ -17,6 +17,7 @@ struct ui_browser { · 16 unmodified lines | |||
| 17 | u64 index, top_idx; | 17 | u64 index, top_idx; |
| 18 | void *top, *entries; | 18 | void *top, *entries; |
| 19 | u16 y, x, width, height, rows, columns, horiz_scroll; | 19 | u16 y, x, width, height, rows, columns, horiz_scroll; |
| 20 | u8 extra_title_lines; | ||
| 20 | int current_color; | 21 | int current_color; |
| 21 | void *priv; | 22 | void *priv; |
| 22 | const char *title; | 23 | const char *title; |
| @@ -38,6 +39,7 @@ bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row); · 15 unmodified lines | |||
| 38 | void ui_browser__refresh_dimensions(struct ui_browser *browser); | 39 | void ui_browser__refresh_dimensions(struct ui_browser *browser); |
| 39 | void ui_browser__reset_index(struct ui_browser *browser); | 40 | void ui_browser__reset_index(struct ui_browser *browser); |
| 40 | 41 | ||
| 42 | void ui_browser__gotorc_title(struct ui_browser *browser, int y, int x); | ||
| 41 | void ui_browser__gotorc(struct ui_browser *browser, int y, int x); | 43 | void ui_browser__gotorc(struct ui_browser *browser, int y, int x); |
| 42 | void ui_browser__write_nstring(struct ui_browser *browser, const char *msg, | 44 | void ui_browser__write_nstring(struct ui_browser *browser, const char *msg, |
| 43 | unsigned int width); | 45 | unsigned int width); |
| @@ -218,7 +218,7 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser) · 217 unmodified lines | |||
| 218 | annotate_browser__draw_current_jump(browser); | 218 | annotate_browser__draw_current_jump(browser); |
| 219 | 219 | ||
| 220 | ui_browser__set_color(browser, HE_COLORSET_NORMAL); | 220 | ui_browser__set_color(browser, HE_COLORSET_NORMAL); |
| 221 | __ui_browser__vline(browser, pcnt_width, 0, browser->height - 1); | 221 | __ui_browser__vline(browser, pcnt_width, 0, browser->rows - 1); |
| 222 | return ret; | 222 | return ret; |
| 223 | } | 223 | } |
| 224 | 224 | ||
| @@ -592,21 +592,40 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser, · 367 unmodified lines | |||
| 592 | return __annotate_browser__search_reverse(browser); | 592 | return __annotate_browser__search_reverse(browser); |
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help) | ||
| 596 | { | ||
| 597 | struct map_symbol *ms = browser->priv; | ||
| 598 | struct symbol *sym = ms->sym; | ||
| 599 | char symbol_dso[SYM_TITLE_MAX_SIZE]; | ||
| 600 | |||
| 601 | if (ui_browser__show(browser, title, help) < 0) | ||
| 602 | return -1; | ||
| 603 | |||
| 604 | sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso)); | ||
| 605 | |||
| 606 | ui_browser__gotorc_title(browser, 0, 0); | ||
| 607 | ui_browser__set_color(browser, HE_COLORSET_ROOT); | ||
| 608 | ui_browser__write_nstring(browser, symbol_dso, browser->width + 1); | ||
| 609 | return 0; | ||
| 610 | } | ||
| 611 | |||
| 595 | static int annotate_browser__run(struct annotate_browser *browser, | 612 | static int annotate_browser__run(struct annotate_browser *browser, |
| 596 | struct perf_evsel *evsel, | 613 | struct perf_evsel *evsel, |
| 597 | struct hist_browser_timer *hbt) | 614 | struct hist_browser_timer *hbt) |
| 598 | { | 615 | { |
| 599 | struct rb_node *nd = NULL; | 616 | struct rb_node *nd = NULL; |
| 617 | struct hists *hists = evsel__hists(evsel); | ||
| 600 | struct map_symbol *ms = browser->b.priv; | 618 | struct map_symbol *ms = browser->b.priv; |
| 601 | struct symbol *sym = ms->sym; | 619 | struct symbol *sym = ms->sym; |
| 602 | struct annotation *notes = symbol__annotation(ms->sym); | 620 | struct annotation *notes = symbol__annotation(ms->sym); |
| 603 | const char *help = "Press 'h' for help on key bindings"; | 621 | const char *help = "Press 'h' for help on key bindings"; |
| 604 | int delay_secs = hbt ? hbt->refresh : 0; | 622 | int delay_secs = hbt ? hbt->refresh : 0; |
| 623 | char title[256]; | ||
| 605 | int key; | 624 | int key; |
| 606 | char title[SYM_TITLE_MAX_SIZE]; | ||
| 607 | 625 | ||
| 608 | sym_title(sym, ms->map, title, sizeof(title)); | 626 | annotation__scnprintf_samples_period(notes, title, sizeof(title), evsel); |
| 609 | if (ui_browser__show(&browser->b, title, help) < 0) | 627 | |
| 628 | if (annotate_browser__show(&browser->b, title, help) < 0) | ||
| 610 | return -1; | 629 | return -1; |
| 611 | 630 | ||
| 612 | annotate_browser__calc_percent(browser, evsel); | 631 | annotate_browser__calc_percent(browser, evsel); |
| @@ -637,8 +656,11 @@ static int annotate_browser__run(struct annotate_browser *browser, · 24 unmodified lines | |||
| 637 | if (hbt) | 656 | if (hbt) |
| 638 | hbt->timer(hbt->arg); | 657 | hbt->timer(hbt->arg); |
| 639 | 658 | ||
| 640 | if (delay_secs != 0) | 659 | if (delay_secs != 0) { |
| 641 | symbol__annotate_decay_histogram(sym, evsel->idx); | 660 | symbol__annotate_decay_histogram(sym, evsel->idx); |
| 661 | hists__scnprintf_title(hists, title, sizeof(title)); | ||
| 662 | annotate_browser__show(&browser->b, title, help); | ||
| 663 | } | ||
| 642 | continue; | 664 | continue; |
| 643 | case K_TAB: | 665 | case K_TAB: |
| 644 | if (nd != NULL) { | 666 | if (nd != NULL) { |
| @@ -812,6 +834,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, · 167 unmodified lines | |||
| 812 | .seek = ui_browser__list_head_seek, | 834 | .seek = ui_browser__list_head_seek, |
| 813 | .write = annotate_browser__write, | 835 | .write = annotate_browser__write, |
| 814 | .filter = disasm_line__filter, | 836 | .filter = disasm_line__filter, |
| 837 | .extra_title_lines = 1, /* for hists__scnprintf_title() */ | ||
| 815 | .priv = &ms, | 838 | .priv = &ms, |
| 816 | .use_navkeypressed = true, | 839 | .use_navkeypressed = true, |
| 817 | }, | 840 | }, |
| @@ -32,8 +32,7 @@ · 31 unmodified lines | |||
| 32 | 32 | ||
| 33 | extern void hist_browser__init_hpp(void); | 33 | extern void hist_browser__init_hpp(void); |
| 34 | 34 | ||
| 35 | static int perf_evsel_browser_title(struct hist_browser *browser, | 35 | static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size); |
| 36 | char *bf, size_t size); | ||
| 37 | static void hist_browser__update_nr_entries(struct hist_browser *hb); | 36 | static void hist_browser__update_nr_entries(struct hist_browser *hb); |
| 38 | 37 | ||
| 39 | static struct rb_node *hists__filter_entries(struct rb_node *nd, | 38 | static struct rb_node *hists__filter_entries(struct rb_node *nd, |
| @@ -62,6 +61,15 @@ static int hist_browser__get_folding(struct hist_browser *browser) · 22 unmodified lines | |||
| 62 | return unfolded_rows; | 61 | return unfolded_rows; |
| 63 | } | 62 | } |
| 64 | 63 | ||
| 64 | static void hist_browser__set_title_space(struct hist_browser *hb) | ||
| 65 | { | ||
| 66 | struct ui_browser *browser = &hb->b; | ||
| 67 | struct hists *hists = hb->hists; | ||
| 68 | struct perf_hpp_list *hpp_list = hists->hpp_list; | ||
| 69 | |||
| 70 | browser->extra_title_lines = hb->show_headers ? hpp_list->nr_header_lines : 0; | ||
| 71 | } | ||
| 72 | |||
| 65 | static u32 hist_browser__nr_entries(struct hist_browser *hb) | 73 | static u32 hist_browser__nr_entries(struct hist_browser *hb) |
| 66 | { | 74 | { |
| 67 | u32 nr_entries; | 75 | u32 nr_entries; |
| @@ -82,10 +90,16 @@ static void hist_browser__update_rows(struct hist_browser *hb) · 14 unmodified lines | |||
| 82 | struct ui_browser *browser = &hb->b; | 90 | struct ui_browser *browser = &hb->b; |
| 83 | struct hists *hists = hb->hists; | 91 | struct hists *hists = hb->hists; |
| 84 | struct perf_hpp_list *hpp_list = hists->hpp_list; | 92 | struct perf_hpp_list *hpp_list = hists->hpp_list; |
| 85 | u16 header_offset, index_row; | 93 | u16 index_row; |
| 86 | 94 | ||
| 87 | header_offset = hb->show_headers ? hpp_list->nr_header_lines : 0; | 95 | if (!hb->show_headers) { |
| 88 | browser->rows = browser->height - header_offset; | 96 | browser->rows += browser->extra_title_lines; |
| 97 | browser->extra_title_lines = 0; | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | |||
| 101 | browser->extra_title_lines = hpp_list->nr_header_lines; | ||
| 102 | browser->rows -= browser->extra_title_lines; | ||
| 89 | /* | 103 | /* |
| 90 | * Verify if we were at the last line and that line isn't | 104 | * Verify if we were at the last line and that line isn't |
| 91 | * visibe because we now show the header line(s). | 105 | * visibe because we now show the header line(s). |
| @@ -108,17 +122,6 @@ static void hist_browser__refresh_dimensions(struct ui_browser *browser) · 16 unmodified lines | |||
| 108 | * changeset. | 122 | * changeset. |
| 109 | */ | 123 | */ |
| 110 | ui_browser__refresh_dimensions(browser); | 124 | ui_browser__refresh_dimensions(browser); |
| 111 | hist_browser__update_rows(hb); | ||
| 112 | } | ||
| 113 | |||
| 114 | static void hist_browser__gotorc(struct hist_browser *browser, int row, int column) | ||
| 115 | { | ||
| 116 | struct hists *hists = browser->hists; | ||
| 117 | struct perf_hpp_list *hpp_list = hists->hpp_list; | ||
| 118 | u16 header_offset; | ||
| 119 | |||
| 120 | header_offset = browser->show_headers ? hpp_list->nr_header_lines : 0; | ||
| 121 | ui_browser__gotorc(&browser->b, row + header_offset, column); | ||
| 122 | } | 125 | } |
| 123 | 126 | ||
| 124 | static void hist_browser__reset(struct hist_browser *browser) | 127 | static void hist_browser__reset(struct hist_browser *browser) |
| @@ -656,9 +659,10 @@ int hist_browser__run(struct hist_browser *browser, const char *help, · 531 unmodified lines | |||
| 656 | struct hist_entry *h = rb_entry(browser->b.top, | 659 | struct hist_entry *h = rb_entry(browser->b.top, |
| 657 | struct hist_entry, rb_node); | 660 | struct hist_entry, rb_node); |
| 658 | ui_helpline__pop(); | 661 | ui_helpline__pop(); |
| 659 | ui_helpline__fpush("%d: nr_ent=(%d,%d), rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", | 662 | ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d", |
| 660 | seq++, browser->b.nr_entries, | 663 | seq++, browser->b.nr_entries, |
| 661 | browser->hists->nr_entries, | 664 | browser->hists->nr_entries, |
| 665 | browser->b.extra_title_lines, | ||
| 662 | browser->b.rows, | 666 | browser->b.rows, |
| 663 | browser->b.index, | 667 | browser->b.index, |
| 664 | browser->b.top_idx, | 668 | browser->b.top_idx, |
| @@ -733,7 +737,7 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser, · 68 unmodified lines | |||
| 733 | } | 737 | } |
| 734 | 738 | ||
| 735 | ui_browser__set_color(&browser->b, color); | 739 | ui_browser__set_color(&browser->b, color); |
| 736 | hist_browser__gotorc(browser, row, 0); | 740 | ui_browser__gotorc(&browser->b, row, 0); |
| 737 | ui_browser__write_nstring(&browser->b, " ", offset); | 741 | ui_browser__write_nstring(&browser->b, " ", offset); |
| 738 | ui_browser__printf(&browser->b, "%c", folded_sign); | 742 | ui_browser__printf(&browser->b, "%c", folded_sign); |
| 739 | ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' '); | 743 | ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' '); |
| @@ -1249,7 +1253,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, · 509 unmodified lines | |||
| 1249 | }; | 1253 | }; |
| 1250 | int column = 0; | 1254 | int column = 0; |
| 1251 | 1255 | ||
| 1252 | hist_browser__gotorc(browser, row, 0); | 1256 | ui_browser__gotorc(&browser->b, row, 0); |
| 1253 | 1257 | ||
| 1254 | hists__for_each_format(browser->hists, fmt) { | 1258 | hists__for_each_format(browser->hists, fmt) { |
| 1255 | char s[2048]; | 1259 | char s[2048]; |
| @@ -1358,7 +1362,7 @@ static int hist_browser__show_hierarchy_entry(struct hist_browser *browser, · 102 unmodified lines | |||
| 1358 | goto show_callchain; | 1362 | goto show_callchain; |
| 1359 | } | 1363 | } |
| 1360 | 1364 | ||
| 1361 | hist_browser__gotorc(browser, row, 0); | 1365 | ui_browser__gotorc(&browser->b, row, 0); |
| 1362 | 1366 | ||
| 1363 | if (current_entry && browser->b.navkeypressed) | 1367 | if (current_entry && browser->b.navkeypressed) |
| 1364 | ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); | 1368 | ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); |
| @@ -1507,7 +1511,7 @@ static int hist_browser__show_no_entry(struct hist_browser *browser, · 142 unmodified lines | |||
| 1507 | browser->selection = NULL; | 1511 | browser->selection = NULL; |
| 1508 | } | 1512 | } |
| 1509 | 1513 | ||
| 1510 | hist_browser__gotorc(browser, row, 0); | 1514 | ui_browser__gotorc(&browser->b, row, 0); |
| 1511 | 1515 | ||
| 1512 | if (current_entry && browser->b.navkeypressed) | 1516 | if (current_entry && browser->b.navkeypressed) |
| 1513 | ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); | 1517 | ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED); |
| @@ -1713,7 +1717,7 @@ static void hists_browser__headers(struct hist_browser *browser) · 199 unmodified lines | |||
| 1713 | hists_browser__scnprintf_headers(browser, headers, | 1717 | hists_browser__scnprintf_headers(browser, headers, |
| 1714 | sizeof(headers), line); | 1718 | sizeof(headers), line); |
| 1715 | 1719 | ||
| 1716 | ui_browser__gotorc(&browser->b, line, 0); | 1720 | ui_browser__gotorc_title(&browser->b, line, 0); |
| 1717 | ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); | 1721 | ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); |
| 1718 | ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); | 1722 | ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); |
| 1719 | } | 1723 | } |
| @@ -1740,17 +1744,11 @@ static void ui_browser__hists_init_top(struct ui_browser *browser) · 20 unmodified lines | |||
| 1740 | static unsigned int hist_browser__refresh(struct ui_browser *browser) | 1744 | static unsigned int hist_browser__refresh(struct ui_browser *browser) |
| 1741 | { | 1745 | { |
| 1742 | unsigned row = 0; | 1746 | unsigned row = 0; |
| 1743 | u16 header_offset = 0; | ||
| 1744 | struct rb_node *nd; | 1747 | struct rb_node *nd; |
| 1745 | struct hist_browser *hb = container_of(browser, struct hist_browser, b); | 1748 | struct hist_browser *hb = container_of(browser, struct hist_browser, b); |
| 1746 | struct hists *hists = hb->hists; | ||
| 1747 | |||
| 1748 | if (hb->show_headers) { | ||
| 1749 | struct perf_hpp_list *hpp_list = hists->hpp_list; | ||
| 1750 | 1749 | ||
| 1750 | if (hb->show_headers) | ||
| 1751 | hist_browser__show_headers(hb); | 1751 | hist_browser__show_headers(hb); |
| 1752 | header_offset = hpp_list->nr_header_lines; | ||
| 1753 | } | ||
| 1754 | 1752 | ||
| 1755 | ui_browser__hists_init_top(browser); | 1753 | ui_browser__hists_init_top(browser); |
| 1756 | hb->he_selection = NULL; | 1754 | hb->he_selection = NULL; |
| @@ -1788,7 +1786,7 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser) · 31 unmodified lines | |||
| 1788 | break; | 1786 | break; |
| 1789 | } | 1787 | } |
| 1790 | 1788 | ||
| 1791 | return row + header_offset; | 1789 | return row; |
| 1792 | } | 1790 | } |
| 1793 | 1791 | ||
| 1794 | static struct rb_node *hists__filter_entries(struct rb_node *nd, | 1792 | static struct rb_node *hists__filter_entries(struct rb_node *nd, |
| @@ -2143,6 +2141,7 @@ void hist_browser__init(struct hist_browser *browser, · 348 unmodified lines | |||
| 2143 | browser->b.seek = ui_browser__hists_seek; | 2141 | browser->b.seek = ui_browser__hists_seek; |
| 2144 | browser->b.use_navkeypressed = true; | 2142 | browser->b.use_navkeypressed = true; |
| 2145 | browser->show_headers = symbol_conf.show_hist_headers; | 2143 | browser->show_headers = symbol_conf.show_hist_headers; |
| 2144 | hist_browser__set_title_space(browser); | ||
| 2146 | 2145 | ||
| 2147 | if (symbol_conf.report_hierarchy) { | 2146 | if (symbol_conf.report_hierarchy) { |
| 2148 | struct perf_hpp_list_node *fmt_node; | 2147 | struct perf_hpp_list_node *fmt_node; |
| @@ -2183,7 +2182,7 @@ perf_evsel_browser__new(struct perf_evsel *evsel, · 34 unmodified lines | |||
| 2183 | if (browser) { | 2182 | if (browser) { |
| 2184 | browser->hbt = hbt; | 2183 | browser->hbt = hbt; |
| 2185 | browser->env = env; | 2184 | browser->env = env; |
| 2186 | browser->title = perf_evsel_browser_title; | 2185 | browser->title = hists_browser__scnprintf_title; |
| 2187 | } | 2186 | } |
| 2188 | return browser; | 2187 | return browser; |
| 2189 | } | 2188 | } |
| @@ -2209,84 +2208,11 @@ static inline bool is_report_browser(void *timer) · 19 unmodified lines | |||
| 2209 | return timer == NULL; | 2208 | return timer == NULL; |
| 2210 | } | 2209 | } |
| 2211 | 2210 | ||
| 2212 | static int perf_evsel_browser_title(struct hist_browser *browser, | 2211 | static int hists_browser__scnprintf_title(struct hist_browser *browser, char *bf, size_t size) |
| 2213 | char *bf, size_t size) | ||
| 2214 | { | 2212 | { |
| 2215 | struct hist_browser_timer *hbt = browser->hbt; | 2213 | struct hist_browser_timer *hbt = browser->hbt; |
| 2216 | struct hists *hists = browser->hists; | 2214 | int printed = __hists__scnprintf_title(browser->hists, bf, size, !is_report_browser(hbt)); |
| 2217 | char unit; | ||
| 2218 | int printed; | ||
| 2219 | const struct dso *dso = hists->dso_filter; | ||
| 2220 | const struct thread *thread = hists->thread_filter; | ||
| 2221 | int socket_id = hists->socket_filter; | ||
| 2222 | unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; | ||
| 2223 | u64 nr_events = hists->stats.total_period; | ||
| 2224 | struct perf_evsel *evsel = hists_to_evsel(hists); | ||
| 2225 | const char *ev_name = perf_evsel__name(evsel); | ||
| 2226 | char buf[512], sample_freq_str[64] = ""; | ||
| 2227 | size_t buflen = sizeof(buf); | ||
| 2228 | char ref[30] = " show reference callgraph, "; | ||
| 2229 | bool enable_ref = false; | ||
| 2230 | 2215 | ||
| 2231 | if (symbol_conf.filter_relative) { | ||
| 2232 | nr_samples = hists->stats.nr_non_filtered_samples; | ||
| 2233 | nr_events = hists->stats.total_non_filtered_period; | ||
| 2234 | } | ||
| 2235 | |||
| 2236 | if (perf_evsel__is_group_event(evsel)) { | ||
| 2237 | struct perf_evsel *pos; | ||
| 2238 | |||
| 2239 | perf_evsel__group_desc(evsel, buf, buflen); | ||
| 2240 | ev_name = buf; | ||
| 2241 | |||
| 2242 | for_each_group_member(pos, evsel) { | ||
| 2243 | struct hists *pos_hists = evsel__hists(pos); | ||
| 2244 | |||
| 2245 | if (symbol_conf.filter_relative) { | ||
| 2246 | nr_samples += pos_hists->stats.nr_non_filtered_samples; | ||
| 2247 | nr_events += pos_hists->stats.total_non_filtered_period; | ||
| 2248 | } else { | ||
| 2249 | nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; | ||
| 2250 | nr_events += pos_hists->stats.total_period; | ||
| 2251 | } | ||
| 2252 | } | ||
| 2253 | } | ||
| 2254 | |||
| 2255 | if (symbol_conf.show_ref_callgraph && | ||
| 2256 | strstr(ev_name, "call-graph=no")) | ||
| 2257 | enable_ref = true; | ||
| 2258 | |||
| 2259 | if (!is_report_browser(hbt)) | ||
| 2260 | scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); | ||
| 2261 | |||
| 2262 | nr_samples = convert_unit(nr_samples, &unit); | ||
| 2263 | printed = scnprintf(bf, size, | ||
| 2264 | "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, | ||
| 2265 | nr_samples, unit, evsel->nr_members > 1 ? "s" : "", | ||
| 2266 | ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); | ||
| 2267 | |||
| 2268 | |||
| 2269 | if (hists->uid_filter_str) | ||
| 2270 | printed += snprintf(bf + printed, size - printed, | ||
| 2271 | ", UID: %s", hists->uid_filter_str); | ||
| 2272 | if (thread) { | ||
| 2273 | if (hists__has(hists, thread)) { | ||
| 2274 | printed += scnprintf(bf + printed, size - printed, | ||
| 2275 | ", Thread: %s(%d)", | ||
| 2276 | (thread->comm_set ? thread__comm_str(thread) : ""), | ||
| 2277 | thread->tid); | ||
| 2278 | } else { | ||
| 2279 | printed += scnprintf(bf + printed, size - printed, | ||
| 2280 | ", Thread: %s", | ||
| 2281 | (thread->comm_set ? thread__comm_str(thread) : "")); | ||
| 2282 | } | ||
| 2283 | } | ||
| 2284 | if (dso) | ||
| 2285 | printed += scnprintf(bf + printed, size - printed, | ||
| 2286 | ", DSO: %s", dso->short_name); | ||
| 2287 | if (socket_id > -1) | ||
| 2288 | printed += scnprintf(bf + printed, size - printed, | ||
| 2289 | ", Processor Socket: %d", socket_id); | ||
| 2290 | if (!is_report_browser(hbt)) { | 2216 | if (!is_report_browser(hbt)) { |
| 2291 | struct perf_top *top = hbt->arg; | 2217 | struct perf_top *top = hbt->arg; |
| 2292 | 2218 | ||
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 17 | #include "config.h" | 17 | #include "config.h" |
| 18 | #include "cache.h" | 18 | #include "cache.h" |
| 19 | #include "symbol.h" | 19 | #include "symbol.h" |
| 20 | #include "units.h" | ||
| 20 | #include "debug.h" | 21 | #include "debug.h" |
| 21 | #include "annotate.h" | 22 | #include "annotate.h" |
| 22 | #include "evsel.h" | 23 | #include "evsel.h" |
| @@ -2324,7 +2325,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map, · 2301 unmodified lines | |||
| 2324 | struct dso *dso = map->dso; | 2325 | struct dso *dso = map->dso; |
| 2325 | struct rb_root source_line = RB_ROOT; | 2326 | struct rb_root source_line = RB_ROOT; |
| 2326 | struct annotation_options opts = annotation__default_options; | 2327 | struct annotation_options opts = annotation__default_options; |
| 2327 | const char *ev_name = perf_evsel__name(evsel); | 2328 | struct annotation *notes = symbol__annotation(sym); |
| 2328 | char buf[1024]; | 2329 | char buf[1024]; |
| 2329 | 2330 | ||
| 2330 | if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0) | 2331 | if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0) |
| @@ -2336,12 +2337,8 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map, · 5 unmodified lines | |||
| 2336 | print_summary(&source_line, dso->long_name); | 2337 | print_summary(&source_line, dso->long_name); |
| 2337 | } | 2338 | } |
| 2338 | 2339 | ||
| 2339 | if (perf_evsel__is_group_event(evsel)) { | 2340 | annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel); |
| 2340 | perf_evsel__group_desc(evsel, buf, sizeof(buf)); | 2341 | fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name); |
| 2341 | ev_name = buf; | ||
| 2342 | } | ||
| 2343 | |||
| 2344 | fprintf(stdout, "%s() %s\nEvent: %s\n\n", sym->name, dso->long_name, ev_name); | ||
| 2345 | symbol__annotate_fprintf2(sym, stdout); | 2342 | symbol__annotate_fprintf2(sym, stdout); |
| 2346 | 2343 | ||
| 2347 | annotated_source__purge(symbol__annotation(sym)->src); | 2344 | annotated_source__purge(symbol__annotation(sym)->src); |
| @@ -2597,6 +2594,46 @@ out_free_offsets: · 249 unmodified lines | |||
| 2597 | return -1; | 2594 | return -1; |
| 2598 | } | 2595 | } |
| 2599 | 2596 | ||
| 2597 | int __annotation__scnprintf_samples_period(struct annotation *notes, | ||
| 2598 | char *bf, size_t size, | ||
| 2599 | struct perf_evsel *evsel, | ||
| 2600 | bool show_freq) | ||
| 2601 | { | ||
| 2602 | const char *ev_name = perf_evsel__name(evsel); | ||
| 2603 | char buf[1024], ref[30] = " show reference callgraph, "; | ||
| 2604 | char sample_freq_str[64] = ""; | ||
| 2605 | unsigned long nr_samples = 0; | ||
| 2606 | int nr_members = 1; | ||
| 2607 | bool enable_ref = false; | ||
| 2608 | u64 nr_events = 0; | ||
| 2609 | char unit; | ||
| 2610 | int i; | ||
| 2611 | |||
| 2612 | if (perf_evsel__is_group_event(evsel)) { | ||
| 2613 | perf_evsel__group_desc(evsel, buf, sizeof(buf)); | ||
| 2614 | ev_name = buf; | ||
| 2615 | nr_members = evsel->nr_members; | ||
| 2616 | } | ||
| 2617 | |||
| 2618 | for (i = 0; i < nr_members; i++) { | ||
| 2619 | struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i); | ||
| 2620 | |||
| 2621 | nr_samples += ah->nr_samples; | ||
| 2622 | nr_events += ah->period; | ||
| 2623 | } | ||
| 2624 | |||
| 2625 | if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no")) | ||
| 2626 | enable_ref = true; | ||
| 2627 | |||
| 2628 | if (show_freq) | ||
| 2629 | scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); | ||
| 2630 | |||
| 2631 | nr_samples = convert_unit(nr_samples, &unit); | ||
| 2632 | return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, | ||
| 2633 | nr_samples, unit, evsel->nr_members > 1 ? "s" : "", | ||
| 2634 | ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); | ||
| 2635 | } | ||
| 2636 | |||
| 2600 | #define ANNOTATION__CFG(n) \ | 2637 | #define ANNOTATION__CFG(n) \ |
| 2601 | { .name = #n, .value = &annotation__default_options.n, } | 2638 | { .name = #n, .value = &annotation__default_options.n, } |
| 2602 | 2639 | ||
| @@ -151,6 +151,18 @@ double annotation_line__max_percent(struct annotation_line *al, struct annotatio · 150 unmodified lines | |||
| 151 | void annotation_line__write(struct annotation_line *al, struct annotation *notes, | 151 | void annotation_line__write(struct annotation_line *al, struct annotation *notes, |
| 152 | struct annotation_write_ops *ops); | 152 | struct annotation_write_ops *ops); |
| 153 | 153 | ||
| 154 | int __annotation__scnprintf_samples_period(struct annotation *notes, | ||
| 155 | char *bf, size_t size, | ||
| 156 | struct perf_evsel *evsel, | ||
| 157 | bool show_freq); | ||
| 158 | |||
| 159 | static inline int annotation__scnprintf_samples_period(struct annotation *notes, | ||
| 160 | char *bf, size_t size, | ||
| 161 | struct perf_evsel *evsel) | ||
| 162 | { | ||
| 163 | return __annotation__scnprintf_samples_period(notes, bf, size, evsel, true); | ||
| 164 | } | ||
| 165 | |||
| 154 | int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); | 166 | int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); |
| 155 | size_t disasm__fprintf(struct list_head *head, FILE *fp); | 167 | size_t disasm__fprintf(struct list_head *head, FILE *fp); |
| 156 | void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); | 168 | void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); |
| @@ -302,13 +302,27 @@ static int auxtrace_queues__split_buffer(struct auxtrace_queues *queues, · 301 unmodified lines | |||
| 302 | return 0; | 302 | return 0; |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | static bool filter_cpu(struct perf_session *session, int cpu) | ||
| 306 | { | ||
| 307 | unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap; | ||
| 308 | |||
| 309 | return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap); | ||
| 310 | } | ||
| 311 | |||
| 305 | static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, | 312 | static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, |
| 306 | struct perf_session *session, | 313 | struct perf_session *session, |
| 307 | unsigned int idx, | 314 | unsigned int idx, |
| 308 | struct auxtrace_buffer *buffer, | 315 | struct auxtrace_buffer *buffer, |
| 309 | struct auxtrace_buffer **buffer_ptr) | 316 | struct auxtrace_buffer **buffer_ptr) |
| 310 | { | 317 | { |
| 311 | int err; | 318 | int err = -ENOMEM; |
| 319 | |||
| 320 | if (filter_cpu(session, buffer->cpu)) | ||
| 321 | return 0; | ||
| 322 | |||
| 323 | buffer = memdup(buffer, sizeof(*buffer)); | ||
| 324 | if (!buffer) | ||
| 325 | return -ENOMEM; | ||
| 312 | 326 | ||
| 313 | if (session->one_mmap) { | 327 | if (session->one_mmap) { |
| 314 | buffer->data = buffer->data_offset - session->one_mmap_offset + | 328 | buffer->data = buffer->data_offset - session->one_mmap_offset + |
| @@ -316,31 +330,28 @@ static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, · 1 unmodified line | |||
| 316 | } else if (perf_data__is_pipe(session->data)) { | 330 | } else if (perf_data__is_pipe(session->data)) { |
| 317 | buffer->data = auxtrace_copy_data(buffer->size, session); | 331 | buffer->data = auxtrace_copy_data(buffer->size, session); |
| 318 | if (!buffer->data) | 332 | if (!buffer->data) |
| 319 | return -ENOMEM; | 333 | goto out_free; |
| 320 | buffer->data_needs_freeing = true; | 334 | buffer->data_needs_freeing = true; |
| 321 | } else if (BITS_PER_LONG == 32 && | 335 | } else if (BITS_PER_LONG == 32 && |
| 322 | buffer->size > BUFFER_LIMIT_FOR_32_BIT) { | 336 | buffer->size > BUFFER_LIMIT_FOR_32_BIT) { |
| 323 | err = auxtrace_queues__split_buffer(queues, idx, buffer); | 337 | err = auxtrace_queues__split_buffer(queues, idx, buffer); |
| 324 | if (err) | 338 | if (err) |
| 325 | return err; | 339 | goto out_free; |
| 326 | } | 340 | } |
| 327 | 341 | ||
| 328 | err = auxtrace_queues__queue_buffer(queues, idx, buffer); | 342 | err = auxtrace_queues__queue_buffer(queues, idx, buffer); |
| 329 | if (err) | 343 | if (err) |
| 330 | return err; | 344 | goto out_free; |
| 331 | 345 | ||
| 332 | /* FIXME: Doesn't work for split buffer */ | 346 | /* FIXME: Doesn't work for split buffer */ |
| 333 | if (buffer_ptr) | 347 | if (buffer_ptr) |
| 334 | *buffer_ptr = buffer; | 348 | *buffer_ptr = buffer; |
| 335 | 349 | ||
| 336 | return 0; | 350 | return 0; |
| 337 | } | ||
| 338 | 351 | ||
| 339 | static bool filter_cpu(struct perf_session *session, int cpu) | 352 | out_free: |
| 340 | { | 353 | auxtrace_buffer__free(buffer); |
| 341 | unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap; | 354 | return err; |
| 342 | |||
| 343 | return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap); | ||
| 344 | } | 355 | } |
| 345 | 356 | ||
| 346 | int auxtrace_queues__add_event(struct auxtrace_queues *queues, | 357 | int auxtrace_queues__add_event(struct auxtrace_queues *queues, |
| @@ -348,36 +359,19 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues, · 1 unmodified line | |||
| 348 | union perf_event *event, off_t data_offset, | 359 | union perf_event *event, off_t data_offset, |
| 349 | struct auxtrace_buffer **buffer_ptr) | 360 | struct auxtrace_buffer **buffer_ptr) |
| 350 | { | 361 | { |
| 351 | struct auxtrace_buffer *buffer; | 362 | struct auxtrace_buffer buffer = { |
| 352 | unsigned int idx; | 363 | .pid = -1, |
| 353 | int err; | 364 | .tid = event->auxtrace.tid, |
| 354 | 365 | .cpu = event->auxtrace.cpu, | |
| 355 | if (filter_cpu(session, event->auxtrace.cpu)) | 366 | .data_offset = data_offset, |
| 356 | return 0; | 367 | .offset = event->auxtrace.offset, |
| 357 | 368 | .reference = event->auxtrace.reference, | |
| 358 | buffer = zalloc(sizeof(struct auxtrace_buffer)); | 369 | .size = event->auxtrace.size, |
| 359 | if (!buffer) | 370 | }; |
| 360 | return -ENOMEM; | 371 | unsigned int idx = event->auxtrace.idx; |
| 361 | |||
| 362 | buffer->pid = -1; | ||
| 363 | buffer->tid = event->auxtrace.tid; | ||
| 364 | buffer->cpu = event->auxtrace.cpu; | ||
| 365 | buffer->data_offset = data_offset; | ||
| 366 | buffer->offset = event->auxtrace.offset; | ||
| 367 | buffer->reference = event->auxtrace.reference; | ||
| 368 | buffer->size = event->auxtrace.size; | ||
| 369 | idx = event->auxtrace.idx; | ||
| 370 | |||
| 371 | err = auxtrace_queues__add_buffer(queues, session, idx, buffer, | ||
| 372 | buffer_ptr); | ||
| 373 | if (err) | ||
| 374 | goto out_err; | ||
| 375 | |||
| 376 | return 0; | ||
| 377 | 372 | ||
| 378 | out_err: | 373 | return auxtrace_queues__add_buffer(queues, session, idx, &buffer, |
| 379 | auxtrace_buffer__free(buffer); | 374 | buffer_ptr); |
| 380 | return err; | ||
| 381 | } | 375 | } |
| 382 | 376 | ||
| 383 | static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues, | 377 | static int auxtrace_queues__add_indexed_event(struct auxtrace_queues *queues, |
| @@ -41,7 +41,7 @@ int test__clang_to_IR(void) · 40 unmodified lines | |||
| 41 | if (!M) | 41 | if (!M) |
| 42 | return -1; | 42 | return -1; |
| 43 | for (llvm::Function& F : *M) | 43 | for (llvm::Function& F : *M) |
| 44 | if (F.getName() == "bpf_func__SyS_epoll_wait") | 44 | if (F.getName() == "bpf_func__SyS_epoll_pwait") |
| 45 | return 0; | 45 | return 0; |
| 46 | return -1; | 46 | return -1; |
| 47 | } | 47 | } |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | * Copyright (C) 2016 Huawei Inc. | 9 | * Copyright (C) 2016 Huawei Inc. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include "clang/Basic/Version.h" | ||
| 12 | #include "clang/CodeGen/CodeGenAction.h" | 13 | #include "clang/CodeGen/CodeGenAction.h" |
| 13 | #include "clang/Frontend/CompilerInvocation.h" | 14 | #include "clang/Frontend/CompilerInvocation.h" |
| 14 | #include "clang/Frontend/CompilerInstance.h" | 15 | #include "clang/Frontend/CompilerInstance.h" |
| @@ -58,7 +59,8 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path, · 43 unmodified lines | |||
| 58 | 59 | ||
| 59 | FrontendOptions& Opts = CI->getFrontendOpts(); | 60 | FrontendOptions& Opts = CI->getFrontendOpts(); |
| 60 | Opts.Inputs.clear(); | 61 | Opts.Inputs.clear(); |
| 61 | Opts.Inputs.emplace_back(Path, IK_C); | 62 | Opts.Inputs.emplace_back(Path, |
| 63 | FrontendOptions::getInputKindForExtension("c")); | ||
| 62 | return CI; | 64 | return CI; |
| 63 | } | 65 | } |
| 64 | 66 | ||
| @@ -71,10 +73,17 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, · 6 unmodified lines | |||
| 71 | 73 | ||
| 72 | Clang.setVirtualFileSystem(&*VFS); | 74 | Clang.setVirtualFileSystem(&*VFS); |
| 73 | 75 | ||
| 76 | #if CLANG_VERSION_MAJOR < 4 | ||
| 74 | IntrusiveRefCntPtr<CompilerInvocation> CI = | 77 | IntrusiveRefCntPtr<CompilerInvocation> CI = |
| 75 | createCompilerInvocation(std::move(CFlags), Path, | 78 | createCompilerInvocation(std::move(CFlags), Path, |
| 76 | Clang.getDiagnostics()); | 79 | Clang.getDiagnostics()); |
| 77 | Clang.setInvocation(&*CI); | 80 | Clang.setInvocation(&*CI); |
| 81 | #else | ||
| 82 | std::shared_ptr<CompilerInvocation> CI( | ||
| 83 | createCompilerInvocation(std::move(CFlags), Path, | ||
| 84 | Clang.getDiagnostics())); | ||
| 85 | Clang.setInvocation(CI); | ||
| 86 | #endif | ||
| 78 | 87 | ||
| 79 | std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx)); | 88 | std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx)); |
| 80 | if (!Clang.ExecuteAction(*Act)) | 89 | if (!Clang.ExecuteAction(*Act)) |
| @@ -979,7 +979,7 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) · 978 unmodified lines | |||
| 979 | return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); | 979 | return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); |
| 980 | } | 980 | } |
| 981 | 981 | ||
| 982 | #ifdef HAVE_DWARF_GETLOCATIONS | 982 | #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT |
| 983 | /** | 983 | /** |
| 984 | * die_get_var_innermost_scope - Get innermost scope range of given variable DIE | 984 | * die_get_var_innermost_scope - Get innermost scope range of given variable DIE |
| 985 | * @sp_die: a subprogram DIE | 985 | * @sp_die: a subprogram DIE |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | #include "session.h" | 6 | #include "session.h" |
| 7 | #include "namespaces.h" | 7 | #include "namespaces.h" |
| 8 | #include "sort.h" | 8 | #include "sort.h" |
| 9 | #include "units.h" | ||
| 9 | #include "evlist.h" | 10 | #include "evlist.h" |
| 10 | #include "evsel.h" | 11 | #include "evsel.h" |
| 11 | #include "annotate.h" | 12 | #include "annotate.h" |
| @@ -14,6 +15,7 @@ · 2 unmodified lines | |||
| 14 | #include "ui/progress.h" | 15 | #include "ui/progress.h" |
| 15 | #include <errno.h> | 16 | #include <errno.h> |
| 16 | #include <math.h> | 17 | #include <math.h> |
| 18 | #include <inttypes.h> | ||
| 17 | #include <sys/param.h> | 19 | #include <sys/param.h> |
| 18 | 20 | ||
| 19 | static bool hists__filter_entry_by_dso(struct hists *hists, | 21 | static bool hists__filter_entry_by_dso(struct hists *hists, |
| @@ -2454,6 +2456,85 @@ u64 hists__total_period(struct hists *hists) · 2434 unmodified lines | |||
| 2454 | hists->stats.total_period; | 2456 | hists->stats.total_period; |
| 2455 | } | 2457 | } |
| 2456 | 2458 | ||
| 2459 | int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq) | ||
| 2460 | { | ||
| 2461 | char unit; | ||
| 2462 | int printed; | ||
| 2463 | const struct dso *dso = hists->dso_filter; | ||
| 2464 | const struct thread *thread = hists->thread_filter; | ||
| 2465 | int socket_id = hists->socket_filter; | ||
| 2466 | unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; | ||
| 2467 | u64 nr_events = hists->stats.total_period; | ||
| 2468 | struct perf_evsel *evsel = hists_to_evsel(hists); | ||
| 2469 | const char *ev_name = perf_evsel__name(evsel); | ||
| 2470 | char buf[512], sample_freq_str[64] = ""; | ||
| 2471 | size_t buflen = sizeof(buf); | ||
| 2472 | char ref[30] = " show reference callgraph, "; | ||
| 2473 | bool enable_ref = false; | ||
| 2474 | |||
| 2475 | if (symbol_conf.filter_relative) { | ||
| 2476 | nr_samples = hists->stats.nr_non_filtered_samples; | ||
| 2477 | nr_events = hists->stats.total_non_filtered_period; | ||
| 2478 | } | ||
| 2479 | |||
| 2480 | if (perf_evsel__is_group_event(evsel)) { | ||
| 2481 | struct perf_evsel *pos; | ||
| 2482 | |||
| 2483 | perf_evsel__group_desc(evsel, buf, buflen); | ||
| 2484 | ev_name = buf; | ||
| 2485 | |||
| 2486 | for_each_group_member(pos, evsel) { | ||
| 2487 | struct hists *pos_hists = evsel__hists(pos); | ||
| 2488 | |||
| 2489 | if (symbol_conf.filter_relative) { | ||
| 2490 | nr_samples += pos_hists->stats.nr_non_filtered_samples; | ||
| 2491 | nr_events += pos_hists->stats.total_non_filtered_period; | ||
| 2492 | } else { | ||
| 2493 | nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; | ||
| 2494 | nr_events += pos_hists->stats.total_period; | ||
| 2495 | } | ||
| 2496 | } | ||
| 2497 | } | ||
| 2498 | |||
| 2499 | if (symbol_conf.show_ref_callgraph && | ||
| 2500 | strstr(ev_name, "call-graph=no")) | ||
| 2501 | enable_ref = true; | ||
| 2502 | |||
| 2503 | if (show_freq) | ||
| 2504 | scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq); | ||
| 2505 | |||
| 2506 | nr_samples = convert_unit(nr_samples, &unit); | ||
| 2507 | printed = scnprintf(bf, size, | ||
| 2508 | "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64, | ||
| 2509 | nr_samples, unit, evsel->nr_members > 1 ? "s" : "", | ||
| 2510 | ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events); | ||
| 2511 | |||
| 2512 | |||
| 2513 | if (hists->uid_filter_str) | ||
| 2514 | printed += snprintf(bf + printed, size - printed, | ||
| 2515 | ", UID: %s", hists->uid_filter_str); | ||
| 2516 | if (thread) { | ||
| 2517 | if (hists__has(hists, thread)) { | ||
| 2518 | printed += scnprintf(bf + printed, size - printed, | ||
| 2519 | ", Thread: %s(%d)", | ||
| 2520 | (thread->comm_set ? thread__comm_str(thread) : ""), | ||
| 2521 | thread->tid); | ||
| 2522 | } else { | ||
| 2523 | printed += scnprintf(bf + printed, size - printed, | ||
| 2524 | ", Thread: %s", | ||
| 2525 | (thread->comm_set ? thread__comm_str(thread) : "")); | ||
| 2526 | } | ||
| 2527 | } | ||
| 2528 | if (dso) | ||
| 2529 | printed += scnprintf(bf + printed, size - printed, | ||
| 2530 | ", DSO: %s", dso->short_name); | ||
| 2531 | if (socket_id > -1) | ||
| 2532 | printed += scnprintf(bf + printed, size - printed, | ||
| 2533 | ", Processor Socket: %d", socket_id); | ||
| 2534 | |||
| 2535 | return printed; | ||
| 2536 | } | ||
| 2537 | |||
| 2457 | int parse_filter_percentage(const struct option *opt __maybe_unused, | 2538 | int parse_filter_percentage(const struct option *opt __maybe_unused, |
| 2458 | const char *arg, int unset __maybe_unused) | 2539 | const char *arg, int unset __maybe_unused) |
| 2459 | { | 2540 | { |
| @@ -61,6 +61,7 @@ enum hist_column { · 60 unmodified lines | |||
| 61 | HISTC_SRCLINE_TO, | 61 | HISTC_SRCLINE_TO, |
| 62 | HISTC_TRACE, | 62 | HISTC_TRACE, |
| 63 | HISTC_SYM_SIZE, | 63 | HISTC_SYM_SIZE, |
| 64 | HISTC_DSO_SIZE, | ||
| 64 | HISTC_NR_COLS, /* Last entry */ | 65 | HISTC_NR_COLS, /* Last entry */ |
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| @@ -503,5 +504,11 @@ int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...); · 436 unmodified lines | |||
| 503 | int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp, | 504 | int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp, |
| 504 | struct perf_hpp_list *hpp_list); | 505 | struct perf_hpp_list *hpp_list); |
| 505 | int hists__fprintf_headers(struct hists *hists, FILE *fp); | 506 | int hists__fprintf_headers(struct hists *hists, FILE *fp); |
| 507 | int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq); | ||
| 508 | |||
| 509 | static inline int hists__scnprintf_title(struct hists *hists, char *bf, size_t size) | ||
| 510 | { | ||
| 511 | return __hists__scnprintf_title(hists, bf, size, true); | ||
| 512 | } | ||
| 506 | 513 | ||
| 507 | #endif /* __PERF_HIST_H */ | 514 | #endif /* __PERF_HIST_H */ |
| @@ -103,6 +103,10 @@ static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip) · 102 unmodified lines | |||
| 103 | return ip; | 103 | return ip; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | static inline size_t map__size(const struct map *map) | ||
| 107 | { | ||
| 108 | return map->end - map->start; | ||
| 109 | } | ||
| 106 | 110 | ||
| 107 | /* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ | 111 | /* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ |
| 108 | u64 map__rip_2objdump(struct map *map, u64 rip); | 112 | u64 map__rip_2objdump(struct map *map, u64 rip); |
| @@ -1591,7 +1591,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session) · 1590 unmodified lines | |||
| 1591 | drop_rate = (double)stats->total_lost_samples / | 1591 | drop_rate = (double)stats->total_lost_samples / |
| 1592 | (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples); | 1592 | (double) (stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples); |
| 1593 | if (drop_rate > 0.05) { | 1593 | if (drop_rate > 0.05) { |
| 1594 | ui__warning("Processed %" PRIu64 " samples and lost %3.2f%% samples!\n\n", | 1594 | ui__warning("Processed %" PRIu64 " samples and lost %3.2f%%!\n\n", |
| 1595 | stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples, | 1595 | stats->nr_events[PERF_RECORD_SAMPLE] + stats->total_lost_samples, |
| 1596 | drop_rate * 100.0); | 1596 | drop_rate * 100.0); |
| 1597 | } | 1597 | } |
| @@ -1545,6 +1545,46 @@ struct sort_entry sort_sym_size = { · 1544 unmodified lines | |||
| 1545 | .se_width_idx = HISTC_SYM_SIZE, | 1545 | .se_width_idx = HISTC_SYM_SIZE, |
| 1546 | }; | 1546 | }; |
| 1547 | 1547 | ||
| 1548 | /* --sort dso_size */ | ||
| 1549 | |||
| 1550 | static int64_t _sort__dso_size_cmp(struct map *map_l, struct map *map_r) | ||
| 1551 | { | ||
| 1552 | int64_t size_l = map_l != NULL ? map__size(map_l) : 0; | ||
| 1553 | int64_t size_r = map_r != NULL ? map__size(map_r) : 0; | ||
| 1554 | |||
| 1555 | return size_l < size_r ? -1 : | ||
| 1556 | size_l == size_r ? 0 : 1; | ||
| 1557 | } | ||
| 1558 | |||
| 1559 | static int64_t | ||
| 1560 | sort__dso_size_cmp(struct hist_entry *left, struct hist_entry *right) | ||
| 1561 | { | ||
| 1562 | return _sort__dso_size_cmp(right->ms.map, left->ms.map); | ||
| 1563 | } | ||
| 1564 | |||
| 1565 | static int _hist_entry__dso_size_snprintf(struct map *map, char *bf, | ||
| 1566 | size_t bf_size, unsigned int width) | ||
| 1567 | { | ||
| 1568 | if (map && map->dso) | ||
| 1569 | return repsep_snprintf(bf, bf_size, "%*d", width, | ||
| 1570 | map__size(map)); | ||
| 1571 | |||
| 1572 | return repsep_snprintf(bf, bf_size, "%*s", width, "unknown"); | ||
| 1573 | } | ||
| 1574 | |||
| 1575 | static int hist_entry__dso_size_snprintf(struct hist_entry *he, char *bf, | ||
| 1576 | size_t size, unsigned int width) | ||
| 1577 | { | ||
| 1578 | return _hist_entry__dso_size_snprintf(he->ms.map, bf, size, width); | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | struct sort_entry sort_dso_size = { | ||
| 1582 | .se_header = "DSO size", | ||
| 1583 | .se_cmp = sort__dso_size_cmp, | ||
| 1584 | .se_snprintf = hist_entry__dso_size_snprintf, | ||
| 1585 | .se_width_idx = HISTC_DSO_SIZE, | ||
| 1586 | }; | ||
| 1587 | |||
| 1548 | 1588 | ||
| 1549 | struct sort_dimension { | 1589 | struct sort_dimension { |
| 1550 | const char *name; | 1590 | const char *name; |
| @@ -1569,6 +1609,7 @@ static struct sort_dimension common_sort_dimensions[] = { · 18 unmodified lines | |||
| 1569 | DIM(SORT_TRANSACTION, "transaction", sort_transaction), | 1609 | DIM(SORT_TRANSACTION, "transaction", sort_transaction), |
| 1570 | DIM(SORT_TRACE, "trace", sort_trace), | 1610 | DIM(SORT_TRACE, "trace", sort_trace), |
| 1571 | DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size), | 1611 | DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size), |
| 1612 | DIM(SORT_DSO_SIZE, "dso_size", sort_dso_size), | ||
| 1572 | DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id), | 1613 | DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id), |
| 1573 | }; | 1614 | }; |
| 1574 | 1615 | ||
| @@ -220,6 +220,7 @@ enum sort_type { · 219 unmodified lines | |||
| 220 | SORT_TRANSACTION, | 220 | SORT_TRANSACTION, |
| 221 | SORT_TRACE, | 221 | SORT_TRACE, |
| 222 | SORT_SYM_SIZE, | 222 | SORT_SYM_SIZE, |
| 223 | SORT_DSO_SIZE, | ||
| 223 | SORT_CGROUP_ID, | 224 | SORT_CGROUP_ID, |
| 224 | 225 | ||
| 225 | /* branch stack specific sort keys */ | 226 | /* branch stack specific sort keys */ |
| @@ -11,8 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <stdlib.h> | 11 | #include <stdlib.h> |
| 12 | #include <stdarg.h> | 12 | #include <stdarg.h> |
| 13 | #include <linux/compiler.h> | 13 | #include <linux/compiler.h> |
| 14 | #include <linux/types.h> | 14 | #include <sys/types.h> |
| 15 | #include "namespaces.h" | ||
| 16 | 15 | ||
| 17 | /* General helper functions */ | 16 | /* General helper functions */ |
| 18 | void usage(const char *err) __noreturn; | 17 | void usage(const char *err) __noreturn; |
| @@ -26,6 +25,7 @@ static inline void *zalloc(size_t size) · 7 unmodified lines | |||
| 26 | #define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) | 25 | #define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) |
| 27 | 26 | ||
| 28 | struct dirent; | 27 | struct dirent; |
| 28 | struct nsinfo; | ||
| 29 | struct strlist; | 29 | struct strlist; |
| 30 | 30 | ||
| 31 | int mkdir_p(char *path, mode_t mode); | 31 | int mkdir_p(char *path, mode_t mode); |