mirror of https://gitee.com/openkylin/linux.git
perf/core improvements and fixes:
- Record min/max LBR cycles (>= skylake) and add 'perf annotate' TUI hotkey to show it (c) (Jin Yao) - Fix machine->kernel_start for PTI on x86 (Adrian Hunter) - Make machine->env->arch always available, e.g. in 'perf top', not just when reading that info from perf.data files (Adrian Hunter) - Reduce the number of files read at 'perf' start, leaving information such as cacheline size, tracefs mount point determination, max_stack, etc, to be lazily read as tools needs then (Arnaldo Carvalho de Melo) - Fixup BPF include and examples install messages (Arnaldo Carvalho de Melo) - Fixup callchain addresses and symbol offsets in 'perf script', to help correlating with objdump output (Sandipan Das) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEELb9bqkb7Te0zijNb1lAW81NSqkAFAlsAAa4ACgkQ1lAW81NS qkAcag//UGyLeatnVTZhsNyFeVzS3a8nb//OWOKAYx70iWXTlriOXDjnF2UEmeoZ PMosDi2QksbiHoFiKRwYs8HlNbnUgCf+XqJfXY6wusQEyvlvm2TQzxclW9jgA6aU DuYJiaWFZdsJsEug2qKmBR6P0rE9JjB1m8frP6mpjqa0be39PbzEkMp7BamoEPoM FmLjARE4ob2Q56sq8BogjhjRsOkwqPbcJHRkH7EfOrjqRsqjvnjg4LAvf2qf7jXG aliPUCOhihxtP67uMo9i9D0D94M7zKdwvZHfweCi2atz9I7cF8rOdjtAzUpdCnhh YvmhBCmaEYfd2VLnSGHTcgSRZcuMO0+QDDECS2/MvYn8mzGSJLqPMLR9EGoYHcI5 0LWDxQHxHGBUBezcv4iq1YYaec9r+kFMXVFkC/v4v2CUisCfjLIbn0qC64FlK0hm dl60f5nZ/O7FHN2ObvNbtfSIHoKnb6/TIfASQHO3uCGlwF+EF2HpJ79h/vWcCY3S 0d4ENf4JrVZQxN7s9qly8XJ8jZkWQsVDVYu3EPyOKkVp/F7x6y2jO+ap1s3uSMjI g8lrNnhyeUQiTf/fnoascvrq1Opl3gLm/iJ92UOTV9fnCn4rFnt0TsZh9+yw9LsH o/m2mPo52ZBxcMDHSUQJ87SsP8CzOEq7JRiKuBJpA5L60nvql10= =RER4 -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo-4.18-20180519' 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: - Record min/max LBR cycles (>= Skylake) and add 'perf annotate' TUI hotkey to show it (c) (Jin Yao) - Fix machine->kernel_start for PTI on x86 (Adrian Hunter) - Make machine->env->arch always available, e.g. in 'perf top', not just when reading that info from perf.data files (Adrian Hunter) - Reduce the number of files read at 'perf' start, leaving information such as cacheline size, tracefs mount point determination, max_stack, etc, to be lazily read as tools needs then (Arnaldo Carvalho de Melo) - Fix up BPF include and examples install messages (Arnaldo Carvalho de Melo) - Fix up callchain addresses and symbol offsets in 'perf script', to help correlating with objdump output (Sandipan Das) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
2996123e7e
|
@ -21,6 +21,9 @@
|
|||
/* &a[0] degrades to a pointer: a different type from an array */
|
||||
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
|
||||
|
||||
#ifndef __pure
|
||||
#define __pure __attribute__((pure))
|
||||
#endif
|
||||
#define noinline __attribute__((noinline))
|
||||
#ifndef __packed
|
||||
#define __packed __attribute__((packed))
|
||||
|
|
|
@ -13,11 +13,9 @@
|
|||
|
||||
#include "tracing_path.h"
|
||||
|
||||
|
||||
char tracing_mnt[PATH_MAX] = "/sys/kernel/debug";
|
||||
char tracing_path[PATH_MAX] = "/sys/kernel/debug/tracing";
|
||||
char tracing_events_path[PATH_MAX] = "/sys/kernel/debug/tracing/events";
|
||||
|
||||
static char tracing_mnt[PATH_MAX] = "/sys/kernel/debug";
|
||||
static char tracing_path[PATH_MAX] = "/sys/kernel/debug/tracing";
|
||||
static char tracing_events_path[PATH_MAX] = "/sys/kernel/debug/tracing/events";
|
||||
|
||||
static void __tracing_path_set(const char *tracing, const char *mountpoint)
|
||||
{
|
||||
|
@ -76,7 +74,7 @@ char *get_tracing_file(const char *name)
|
|||
{
|
||||
char *file;
|
||||
|
||||
if (asprintf(&file, "%s/%s", tracing_path, name) < 0)
|
||||
if (asprintf(&file, "%s/%s", tracing_path_mount(), name) < 0)
|
||||
return NULL;
|
||||
|
||||
return file;
|
||||
|
@ -87,6 +85,34 @@ void put_tracing_file(char *file)
|
|||
free(file);
|
||||
}
|
||||
|
||||
char *get_events_file(const char *name)
|
||||
{
|
||||
char *file;
|
||||
|
||||
if (asprintf(&file, "%s/events/%s", tracing_path_mount(), name) < 0)
|
||||
return NULL;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
void put_events_file(char *file)
|
||||
{
|
||||
free(file);
|
||||
}
|
||||
|
||||
DIR *tracing_events__opendir(void)
|
||||
{
|
||||
DIR *dir = NULL;
|
||||
char *path = get_tracing_file("events");
|
||||
|
||||
if (path) {
|
||||
dir = opendir(path);
|
||||
put_events_file(path);
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
int tracing_path__strerror_open_tp(int err, char *buf, size_t size,
|
||||
const char *sys, const char *name)
|
||||
{
|
||||
|
@ -129,7 +155,7 @@ int tracing_path__strerror_open_tp(int err, char *buf, size_t size,
|
|||
snprintf(buf, size,
|
||||
"Error:\tNo permissions to read %s/%s\n"
|
||||
"Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
|
||||
tracing_events_path, filename, tracing_mnt);
|
||||
tracing_events_path, filename, tracing_path_mount());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
#define __API_FS_TRACING_PATH_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
extern char tracing_path[];
|
||||
extern char tracing_events_path[];
|
||||
DIR *tracing_events__opendir(void);
|
||||
|
||||
void tracing_path_set(const char *mountpoint);
|
||||
const char *tracing_path_mount(void);
|
||||
|
@ -13,5 +13,10 @@ const char *tracing_path_mount(void);
|
|||
char *get_tracing_file(const char *name);
|
||||
void put_tracing_file(char *file);
|
||||
|
||||
char *get_events_file(const char *name);
|
||||
void put_events_file(char *file);
|
||||
|
||||
#define zput_events_file(ptr) ({ free(*ptr); *ptr = NULL; })
|
||||
|
||||
int tracing_path__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name);
|
||||
#endif /* __API_FS_TRACING_PATH_H */
|
||||
|
|
|
@ -770,9 +770,11 @@ endif
|
|||
ifndef NO_LIBBPF
|
||||
$(call QUIET_INSTALL, lib) \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'
|
||||
$(call QUIET_INSTALL, include/bpf) \
|
||||
$(INSTALL) include/bpf/*.h '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'
|
||||
$(call QUIET_INSTALL, lib) \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
|
||||
$(call QUIET_INSTALL, examples/bpf) \
|
||||
$(INSTALL) examples/bpf/*.c '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
|
||||
endif
|
||||
$(call QUIET_INSTALL, perf-archive) \
|
||||
|
|
|
@ -153,8 +153,8 @@ static struct {
|
|||
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
|
||||
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
|
||||
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
|
||||
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
|
||||
PERF_OUTPUT_PERIOD,
|
||||
PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
|
||||
PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
|
||||
|
||||
.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
|
||||
},
|
||||
|
@ -165,8 +165,9 @@ static struct {
|
|||
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
|
||||
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
|
||||
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
|
||||
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
|
||||
PERF_OUTPUT_PERIOD | PERF_OUTPUT_BPF_OUTPUT,
|
||||
PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
|
||||
PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |
|
||||
PERF_OUTPUT_BPF_OUTPUT,
|
||||
|
||||
.invalid_fields = PERF_OUTPUT_TRACE,
|
||||
},
|
||||
|
@ -185,10 +186,10 @@ static struct {
|
|||
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
|
||||
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
|
||||
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
|
||||
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
|
||||
PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR |
|
||||
PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT |
|
||||
PERF_OUTPUT_PHYS_ADDR,
|
||||
PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
|
||||
PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |
|
||||
PERF_OUTPUT_ADDR | PERF_OUTPUT_DATA_SRC |
|
||||
PERF_OUTPUT_WEIGHT | PERF_OUTPUT_PHYS_ADDR,
|
||||
|
||||
.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
|
||||
},
|
||||
|
@ -199,8 +200,8 @@ static struct {
|
|||
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
|
||||
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
|
||||
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
|
||||
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
|
||||
PERF_OUTPUT_PERIOD,
|
||||
PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
|
||||
PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
|
||||
|
||||
.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
|
||||
},
|
||||
|
@ -211,8 +212,8 @@ static struct {
|
|||
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
|
||||
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
|
||||
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
|
||||
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
|
||||
PERF_OUTPUT_SYNTH,
|
||||
PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
|
||||
PERF_OUTPUT_DSO | PERF_OUTPUT_SYNTH,
|
||||
|
||||
.invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
|
||||
},
|
||||
|
@ -544,6 +545,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
|
|||
if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
|
||||
output[j].fields |= PERF_OUTPUT_IP;
|
||||
output[j].fields |= PERF_OUTPUT_SYM;
|
||||
output[j].fields |= PERF_OUTPUT_SYMOFFSET;
|
||||
output[j].fields |= PERF_OUTPUT_DSO;
|
||||
set_print_ip_opts(attr);
|
||||
goto out;
|
||||
|
|
|
@ -1264,7 +1264,7 @@ int cmd_top(int argc, const char **argv)
|
|||
.proc_map_timeout = 500,
|
||||
.overwrite = 1,
|
||||
},
|
||||
.max_stack = sysctl_perf_event_max_stack,
|
||||
.max_stack = sysctl__max_stack(),
|
||||
.sym_pcnt_filter = 5,
|
||||
.nr_threads_synthesize = UINT_MAX,
|
||||
};
|
||||
|
|
|
@ -3162,7 +3162,7 @@ int cmd_trace(int argc, const char **argv)
|
|||
mmap_pages_user_set = false;
|
||||
|
||||
if (trace.max_stack == UINT_MAX) {
|
||||
trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack;
|
||||
trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl__max_stack();
|
||||
max_stack_user_set = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
|
|||
(*argc)--;
|
||||
} else if (strstarts(cmd, CMD_DEBUGFS_DIR)) {
|
||||
tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
|
||||
fprintf(stderr, "dir: %s\n", tracing_path);
|
||||
fprintf(stderr, "dir: %s\n", tracing_path_mount());
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--list-cmds")) {
|
||||
|
@ -421,22 +421,11 @@ void pthread__unblock_sigwinch(void)
|
|||
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
||||
}
|
||||
|
||||
#ifdef _SC_LEVEL1_DCACHE_LINESIZE
|
||||
#define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
|
||||
#else
|
||||
static void cache_line_size(int *cacheline_sizep)
|
||||
{
|
||||
if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep))
|
||||
pr_debug("cannot determine cache line size");
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
int err;
|
||||
const char *cmd;
|
||||
char sbuf[STRERR_BUFSIZE];
|
||||
int value;
|
||||
|
||||
/* libsubcmd init */
|
||||
exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
|
||||
|
@ -444,13 +433,6 @@ int main(int argc, const char **argv)
|
|||
|
||||
/* The page_size is placed in util object. */
|
||||
page_size = sysconf(_SC_PAGE_SIZE);
|
||||
cache_line_size(&cacheline_size);
|
||||
|
||||
if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0)
|
||||
sysctl_perf_event_max_stack = value;
|
||||
|
||||
if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0)
|
||||
sysctl_perf_event_max_contexts_per_stack = value;
|
||||
|
||||
cmd = extract_argv0_path(argv[0]);
|
||||
if (!cmd)
|
||||
|
@ -458,15 +440,11 @@ int main(int argc, const char **argv)
|
|||
|
||||
srandom(time(NULL));
|
||||
|
||||
perf_config__init();
|
||||
err = perf_config(perf_default_config, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
set_buildid_dir(NULL);
|
||||
|
||||
/* get debugfs/tracefs mount point from /proc/mounts */
|
||||
tracing_path_mount();
|
||||
|
||||
/*
|
||||
* "perf-xxxx" is the same as "perf xxxx", but we obviously:
|
||||
*
|
||||
|
|
|
@ -1323,12 +1323,12 @@ static int count_tracepoints(void)
|
|||
DIR *events_dir;
|
||||
int cnt = 0;
|
||||
|
||||
events_dir = opendir(tracing_events_path);
|
||||
events_dir = tracing_events__opendir();
|
||||
|
||||
TEST_ASSERT_VAL("Can't open events dir", events_dir);
|
||||
|
||||
while ((events_ent = readdir(events_dir))) {
|
||||
char sys_path[PATH_MAX];
|
||||
char *sys_path;
|
||||
struct dirent *sys_ent;
|
||||
DIR *sys_dir;
|
||||
|
||||
|
@ -1339,8 +1339,8 @@ static int count_tracepoints(void)
|
|||
|| !strcmp(events_ent->d_name, "header_page"))
|
||||
continue;
|
||||
|
||||
scnprintf(sys_path, PATH_MAX, "%s/%s",
|
||||
tracing_events_path, events_ent->d_name);
|
||||
sys_path = get_events_file(events_ent->d_name);
|
||||
TEST_ASSERT_VAL("Can't get sys path", sys_path);
|
||||
|
||||
sys_dir = opendir(sys_path);
|
||||
TEST_ASSERT_VAL("Can't open sys dir", sys_dir);
|
||||
|
@ -1356,6 +1356,7 @@ static int count_tracepoints(void)
|
|||
}
|
||||
|
||||
closedir(sys_dir);
|
||||
put_events_file(sys_path);
|
||||
}
|
||||
|
||||
closedir(events_dir);
|
||||
|
|
|
@ -16,18 +16,18 @@ nm -g $libc 2>/dev/null | fgrep -q inet_pton || exit 254
|
|||
trace_libc_inet_pton_backtrace() {
|
||||
idx=0
|
||||
expected[0]="ping[][0-9 \.:]+probe_libc:inet_pton: \([[:xdigit:]]+\)"
|
||||
expected[1]=".*inet_pton[[:space:]]\($libc|inlined\)$"
|
||||
expected[1]=".*inet_pton\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$"
|
||||
case "$(uname -m)" in
|
||||
s390x)
|
||||
eventattr='call-graph=dwarf,max-stack=4'
|
||||
expected[2]="gaih_inet.*[[:space:]]\($libc|inlined\)$"
|
||||
expected[3]="(__GI_)?getaddrinfo[[:space:]]\($libc|inlined\)$"
|
||||
expected[4]="main[[:space:]]\(.*/bin/ping.*\)$"
|
||||
expected[2]="gaih_inet.*\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$"
|
||||
expected[3]="(__GI_)?getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$"
|
||||
expected[4]="main\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$"
|
||||
;;
|
||||
*)
|
||||
eventattr='max-stack=3'
|
||||
expected[2]="getaddrinfo[[:space:]]\($libc\)$"
|
||||
expected[3]=".*\(.*/bin/ping.*\)$"
|
||||
expected[2]="getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$"
|
||||
expected[3]=".*\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
|
@ -695,6 +695,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
|
|||
"O Bump offset level (jump targets -> +call -> all -> cycle thru)\n"
|
||||
"s Toggle source code view\n"
|
||||
"t Circulate percent, total period, samples view\n"
|
||||
"c Show min/max cycle\n"
|
||||
"/ Search string\n"
|
||||
"k Toggle line numbers\n"
|
||||
"P Print to [symbol_name].annotation file.\n"
|
||||
|
@ -791,6 +792,13 @@ static int annotate_browser__run(struct annotate_browser *browser,
|
|||
notes->options->show_total_period = true;
|
||||
annotation__update_column_widths(notes);
|
||||
continue;
|
||||
case 'c':
|
||||
if (notes->options->show_minmax_cycle)
|
||||
notes->options->show_minmax_cycle = false;
|
||||
else
|
||||
notes->options->show_minmax_cycle = true;
|
||||
annotation__update_column_widths(notes);
|
||||
continue;
|
||||
case K_LEFT:
|
||||
case K_ESC:
|
||||
case 'q':
|
||||
|
|
|
@ -760,6 +760,15 @@ static int __symbol__account_cycles(struct annotation *notes,
|
|||
ch[offset].num_aggr++;
|
||||
ch[offset].cycles_aggr += cycles;
|
||||
|
||||
if (cycles > ch[offset].cycles_max)
|
||||
ch[offset].cycles_max = cycles;
|
||||
|
||||
if (ch[offset].cycles_min) {
|
||||
if (cycles && cycles < ch[offset].cycles_min)
|
||||
ch[offset].cycles_min = cycles;
|
||||
} else
|
||||
ch[offset].cycles_min = cycles;
|
||||
|
||||
if (!have_start && ch[offset].have_start)
|
||||
return 0;
|
||||
if (ch[offset].num) {
|
||||
|
@ -953,8 +962,11 @@ void annotation__compute_ipc(struct annotation *notes, size_t size)
|
|||
if (ch->have_start)
|
||||
annotation__count_and_fill(notes, ch->start, offset, ch);
|
||||
al = notes->offsets[offset];
|
||||
if (al && ch->num_aggr)
|
||||
if (al && ch->num_aggr) {
|
||||
al->cycles = ch->cycles_aggr / ch->num_aggr;
|
||||
al->cycles_max = ch->cycles_max;
|
||||
al->cycles_min = ch->cycles_min;
|
||||
}
|
||||
notes->have_cycles = true;
|
||||
}
|
||||
}
|
||||
|
@ -2486,13 +2498,38 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
|
|||
else
|
||||
obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
|
||||
|
||||
if (al->cycles)
|
||||
obj__printf(obj, "%*" PRIu64 " ",
|
||||
if (!notes->options->show_minmax_cycle) {
|
||||
if (al->cycles)
|
||||
obj__printf(obj, "%*" PRIu64 " ",
|
||||
ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
|
||||
else if (!show_title)
|
||||
obj__printf(obj, "%*s", ANNOTATION__CYCLES_WIDTH, " ");
|
||||
else
|
||||
obj__printf(obj, "%*s ", ANNOTATION__CYCLES_WIDTH - 1, "Cycle");
|
||||
else if (!show_title)
|
||||
obj__printf(obj, "%*s",
|
||||
ANNOTATION__CYCLES_WIDTH, " ");
|
||||
else
|
||||
obj__printf(obj, "%*s ",
|
||||
ANNOTATION__CYCLES_WIDTH - 1,
|
||||
"Cycle");
|
||||
} else {
|
||||
if (al->cycles) {
|
||||
char str[32];
|
||||
|
||||
scnprintf(str, sizeof(str),
|
||||
"%" PRIu64 "(%" PRIu64 "/%" PRIu64 ")",
|
||||
al->cycles, al->cycles_min,
|
||||
al->cycles_max);
|
||||
|
||||
obj__printf(obj, "%*s ",
|
||||
ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
|
||||
str);
|
||||
} else if (!show_title)
|
||||
obj__printf(obj, "%*s",
|
||||
ANNOTATION__MINMAX_CYCLES_WIDTH,
|
||||
" ");
|
||||
else
|
||||
obj__printf(obj, "%*s ",
|
||||
ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
|
||||
"Cycle(min/max)");
|
||||
}
|
||||
}
|
||||
|
||||
obj__printf(obj, " ");
|
||||
|
|
|
@ -61,6 +61,7 @@ bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
|
|||
|
||||
#define ANNOTATION__IPC_WIDTH 6
|
||||
#define ANNOTATION__CYCLES_WIDTH 6
|
||||
#define ANNOTATION__MINMAX_CYCLES_WIDTH 19
|
||||
|
||||
struct annotation_options {
|
||||
bool hide_src_code,
|
||||
|
@ -69,7 +70,8 @@ struct annotation_options {
|
|||
show_linenr,
|
||||
show_nr_jumps,
|
||||
show_nr_samples,
|
||||
show_total_period;
|
||||
show_total_period,
|
||||
show_minmax_cycle;
|
||||
u8 offset_level;
|
||||
};
|
||||
|
||||
|
@ -105,6 +107,8 @@ struct annotation_line {
|
|||
int jump_sources;
|
||||
float ipc;
|
||||
u64 cycles;
|
||||
u64 cycles_max;
|
||||
u64 cycles_min;
|
||||
size_t privsize;
|
||||
char *path;
|
||||
u32 idx;
|
||||
|
@ -186,6 +190,8 @@ struct cyc_hist {
|
|||
u64 start;
|
||||
u64 cycles;
|
||||
u64 cycles_aggr;
|
||||
u64 cycles_max;
|
||||
u64 cycles_min;
|
||||
u32 num;
|
||||
u32 num_aggr;
|
||||
u8 have_start;
|
||||
|
@ -239,6 +245,9 @@ struct annotation {
|
|||
|
||||
static inline int annotation__cycles_width(struct annotation *notes)
|
||||
{
|
||||
if (notes->have_cycles && notes->options->show_minmax_cycle)
|
||||
return ANNOTATION__IPC_WIDTH + ANNOTATION__MINMAX_CYCLES_WIDTH;
|
||||
|
||||
return notes->have_cycles ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -707,6 +707,14 @@ struct perf_config_set *perf_config_set__new(void)
|
|||
return set;
|
||||
}
|
||||
|
||||
static int perf_config__init(void)
|
||||
{
|
||||
if (config_set == NULL)
|
||||
config_set = perf_config_set__new();
|
||||
|
||||
return config_set == NULL;
|
||||
}
|
||||
|
||||
int perf_config(config_fn_t fn, void *data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
@ -714,7 +722,7 @@ int perf_config(config_fn_t fn, void *data)
|
|||
struct perf_config_section *section;
|
||||
struct perf_config_item *item;
|
||||
|
||||
if (config_set == NULL)
|
||||
if (config_set == NULL && perf_config__init())
|
||||
return -1;
|
||||
|
||||
perf_config_set__for_each_entry(config_set, section, item) {
|
||||
|
@ -735,12 +743,6 @@ int perf_config(config_fn_t fn, void *data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void perf_config__init(void)
|
||||
{
|
||||
if (config_set == NULL)
|
||||
config_set = perf_config_set__new();
|
||||
}
|
||||
|
||||
void perf_config__exit(void)
|
||||
{
|
||||
perf_config_set__delete(config_set);
|
||||
|
|
|
@ -38,7 +38,6 @@ struct perf_config_set *perf_config_set__new(void);
|
|||
void perf_config_set__delete(struct perf_config_set *set);
|
||||
int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
|
||||
const char *var, const char *value);
|
||||
void perf_config__init(void);
|
||||
void perf_config__exit(void);
|
||||
void perf_config__refresh(void);
|
||||
|
||||
|
|
|
@ -93,6 +93,24 @@ int perf_env__read_cpu_topology_map(struct perf_env *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int perf_env__read_arch(struct perf_env *env)
|
||||
{
|
||||
struct utsname uts;
|
||||
|
||||
if (env->arch)
|
||||
return 0;
|
||||
|
||||
if (!uname(&uts))
|
||||
env->arch = strdup(uts.machine);
|
||||
|
||||
return env->arch ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
const char *perf_env__raw_arch(struct perf_env *env)
|
||||
{
|
||||
return env && !perf_env__read_arch(env) ? env->arch : "unknown";
|
||||
}
|
||||
|
||||
void cpu_cache_level__free(struct cpu_cache_level *cache)
|
||||
{
|
||||
free(cache->type);
|
||||
|
|
|
@ -76,4 +76,6 @@ int perf_env__read_cpu_topology_map(struct perf_env *env);
|
|||
void cpu_cache_level__free(struct cpu_cache_level *cache);
|
||||
|
||||
const char *perf_env__arch(struct perf_env *env);
|
||||
const char *perf_env__raw_arch(struct perf_env *env);
|
||||
|
||||
#endif /* __PERF_ENV_H */
|
||||
|
|
|
@ -2862,7 +2862,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
|
|||
return scnprintf(msg, size,
|
||||
"Not enough memory to setup event with callchain.\n"
|
||||
"Hint: Try tweaking /proc/sys/kernel/perf_event_max_stack\n"
|
||||
"Hint: Current value: %d", sysctl_perf_event_max_stack);
|
||||
"Hint: Current value: %d", sysctl__max_stack());
|
||||
break;
|
||||
case ENODEV:
|
||||
if (target->cpu_list)
|
||||
|
|
|
@ -1764,7 +1764,7 @@ static int add_callchain_ip(struct thread *thread,
|
|||
}
|
||||
|
||||
srcline = callchain_srcline(al.map, al.sym, al.addr);
|
||||
return callchain_cursor_append(cursor, al.addr, al.map, al.sym,
|
||||
return callchain_cursor_append(cursor, ip, al.map, al.sym,
|
||||
branch, flags, nr_loop_iter,
|
||||
iter_cycles, branch_from, srcline);
|
||||
}
|
||||
|
@ -2296,6 +2296,15 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compares the raw arch string. N.B. see instead perf_env__arch() if a
|
||||
* normalized arch is needed.
|
||||
*/
|
||||
bool machine__is(struct machine *machine, const char *arch)
|
||||
{
|
||||
return machine && !strcmp(perf_env__raw_arch(machine->env), arch);
|
||||
}
|
||||
|
||||
int machine__get_kernel_start(struct machine *machine)
|
||||
{
|
||||
struct map *map = machine__kernel_map(machine);
|
||||
|
@ -2312,7 +2321,12 @@ int machine__get_kernel_start(struct machine *machine)
|
|||
machine->kernel_start = 1ULL << 63;
|
||||
if (map) {
|
||||
err = map__load(map);
|
||||
if (!err)
|
||||
/*
|
||||
* On x86_64, PTI entry trampolines are less than the
|
||||
* start of kernel text, but still above 2^63. So leave
|
||||
* kernel_start = 1ULL << 63 for x86_64.
|
||||
*/
|
||||
if (!err && !machine__is(machine, "x86_64"))
|
||||
machine->kernel_start = map->start;
|
||||
}
|
||||
return err;
|
||||
|
|
|
@ -188,6 +188,8 @@ static inline bool machine__is_host(struct machine *machine)
|
|||
return machine ? machine->pid == HOST_KERNEL_ID : false;
|
||||
}
|
||||
|
||||
bool machine__is(struct machine *machine, const char *arch);
|
||||
|
||||
struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid);
|
||||
struct thread *machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid);
|
||||
|
||||
|
|
|
@ -156,13 +156,12 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
|
|||
(strcmp(sys_dirent->d_name, ".")) && \
|
||||
(strcmp(sys_dirent->d_name, "..")))
|
||||
|
||||
static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
|
||||
static int tp_event_has_id(const char *dir_path, struct dirent *evt_dir)
|
||||
{
|
||||
char evt_path[MAXPATHLEN];
|
||||
int fd;
|
||||
|
||||
snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
|
||||
sys_dir->d_name, evt_dir->d_name);
|
||||
snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, evt_dir->d_name);
|
||||
fd = open(evt_path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -EINVAL;
|
||||
|
@ -171,12 +170,12 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define for_each_event(sys_dirent, evt_dir, evt_dirent) \
|
||||
#define for_each_event(dir_path, evt_dir, evt_dirent) \
|
||||
while ((evt_dirent = readdir(evt_dir)) != NULL) \
|
||||
if (evt_dirent->d_type == DT_DIR && \
|
||||
(strcmp(evt_dirent->d_name, ".")) && \
|
||||
(strcmp(evt_dirent->d_name, "..")) && \
|
||||
(!tp_event_has_id(sys_dirent, evt_dirent)))
|
||||
(!tp_event_has_id(dir_path, evt_dirent)))
|
||||
|
||||
#define MAX_EVENT_LENGTH 512
|
||||
|
||||
|
@ -190,21 +189,21 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
|
|||
int fd;
|
||||
u64 id;
|
||||
char evt_path[MAXPATHLEN];
|
||||
char dir_path[MAXPATHLEN];
|
||||
char *dir_path;
|
||||
|
||||
sys_dir = opendir(tracing_events_path);
|
||||
sys_dir = tracing_events__opendir();
|
||||
if (!sys_dir)
|
||||
return NULL;
|
||||
|
||||
for_each_subsystem(sys_dir, sys_dirent) {
|
||||
|
||||
snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
|
||||
sys_dirent->d_name);
|
||||
dir_path = get_events_file(sys_dirent->d_name);
|
||||
if (!dir_path)
|
||||
continue;
|
||||
evt_dir = opendir(dir_path);
|
||||
if (!evt_dir)
|
||||
continue;
|
||||
goto next;
|
||||
|
||||
for_each_event(sys_dirent, evt_dir, evt_dirent) {
|
||||
for_each_event(dir_path, evt_dir, evt_dirent) {
|
||||
|
||||
scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
|
||||
evt_dirent->d_name);
|
||||
|
@ -218,6 +217,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
|
|||
close(fd);
|
||||
id = atoll(id_buf);
|
||||
if (id == config) {
|
||||
put_events_file(dir_path);
|
||||
closedir(evt_dir);
|
||||
closedir(sys_dir);
|
||||
path = zalloc(sizeof(*path));
|
||||
|
@ -242,6 +242,8 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
|
|||
}
|
||||
}
|
||||
closedir(evt_dir);
|
||||
next:
|
||||
put_events_file(dir_path);
|
||||
}
|
||||
|
||||
closedir(sys_dir);
|
||||
|
@ -512,14 +514,19 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
|
|||
struct parse_events_error *err,
|
||||
struct list_head *head_config)
|
||||
{
|
||||
char evt_path[MAXPATHLEN];
|
||||
char *evt_path;
|
||||
struct dirent *evt_ent;
|
||||
DIR *evt_dir;
|
||||
int ret = 0, found = 0;
|
||||
|
||||
snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
|
||||
evt_path = get_events_file(sys_name);
|
||||
if (!evt_path) {
|
||||
tracepoint_error(err, errno, sys_name, evt_name);
|
||||
return -1;
|
||||
}
|
||||
evt_dir = opendir(evt_path);
|
||||
if (!evt_dir) {
|
||||
put_events_file(evt_path);
|
||||
tracepoint_error(err, errno, sys_name, evt_name);
|
||||
return -1;
|
||||
}
|
||||
|
@ -545,6 +552,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
|
|||
ret = -1;
|
||||
}
|
||||
|
||||
put_events_file(evt_path);
|
||||
closedir(evt_dir);
|
||||
return ret;
|
||||
}
|
||||
|
@ -570,7 +578,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
|
|||
DIR *events_dir;
|
||||
int ret = 0;
|
||||
|
||||
events_dir = opendir(tracing_events_path);
|
||||
events_dir = tracing_events__opendir();
|
||||
if (!events_dir) {
|
||||
tracepoint_error(err, errno, sys_name, evt_name);
|
||||
return -1;
|
||||
|
@ -2092,13 +2100,13 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
|
|||
DIR *sys_dir, *evt_dir;
|
||||
struct dirent *sys_dirent, *evt_dirent;
|
||||
char evt_path[MAXPATHLEN];
|
||||
char dir_path[MAXPATHLEN];
|
||||
char *dir_path;
|
||||
char **evt_list = NULL;
|
||||
unsigned int evt_i = 0, evt_num = 0;
|
||||
bool evt_num_known = false;
|
||||
|
||||
restart:
|
||||
sys_dir = opendir(tracing_events_path);
|
||||
sys_dir = tracing_events__opendir();
|
||||
if (!sys_dir)
|
||||
return;
|
||||
|
||||
|
@ -2113,13 +2121,14 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
|
|||
!strglobmatch(sys_dirent->d_name, subsys_glob))
|
||||
continue;
|
||||
|
||||
snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
|
||||
sys_dirent->d_name);
|
||||
dir_path = get_events_file(sys_dirent->d_name);
|
||||
if (!dir_path)
|
||||
continue;
|
||||
evt_dir = opendir(dir_path);
|
||||
if (!evt_dir)
|
||||
continue;
|
||||
goto next;
|
||||
|
||||
for_each_event(sys_dirent, evt_dir, evt_dirent) {
|
||||
for_each_event(dir_path, evt_dir, evt_dirent) {
|
||||
if (event_glob != NULL &&
|
||||
!strglobmatch(evt_dirent->d_name, event_glob))
|
||||
continue;
|
||||
|
@ -2133,11 +2142,15 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
|
|||
sys_dirent->d_name, evt_dirent->d_name);
|
||||
|
||||
evt_list[evt_i] = strdup(evt_path);
|
||||
if (evt_list[evt_i] == NULL)
|
||||
if (evt_list[evt_i] == NULL) {
|
||||
put_events_file(dir_path);
|
||||
goto out_close_evt_dir;
|
||||
}
|
||||
evt_i++;
|
||||
}
|
||||
closedir(evt_dir);
|
||||
next:
|
||||
put_events_file(dir_path);
|
||||
}
|
||||
closedir(sys_dir);
|
||||
|
||||
|
@ -2185,21 +2198,21 @@ int is_valid_tracepoint(const char *event_string)
|
|||
DIR *sys_dir, *evt_dir;
|
||||
struct dirent *sys_dirent, *evt_dirent;
|
||||
char evt_path[MAXPATHLEN];
|
||||
char dir_path[MAXPATHLEN];
|
||||
char *dir_path;
|
||||
|
||||
sys_dir = opendir(tracing_events_path);
|
||||
sys_dir = tracing_events__opendir();
|
||||
if (!sys_dir)
|
||||
return 0;
|
||||
|
||||
for_each_subsystem(sys_dir, sys_dirent) {
|
||||
|
||||
snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
|
||||
sys_dirent->d_name);
|
||||
dir_path = get_events_file(sys_dirent->d_name);
|
||||
if (!dir_path)
|
||||
continue;
|
||||
evt_dir = opendir(dir_path);
|
||||
if (!evt_dir)
|
||||
continue;
|
||||
goto next;
|
||||
|
||||
for_each_event(sys_dirent, evt_dir, evt_dirent) {
|
||||
for_each_event(dir_path, evt_dir, evt_dirent) {
|
||||
snprintf(evt_path, MAXPATHLEN, "%s:%s",
|
||||
sys_dirent->d_name, evt_dirent->d_name);
|
||||
if (!strcmp(evt_path, event_string)) {
|
||||
|
@ -2209,6 +2222,8 @@ int is_valid_tracepoint(const char *event_string)
|
|||
}
|
||||
}
|
||||
closedir(evt_dir);
|
||||
next:
|
||||
put_events_file(dir_path);
|
||||
}
|
||||
closedir(sys_dir);
|
||||
return 0;
|
||||
|
|
|
@ -84,8 +84,7 @@ int open_trace_file(const char *trace_file, bool readwrite)
|
|||
char buf[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
ret = e_snprintf(buf, PATH_MAX, "%s/%s",
|
||||
tracing_path, trace_file);
|
||||
ret = e_snprintf(buf, PATH_MAX, "%s/%s", tracing_path_mount(), trace_file);
|
||||
if (ret >= 0) {
|
||||
pr_debug("Opening %s write=%d\n", buf, readwrite);
|
||||
if (readwrite && !probe_event_dry_run)
|
||||
|
|
|
@ -2582,7 +2582,7 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
|
|||
if (sort__mode != SORT_MODE__MEMORY)
|
||||
return -EINVAL;
|
||||
|
||||
if (sd->entry == &sort_mem_dcacheline && cacheline_size == 0)
|
||||
if (sd->entry == &sort_mem_dcacheline && cacheline_size() == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (sd->entry == &sort_mem_daddr_sym)
|
||||
|
@ -2628,7 +2628,7 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
|
|||
if (*tok) {
|
||||
ret = sort_dimension__add(list, tok, evlist, level);
|
||||
if (ret == -EINVAL) {
|
||||
if (!cacheline_size && !strncasecmp(tok, "dcacheline", strlen(tok)))
|
||||
if (!cacheline_size() && !strncasecmp(tok, "dcacheline", strlen(tok)))
|
||||
pr_err("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
|
||||
else
|
||||
pr_err("Invalid --sort key: `%s'", tok);
|
||||
|
|
|
@ -186,13 +186,13 @@ static inline float hist_entry__get_percent_limit(struct hist_entry *he)
|
|||
static inline u64 cl_address(u64 address)
|
||||
{
|
||||
/* return the cacheline of the address */
|
||||
return (address & ~(cacheline_size - 1));
|
||||
return (address & ~(cacheline_size() - 1));
|
||||
}
|
||||
|
||||
static inline u64 cl_offset(u64 address)
|
||||
{
|
||||
/* return the cacheline of the address */
|
||||
return (address & (cacheline_size - 1));
|
||||
return (address & (cacheline_size() - 1));
|
||||
}
|
||||
|
||||
enum sort_mode {
|
||||
|
|
|
@ -103,11 +103,10 @@ static int record_file(const char *file, ssize_t hdr_sz)
|
|||
|
||||
static int record_header_files(void)
|
||||
{
|
||||
char *path;
|
||||
char *path = get_events_file("header_page");
|
||||
struct stat st;
|
||||
int err = -EIO;
|
||||
|
||||
path = get_tracing_file("events/header_page");
|
||||
if (!path) {
|
||||
pr_debug("can't get tracing/events/header_page");
|
||||
return -ENOMEM;
|
||||
|
@ -128,9 +127,9 @@ static int record_header_files(void)
|
|||
goto out;
|
||||
}
|
||||
|
||||
put_tracing_file(path);
|
||||
put_events_file(path);
|
||||
|
||||
path = get_tracing_file("events/header_event");
|
||||
path = get_events_file("header_event");
|
||||
if (!path) {
|
||||
pr_debug("can't get tracing/events/header_event");
|
||||
err = -ENOMEM;
|
||||
|
@ -154,7 +153,7 @@ static int record_header_files(void)
|
|||
|
||||
err = 0;
|
||||
out:
|
||||
put_tracing_file(path);
|
||||
put_events_file(path);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -243,7 +242,7 @@ static int record_ftrace_files(struct tracepoint_path *tps)
|
|||
char *path;
|
||||
int ret;
|
||||
|
||||
path = get_tracing_file("events/ftrace");
|
||||
path = get_events_file("ftrace");
|
||||
if (!path) {
|
||||
pr_debug("can't get tracing/events/ftrace");
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -75,6 +75,7 @@ void trace_event__cleanup(struct trace_event *t)
|
|||
static struct event_format*
|
||||
tp_format(const char *sys, const char *name)
|
||||
{
|
||||
char *tp_dir = get_events_file(sys);
|
||||
struct pevent *pevent = tevent.pevent;
|
||||
struct event_format *event = NULL;
|
||||
char path[PATH_MAX];
|
||||
|
@ -82,8 +83,11 @@ tp_format(const char *sys, const char *name)
|
|||
char *data;
|
||||
int err;
|
||||
|
||||
scnprintf(path, PATH_MAX, "%s/%s/%s/format",
|
||||
tracing_events_path, sys, name);
|
||||
if (!tp_dir)
|
||||
return ERR_PTR(-errno);
|
||||
|
||||
scnprintf(path, PATH_MAX, "%s/%s/format", tp_dir, name);
|
||||
put_events_file(tp_dir);
|
||||
|
||||
err = filename__read_str(path, &data, &size);
|
||||
if (err)
|
||||
|
|
|
@ -38,11 +38,43 @@ void perf_set_multithreaded(void)
|
|||
}
|
||||
|
||||
unsigned int page_size;
|
||||
int cacheline_size;
|
||||
|
||||
#ifdef _SC_LEVEL1_DCACHE_LINESIZE
|
||||
#define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
|
||||
#else
|
||||
static void cache_line_size(int *cacheline_sizep)
|
||||
{
|
||||
if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep))
|
||||
pr_debug("cannot determine cache line size");
|
||||
}
|
||||
#endif
|
||||
|
||||
int cacheline_size(void)
|
||||
{
|
||||
static int size;
|
||||
|
||||
if (!size)
|
||||
cache_line_size(&size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
|
||||
int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK;
|
||||
|
||||
int sysctl__max_stack(void)
|
||||
{
|
||||
int value;
|
||||
|
||||
if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0)
|
||||
sysctl_perf_event_max_stack = value;
|
||||
|
||||
if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0)
|
||||
sysctl_perf_event_max_contexts_per_stack = value;
|
||||
|
||||
return sysctl_perf_event_max_stack;
|
||||
}
|
||||
|
||||
bool test_attr__enabled;
|
||||
|
||||
bool perf_host = true;
|
||||
|
|
|
@ -43,7 +43,9 @@ size_t hex_width(u64 v);
|
|||
int hex2u64(const char *ptr, u64 *val);
|
||||
|
||||
extern unsigned int page_size;
|
||||
extern int cacheline_size;
|
||||
int __pure cacheline_size(void);
|
||||
|
||||
int sysctl__max_stack(void);
|
||||
|
||||
int fetch_kernel_version(unsigned int *puint,
|
||||
char *str, size_t str_sz);
|
||||
|
|
Loading…
Reference in New Issue