From 0a4e1ae6808a28a92573550603121b146b11312e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:41 +0100 Subject: perf tests: Move test__vmlinux_matches_kallsyms into separate object Separating test__vmlinux_matches_kallsyms test from the builtin-test into vmlinux-kallsyms object. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-2-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index cca5bb8..7c7ba4d 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -431,6 +431,7 @@ LIB_OBJS += $(OUTPUT)arch/common.o LIB_OBJS += $(OUTPUT)tests/parse-events.o LIB_OBJS += $(OUTPUT)tests/dso-data.o LIB_OBJS += $(OUTPUT)tests/attr.o +LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 5d4354e..5bc9063 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -21,231 +21,12 @@ #include -static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused, - struct symbol *sym) -{ - bool *visited = symbol__priv(sym); - *visited = true; - return 0; -} - -static int test__vmlinux_matches_kallsyms(void) -{ - int err = -1; - struct rb_node *nd; - struct symbol *sym; - struct map *kallsyms_map, *vmlinux_map; - struct machine kallsyms, vmlinux; - enum map_type type = MAP__FUNCTION; - struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", }; - - /* - * Step 1: - * - * Init the machines that will hold kernel, modules obtained from - * both vmlinux + .ko files and from /proc/kallsyms split by modules. - */ - machine__init(&kallsyms, "", HOST_KERNEL_ID); - machine__init(&vmlinux, "", HOST_KERNEL_ID); - - /* - * Step 2: - * - * Create the kernel maps for kallsyms and the DSO where we will then - * load /proc/kallsyms. Also create the modules maps from /proc/modules - * and find the .ko files that match them in /lib/modules/`uname -r`/. - */ - if (machine__create_kernel_maps(&kallsyms) < 0) { - pr_debug("machine__create_kernel_maps "); - return -1; - } - - /* - * Step 3: - * - * Load and split /proc/kallsyms into multiple maps, one per module. - */ - if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) { - pr_debug("dso__load_kallsyms "); - goto out; - } - - /* - * Step 4: - * - * kallsyms will be internally on demand sorted by name so that we can - * find the reference relocation * symbol, i.e. the symbol we will use - * to see if the running kernel was relocated by checking if it has the - * same value in the vmlinux file we load. - */ - kallsyms_map = machine__kernel_map(&kallsyms, type); - - sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL); - if (sym == NULL) { - pr_debug("dso__find_symbol_by_name "); - goto out; - } - - ref_reloc_sym.addr = sym->start; - - /* - * Step 5: - * - * Now repeat step 2, this time for the vmlinux file we'll auto-locate. - */ - if (machine__create_kernel_maps(&vmlinux) < 0) { - pr_debug("machine__create_kernel_maps "); - goto out; - } - - vmlinux_map = machine__kernel_map(&vmlinux, type); - map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym; - - /* - * Step 6: - * - * Locate a vmlinux file in the vmlinux path that has a buildid that - * matches the one of the running kernel. - * - * While doing that look if we find the ref reloc symbol, if we find it - * we'll have its ref_reloc_symbol.unrelocated_addr and then - * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines - * to fixup the symbols. - */ - if (machine__load_vmlinux_path(&vmlinux, type, - vmlinux_matches_kallsyms_filter) <= 0) { - pr_debug("machine__load_vmlinux_path "); - goto out; - } - - err = 0; - /* - * Step 7: - * - * Now look at the symbols in the vmlinux DSO and check if we find all of them - * in the kallsyms dso. For the ones that are in both, check its names and - * end addresses too. - */ - for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) { - struct symbol *pair, *first_pair; - bool backwards = true; - - sym = rb_entry(nd, struct symbol, rb_node); - - if (sym->start == sym->end) - continue; - - first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL); - pair = first_pair; - - if (pair && pair->start == sym->start) { -next_pair: - if (strcmp(sym->name, pair->name) == 0) { - /* - * kallsyms don't have the symbol end, so we - * set that by using the next symbol start - 1, - * in some cases we get this up to a page - * wrong, trace_kmalloc when I was developing - * this code was one such example, 2106 bytes - * off the real size. More than that and we - * _really_ have a problem. - */ - s64 skew = sym->end - pair->end; - if (llabs(skew) < page_size) - continue; - - pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n", - sym->start, sym->name, sym->end, pair->end); - } else { - struct rb_node *nnd; -detour: - nnd = backwards ? rb_prev(&pair->rb_node) : - rb_next(&pair->rb_node); - if (nnd) { - struct symbol *next = rb_entry(nnd, struct symbol, rb_node); - - if (next->start == sym->start) { - pair = next; - goto next_pair; - } - } - - if (backwards) { - backwards = false; - pair = first_pair; - goto detour; - } - - pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", - sym->start, sym->name, pair->name); - } - } else - pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name); - - err = -1; - } - - if (!verbose) - goto out; - - pr_info("Maps only in vmlinux:\n"); - - for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { - struct map *pos = rb_entry(nd, struct map, rb_node), *pair; - /* - * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while - * the kernel will have the path for the vmlinux file being used, - * so use the short name, less descriptive but the same ("[kernel]" in - * both cases. - */ - pair = map_groups__find_by_name(&kallsyms.kmaps, type, - (pos->dso->kernel ? - pos->dso->short_name : - pos->dso->name)); - if (pair) - pair->priv = 1; - else - map__fprintf(pos, stderr); - } - - pr_info("Maps in vmlinux with a different name in kallsyms:\n"); - - for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { - struct map *pos = rb_entry(nd, struct map, rb_node), *pair; - - pair = map_groups__find(&kallsyms.kmaps, type, pos->start); - if (pair == NULL || pair->priv) - continue; - - if (pair->start == pos->start) { - pair->priv = 1; - pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", - pos->start, pos->end, pos->pgoff, pos->dso->name); - if (pos->pgoff != pair->pgoff || pos->end != pair->end) - pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "", - pair->start, pair->end, pair->pgoff); - pr_info(" %s\n", pair->dso->name); - pair->priv = 1; - } - } - - pr_info("Maps only in kallsyms:\n"); - - for (nd = rb_first(&kallsyms.kmaps.maps[type]); - nd; nd = rb_next(nd)) { - struct map *pos = rb_entry(nd, struct map, rb_node); - - if (!pos->priv) - map__fprintf(pos, stderr); - } -out: - return err; -} - #include "util/cpumap.h" #include "util/evsel.h" #include +#include "tests.h" + static int trace_event__id(const char *evname) { char *filename; diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h new file mode 100644 index 0000000..2223de5 --- /dev/null +++ b/tools/perf/tests/tests.h @@ -0,0 +1,6 @@ +#ifndef TESTS_H +#define TESTS_H + +int test__vmlinux_matches_kallsyms(void); + +#endif /* TESTS_H */ diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c new file mode 100644 index 0000000..0d1cdbe --- /dev/null +++ b/tools/perf/tests/vmlinux-kallsyms.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include "map.h" +#include "symbol.h" +#include "util.h" +#include "tests.h" +#include "debug.h" +#include "machine.h" + +static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused, + struct symbol *sym) +{ + bool *visited = symbol__priv(sym); + *visited = true; + return 0; +} + +int test__vmlinux_matches_kallsyms(void) +{ + int err = -1; + struct rb_node *nd; + struct symbol *sym; + struct map *kallsyms_map, *vmlinux_map; + struct machine kallsyms, vmlinux; + enum map_type type = MAP__FUNCTION; + struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", }; + + /* + * Step 1: + * + * Init the machines that will hold kernel, modules obtained from + * both vmlinux + .ko files and from /proc/kallsyms split by modules. + */ + machine__init(&kallsyms, "", HOST_KERNEL_ID); + machine__init(&vmlinux, "", HOST_KERNEL_ID); + + /* + * Step 2: + * + * Create the kernel maps for kallsyms and the DSO where we will then + * load /proc/kallsyms. Also create the modules maps from /proc/modules + * and find the .ko files that match them in /lib/modules/`uname -r`/. + */ + if (machine__create_kernel_maps(&kallsyms) < 0) { + pr_debug("machine__create_kernel_maps "); + return -1; + } + + /* + * Step 3: + * + * Load and split /proc/kallsyms into multiple maps, one per module. + */ + if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) { + pr_debug("dso__load_kallsyms "); + goto out; + } + + /* + * Step 4: + * + * kallsyms will be internally on demand sorted by name so that we can + * find the reference relocation * symbol, i.e. the symbol we will use + * to see if the running kernel was relocated by checking if it has the + * same value in the vmlinux file we load. + */ + kallsyms_map = machine__kernel_map(&kallsyms, type); + + sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL); + if (sym == NULL) { + pr_debug("dso__find_symbol_by_name "); + goto out; + } + + ref_reloc_sym.addr = sym->start; + + /* + * Step 5: + * + * Now repeat step 2, this time for the vmlinux file we'll auto-locate. + */ + if (machine__create_kernel_maps(&vmlinux) < 0) { + pr_debug("machine__create_kernel_maps "); + goto out; + } + + vmlinux_map = machine__kernel_map(&vmlinux, type); + map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym; + + /* + * Step 6: + * + * Locate a vmlinux file in the vmlinux path that has a buildid that + * matches the one of the running kernel. + * + * While doing that look if we find the ref reloc symbol, if we find it + * we'll have its ref_reloc_symbol.unrelocated_addr and then + * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines + * to fixup the symbols. + */ + if (machine__load_vmlinux_path(&vmlinux, type, + vmlinux_matches_kallsyms_filter) <= 0) { + pr_debug("machine__load_vmlinux_path "); + goto out; + } + + err = 0; + /* + * Step 7: + * + * Now look at the symbols in the vmlinux DSO and check if we find all of them + * in the kallsyms dso. For the ones that are in both, check its names and + * end addresses too. + */ + for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) { + struct symbol *pair, *first_pair; + bool backwards = true; + + sym = rb_entry(nd, struct symbol, rb_node); + + if (sym->start == sym->end) + continue; + + first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL); + pair = first_pair; + + if (pair && pair->start == sym->start) { +next_pair: + if (strcmp(sym->name, pair->name) == 0) { + /* + * kallsyms don't have the symbol end, so we + * set that by using the next symbol start - 1, + * in some cases we get this up to a page + * wrong, trace_kmalloc when I was developing + * this code was one such example, 2106 bytes + * off the real size. More than that and we + * _really_ have a problem. + */ + s64 skew = sym->end - pair->end; + if (llabs(skew) < page_size) + continue; + + pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n", + sym->start, sym->name, sym->end, pair->end); + } else { + struct rb_node *nnd; +detour: + nnd = backwards ? rb_prev(&pair->rb_node) : + rb_next(&pair->rb_node); + if (nnd) { + struct symbol *next = rb_entry(nnd, struct symbol, rb_node); + + if (next->start == sym->start) { + pair = next; + goto next_pair; + } + } + + if (backwards) { + backwards = false; + pair = first_pair; + goto detour; + } + + pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", + sym->start, sym->name, pair->name); + } + } else + pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name); + + err = -1; + } + + if (!verbose) + goto out; + + pr_info("Maps only in vmlinux:\n"); + + for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node), *pair; + /* + * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while + * the kernel will have the path for the vmlinux file being used, + * so use the short name, less descriptive but the same ("[kernel]" in + * both cases. + */ + pair = map_groups__find_by_name(&kallsyms.kmaps, type, + (pos->dso->kernel ? + pos->dso->short_name : + pos->dso->name)); + if (pair) + pair->priv = 1; + else + map__fprintf(pos, stderr); + } + + pr_info("Maps in vmlinux with a different name in kallsyms:\n"); + + for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node), *pair; + + pair = map_groups__find(&kallsyms.kmaps, type, pos->start); + if (pair == NULL || pair->priv) + continue; + + if (pair->start == pos->start) { + pair->priv = 1; + pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", + pos->start, pos->end, pos->pgoff, pos->dso->name); + if (pos->pgoff != pair->pgoff || pos->end != pair->end) + pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "", + pair->start, pair->end, pair->pgoff); + pr_info(" %s\n", pair->dso->name); + pair->priv = 1; + } + } + + pr_info("Maps only in kallsyms:\n"); + + for (nd = rb_first(&kallsyms.kmaps.maps[type]); + nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node); + + if (!pos->priv) + map__fprintf(pos, stderr); + } +out: + return err; +} -- cgit v0.10.2 From d3b59a38bcdab4248134023c2c5dfabee5a4878e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:42 +0100 Subject: perf tests: Move test__open_syscall_event into separate object Separating test__open_syscall_event test from the builtin-test into open-syscall object. Adding util object under tests directory to gather help functions common to more tests. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 7c7ba4d..69f582c 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -432,6 +432,8 @@ LIB_OBJS += $(OUTPUT)tests/parse-events.o LIB_OBJS += $(OUTPUT)tests/dso-data.o LIB_OBJS += $(OUTPUT)tests/attr.o LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o +LIB_OBJS += $(OUTPUT)tests/open-syscall.o +LIB_OBJS += $(OUTPUT)tests/util.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 5bc9063..b6b1e46 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -27,90 +27,6 @@ #include "tests.h" -static int trace_event__id(const char *evname) -{ - char *filename; - int err = -1, fd; - - if (asprintf(&filename, - "%s/syscalls/%s/id", - tracing_events_path, evname) < 0) - return -1; - - fd = open(filename, O_RDONLY); - if (fd >= 0) { - char id[16]; - if (read(fd, id, sizeof(id)) > 0) - err = atoi(id); - close(fd); - } - - free(filename); - return err; -} - -static int test__open_syscall_event(void) -{ - int err = -1, fd; - struct thread_map *threads; - struct perf_evsel *evsel; - struct perf_event_attr attr; - unsigned int nr_open_calls = 111, i; - int id = trace_event__id("sys_enter_open"); - - if (id < 0) { - pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); - return -1; - } - - threads = thread_map__new(-1, getpid(), UINT_MAX); - if (threads == NULL) { - pr_debug("thread_map__new\n"); - return -1; - } - - memset(&attr, 0, sizeof(attr)); - attr.type = PERF_TYPE_TRACEPOINT; - attr.config = id; - evsel = perf_evsel__new(&attr, 0); - if (evsel == NULL) { - pr_debug("perf_evsel__new\n"); - goto out_thread_map_delete; - } - - if (perf_evsel__open_per_thread(evsel, threads) < 0) { - pr_debug("failed to open counter: %s, " - "tweak /proc/sys/kernel/perf_event_paranoid?\n", - strerror(errno)); - goto out_evsel_delete; - } - - for (i = 0; i < nr_open_calls; ++i) { - fd = open("/etc/passwd", O_RDONLY); - close(fd); - } - - if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) { - pr_debug("perf_evsel__read_on_cpu\n"); - goto out_close_fd; - } - - if (evsel->counts->cpu[0].val != nr_open_calls) { - pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n", - nr_open_calls, evsel->counts->cpu[0].val); - goto out_close_fd; - } - - err = 0; -out_close_fd: - perf_evsel__close_fd(evsel, 1, threads->nr); -out_evsel_delete: - perf_evsel__delete(evsel); -out_thread_map_delete: - thread_map__delete(threads); - return err; -} - #include static int test__open_syscall_event_on_all_cpus(void) diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c new file mode 100644 index 0000000..98be8b5 --- /dev/null +++ b/tools/perf/tests/open-syscall.c @@ -0,0 +1,66 @@ +#include "thread_map.h" +#include "evsel.h" +#include "debug.h" +#include "tests.h" + +int test__open_syscall_event(void) +{ + int err = -1, fd; + struct thread_map *threads; + struct perf_evsel *evsel; + struct perf_event_attr attr; + unsigned int nr_open_calls = 111, i; + int id = trace_event__id("sys_enter_open"); + + if (id < 0) { + pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); + return -1; + } + + threads = thread_map__new(-1, getpid(), UINT_MAX); + if (threads == NULL) { + pr_debug("thread_map__new\n"); + return -1; + } + + memset(&attr, 0, sizeof(attr)); + attr.type = PERF_TYPE_TRACEPOINT; + attr.config = id; + evsel = perf_evsel__new(&attr, 0); + if (evsel == NULL) { + pr_debug("perf_evsel__new\n"); + goto out_thread_map_delete; + } + + if (perf_evsel__open_per_thread(evsel, threads) < 0) { + pr_debug("failed to open counter: %s, " + "tweak /proc/sys/kernel/perf_event_paranoid?\n", + strerror(errno)); + goto out_evsel_delete; + } + + for (i = 0; i < nr_open_calls; ++i) { + fd = open("/etc/passwd", O_RDONLY); + close(fd); + } + + if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) { + pr_debug("perf_evsel__read_on_cpu\n"); + goto out_close_fd; + } + + if (evsel->counts->cpu[0].val != nr_open_calls) { + pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n", + nr_open_calls, evsel->counts->cpu[0].val); + goto out_close_fd; + } + + err = 0; +out_close_fd: + perf_evsel__close_fd(evsel, 1, threads->nr); +out_evsel_delete: + perf_evsel__delete(evsel); +out_thread_map_delete: + thread_map__delete(threads); + return err; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 2223de5..bac133e 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -1,6 +1,11 @@ #ifndef TESTS_H #define TESTS_H +/* Tests */ int test__vmlinux_matches_kallsyms(void); +int test__open_syscall_event(void); + +/* Util */ +int trace_event__id(const char *evname); #endif /* TESTS_H */ diff --git a/tools/perf/tests/util.c b/tools/perf/tests/util.c new file mode 100644 index 0000000..748f2e8 --- /dev/null +++ b/tools/perf/tests/util.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include +#include +#include "tests.h" +#include "debugfs.h" + +int trace_event__id(const char *evname) +{ + char *filename; + int err = -1, fd; + + if (asprintf(&filename, + "%s/syscalls/%s/id", + tracing_events_path, evname) < 0) + return -1; + + fd = open(filename, O_RDONLY); + if (fd >= 0) { + char id[16]; + if (read(fd, id, sizeof(id)) > 0) + err = atoi(id); + close(fd); + } + + free(filename); + return err; +} -- cgit v0.10.2 From bd90517b374b1d6381a5509f55df1a9b7c33a6b1 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:43 +0100 Subject: perf tests: Move test__open_syscall_event_on_all_cpus into separate object Separating test__open_syscall_event_on_all_cpus test from the builtin-test into open-syscall-all-cpus object. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-4-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 69f582c..d413e89 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -433,6 +433,7 @@ LIB_OBJS += $(OUTPUT)tests/dso-data.o LIB_OBJS += $(OUTPUT)tests/attr.o LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o LIB_OBJS += $(OUTPUT)tests/open-syscall.o +LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o LIB_OBJS += $(OUTPUT)tests/util.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index b6b1e46..98e883b 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -29,120 +29,6 @@ #include -static int test__open_syscall_event_on_all_cpus(void) -{ - int err = -1, fd, cpu; - struct thread_map *threads; - struct cpu_map *cpus; - struct perf_evsel *evsel; - struct perf_event_attr attr; - unsigned int nr_open_calls = 111, i; - cpu_set_t cpu_set; - int id = trace_event__id("sys_enter_open"); - - if (id < 0) { - pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); - return -1; - } - - threads = thread_map__new(-1, getpid(), UINT_MAX); - if (threads == NULL) { - pr_debug("thread_map__new\n"); - return -1; - } - - cpus = cpu_map__new(NULL); - if (cpus == NULL) { - pr_debug("cpu_map__new\n"); - goto out_thread_map_delete; - } - - - CPU_ZERO(&cpu_set); - - memset(&attr, 0, sizeof(attr)); - attr.type = PERF_TYPE_TRACEPOINT; - attr.config = id; - evsel = perf_evsel__new(&attr, 0); - if (evsel == NULL) { - pr_debug("perf_evsel__new\n"); - goto out_thread_map_delete; - } - - if (perf_evsel__open(evsel, cpus, threads) < 0) { - pr_debug("failed to open counter: %s, " - "tweak /proc/sys/kernel/perf_event_paranoid?\n", - strerror(errno)); - goto out_evsel_delete; - } - - for (cpu = 0; cpu < cpus->nr; ++cpu) { - unsigned int ncalls = nr_open_calls + cpu; - /* - * XXX eventually lift this restriction in a way that - * keeps perf building on older glibc installations - * without CPU_ALLOC. 1024 cpus in 2010 still seems - * a reasonable upper limit tho :-) - */ - if (cpus->map[cpu] >= CPU_SETSIZE) { - pr_debug("Ignoring CPU %d\n", cpus->map[cpu]); - continue; - } - - CPU_SET(cpus->map[cpu], &cpu_set); - if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { - pr_debug("sched_setaffinity() failed on CPU %d: %s ", - cpus->map[cpu], - strerror(errno)); - goto out_close_fd; - } - for (i = 0; i < ncalls; ++i) { - fd = open("/etc/passwd", O_RDONLY); - close(fd); - } - CPU_CLR(cpus->map[cpu], &cpu_set); - } - - /* - * Here we need to explicitely preallocate the counts, as if - * we use the auto allocation it will allocate just for 1 cpu, - * as we start by cpu 0. - */ - if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) { - pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr); - goto out_close_fd; - } - - err = 0; - - for (cpu = 0; cpu < cpus->nr; ++cpu) { - unsigned int expected; - - if (cpus->map[cpu] >= CPU_SETSIZE) - continue; - - if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) { - pr_debug("perf_evsel__read_on_cpu\n"); - err = -1; - break; - } - - expected = nr_open_calls + cpu; - if (evsel->counts->cpu[cpu].val != expected) { - pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n", - expected, cpus->map[cpu], evsel->counts->cpu[cpu].val); - err = -1; - } - } - -out_close_fd: - perf_evsel__close_fd(evsel, 1, threads->nr); -out_evsel_delete: - perf_evsel__delete(evsel); -out_thread_map_delete: - thread_map__delete(threads); - return err; -} /* * This test will generate random numbers of calls to some getpid syscalls, diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c new file mode 100644 index 0000000..31072ab --- /dev/null +++ b/tools/perf/tests/open-syscall-all-cpus.c @@ -0,0 +1,120 @@ +#include "evsel.h" +#include "tests.h" +#include "thread_map.h" +#include "cpumap.h" +#include "debug.h" + +int test__open_syscall_event_on_all_cpus(void) +{ + int err = -1, fd, cpu; + struct thread_map *threads; + struct cpu_map *cpus; + struct perf_evsel *evsel; + struct perf_event_attr attr; + unsigned int nr_open_calls = 111, i; + cpu_set_t cpu_set; + int id = trace_event__id("sys_enter_open"); + + if (id < 0) { + pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); + return -1; + } + + threads = thread_map__new(-1, getpid(), UINT_MAX); + if (threads == NULL) { + pr_debug("thread_map__new\n"); + return -1; + } + + cpus = cpu_map__new(NULL); + if (cpus == NULL) { + pr_debug("cpu_map__new\n"); + goto out_thread_map_delete; + } + + + CPU_ZERO(&cpu_set); + + memset(&attr, 0, sizeof(attr)); + attr.type = PERF_TYPE_TRACEPOINT; + attr.config = id; + evsel = perf_evsel__new(&attr, 0); + if (evsel == NULL) { + pr_debug("perf_evsel__new\n"); + goto out_thread_map_delete; + } + + if (perf_evsel__open(evsel, cpus, threads) < 0) { + pr_debug("failed to open counter: %s, " + "tweak /proc/sys/kernel/perf_event_paranoid?\n", + strerror(errno)); + goto out_evsel_delete; + } + + for (cpu = 0; cpu < cpus->nr; ++cpu) { + unsigned int ncalls = nr_open_calls + cpu; + /* + * XXX eventually lift this restriction in a way that + * keeps perf building on older glibc installations + * without CPU_ALLOC. 1024 cpus in 2010 still seems + * a reasonable upper limit tho :-) + */ + if (cpus->map[cpu] >= CPU_SETSIZE) { + pr_debug("Ignoring CPU %d\n", cpus->map[cpu]); + continue; + } + + CPU_SET(cpus->map[cpu], &cpu_set); + if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { + pr_debug("sched_setaffinity() failed on CPU %d: %s ", + cpus->map[cpu], + strerror(errno)); + goto out_close_fd; + } + for (i = 0; i < ncalls; ++i) { + fd = open("/etc/passwd", O_RDONLY); + close(fd); + } + CPU_CLR(cpus->map[cpu], &cpu_set); + } + + /* + * Here we need to explicitely preallocate the counts, as if + * we use the auto allocation it will allocate just for 1 cpu, + * as we start by cpu 0. + */ + if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) { + pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr); + goto out_close_fd; + } + + err = 0; + + for (cpu = 0; cpu < cpus->nr; ++cpu) { + unsigned int expected; + + if (cpus->map[cpu] >= CPU_SETSIZE) + continue; + + if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) { + pr_debug("perf_evsel__read_on_cpu\n"); + err = -1; + break; + } + + expected = nr_open_calls + cpu; + if (evsel->counts->cpu[cpu].val != expected) { + pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n", + expected, cpus->map[cpu], evsel->counts->cpu[cpu].val); + err = -1; + } + } + +out_close_fd: + perf_evsel__close_fd(evsel, 1, threads->nr); +out_evsel_delete: + perf_evsel__delete(evsel); +out_thread_map_delete: + thread_map__delete(threads); + return err; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index bac133e..c2887f2 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -4,6 +4,7 @@ /* Tests */ int test__vmlinux_matches_kallsyms(void); int test__open_syscall_event(void); +int test__open_syscall_event_on_all_cpus(void); /* Util */ int trace_event__id(const char *evname); -- cgit v0.10.2 From a65b9c62be044b7956022e2823c5f079cf35b069 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:44 +0100 Subject: perf tests: Move test__basic_mmap into separate object Separating test__basic_mmap test from the builtin-test into mmap-basic object. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-5-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index d413e89..337489e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -434,6 +434,7 @@ LIB_OBJS += $(OUTPUT)tests/attr.o LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o LIB_OBJS += $(OUTPUT)tests/open-syscall.o LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o +LIB_OBJS += $(OUTPUT)tests/mmap-basic.o LIB_OBJS += $(OUTPUT)tests/util.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 98e883b..609f592 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -30,163 +30,6 @@ #include -/* - * This test will generate random numbers of calls to some getpid syscalls, - * then establish an mmap for a group of events that are created to monitor - * the syscalls. - * - * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated - * sample.id field to map back to its respective perf_evsel instance. - * - * Then it checks if the number of syscalls reported as perf events by - * the kernel corresponds to the number of syscalls made. - */ -static int test__basic_mmap(void) -{ - int err = -1; - union perf_event *event; - struct thread_map *threads; - struct cpu_map *cpus; - struct perf_evlist *evlist; - struct perf_event_attr attr = { - .type = PERF_TYPE_TRACEPOINT, - .read_format = PERF_FORMAT_ID, - .sample_type = PERF_SAMPLE_ID, - .watermark = 0, - }; - cpu_set_t cpu_set; - const char *syscall_names[] = { "getsid", "getppid", "getpgrp", - "getpgid", }; - pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp, - (void*)getpgid }; -#define nsyscalls ARRAY_SIZE(syscall_names) - int ids[nsyscalls]; - unsigned int nr_events[nsyscalls], - expected_nr_events[nsyscalls], i, j; - struct perf_evsel *evsels[nsyscalls], *evsel; - - for (i = 0; i < nsyscalls; ++i) { - char name[64]; - - snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); - ids[i] = trace_event__id(name); - if (ids[i] < 0) { - pr_debug("Is debugfs mounted on /sys/kernel/debug?\n"); - return -1; - } - nr_events[i] = 0; - expected_nr_events[i] = random() % 257; - } - - threads = thread_map__new(-1, getpid(), UINT_MAX); - if (threads == NULL) { - pr_debug("thread_map__new\n"); - return -1; - } - - cpus = cpu_map__new(NULL); - if (cpus == NULL) { - pr_debug("cpu_map__new\n"); - goto out_free_threads; - } - - CPU_ZERO(&cpu_set); - CPU_SET(cpus->map[0], &cpu_set); - sched_setaffinity(0, sizeof(cpu_set), &cpu_set); - if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { - pr_debug("sched_setaffinity() failed on CPU %d: %s ", - cpus->map[0], strerror(errno)); - goto out_free_cpus; - } - - evlist = perf_evlist__new(cpus, threads); - if (evlist == NULL) { - pr_debug("perf_evlist__new\n"); - goto out_free_cpus; - } - - /* anonymous union fields, can't be initialized above */ - attr.wakeup_events = 1; - attr.sample_period = 1; - - for (i = 0; i < nsyscalls; ++i) { - attr.config = ids[i]; - evsels[i] = perf_evsel__new(&attr, i); - if (evsels[i] == NULL) { - pr_debug("perf_evsel__new\n"); - goto out_free_evlist; - } - - perf_evlist__add(evlist, evsels[i]); - - if (perf_evsel__open(evsels[i], cpus, threads) < 0) { - pr_debug("failed to open counter: %s, " - "tweak /proc/sys/kernel/perf_event_paranoid?\n", - strerror(errno)); - goto out_close_fd; - } - } - - if (perf_evlist__mmap(evlist, 128, true) < 0) { - pr_debug("failed to mmap events: %d (%s)\n", errno, - strerror(errno)); - goto out_close_fd; - } - - for (i = 0; i < nsyscalls; ++i) - for (j = 0; j < expected_nr_events[i]; ++j) { - int foo = syscalls[i](); - ++foo; - } - - while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { - struct perf_sample sample; - - if (event->header.type != PERF_RECORD_SAMPLE) { - pr_debug("unexpected %s event\n", - perf_event__name(event->header.type)); - goto out_munmap; - } - - err = perf_evlist__parse_sample(evlist, event, &sample); - if (err) { - pr_err("Can't parse sample, err = %d\n", err); - goto out_munmap; - } - - evsel = perf_evlist__id2evsel(evlist, sample.id); - if (evsel == NULL) { - pr_debug("event with id %" PRIu64 - " doesn't map to an evsel\n", sample.id); - goto out_munmap; - } - nr_events[evsel->idx]++; - } - - list_for_each_entry(evsel, &evlist->entries, node) { - if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { - pr_debug("expected %d %s events, got %d\n", - expected_nr_events[evsel->idx], - perf_evsel__name(evsel), nr_events[evsel->idx]); - goto out_munmap; - } - } - - err = 0; -out_munmap: - perf_evlist__munmap(evlist); -out_close_fd: - for (i = 0; i < nsyscalls; ++i) - perf_evsel__close_fd(evsels[i], 1, threads->nr); -out_free_evlist: - perf_evlist__delete(evlist); -out_free_cpus: - cpu_map__delete(cpus); -out_free_threads: - thread_map__delete(threads); - return err; -#undef nsyscalls -} static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp) { diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c new file mode 100644 index 0000000..e174681 --- /dev/null +++ b/tools/perf/tests/mmap-basic.c @@ -0,0 +1,162 @@ +#include "evlist.h" +#include "evsel.h" +#include "thread_map.h" +#include "cpumap.h" +#include "tests.h" + +/* + * This test will generate random numbers of calls to some getpid syscalls, + * then establish an mmap for a group of events that are created to monitor + * the syscalls. + * + * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated + * sample.id field to map back to its respective perf_evsel instance. + * + * Then it checks if the number of syscalls reported as perf events by + * the kernel corresponds to the number of syscalls made. + */ +int test__basic_mmap(void) +{ + int err = -1; + union perf_event *event; + struct thread_map *threads; + struct cpu_map *cpus; + struct perf_evlist *evlist; + struct perf_event_attr attr = { + .type = PERF_TYPE_TRACEPOINT, + .read_format = PERF_FORMAT_ID, + .sample_type = PERF_SAMPLE_ID, + .watermark = 0, + }; + cpu_set_t cpu_set; + const char *syscall_names[] = { "getsid", "getppid", "getpgrp", + "getpgid", }; + pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp, + (void*)getpgid }; +#define nsyscalls ARRAY_SIZE(syscall_names) + int ids[nsyscalls]; + unsigned int nr_events[nsyscalls], + expected_nr_events[nsyscalls], i, j; + struct perf_evsel *evsels[nsyscalls], *evsel; + + for (i = 0; i < nsyscalls; ++i) { + char name[64]; + + snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); + ids[i] = trace_event__id(name); + if (ids[i] < 0) { + pr_debug("Is debugfs mounted on /sys/kernel/debug?\n"); + return -1; + } + nr_events[i] = 0; + expected_nr_events[i] = random() % 257; + } + + threads = thread_map__new(-1, getpid(), UINT_MAX); + if (threads == NULL) { + pr_debug("thread_map__new\n"); + return -1; + } + + cpus = cpu_map__new(NULL); + if (cpus == NULL) { + pr_debug("cpu_map__new\n"); + goto out_free_threads; + } + + CPU_ZERO(&cpu_set); + CPU_SET(cpus->map[0], &cpu_set); + sched_setaffinity(0, sizeof(cpu_set), &cpu_set); + if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { + pr_debug("sched_setaffinity() failed on CPU %d: %s ", + cpus->map[0], strerror(errno)); + goto out_free_cpus; + } + + evlist = perf_evlist__new(cpus, threads); + if (evlist == NULL) { + pr_debug("perf_evlist__new\n"); + goto out_free_cpus; + } + + /* anonymous union fields, can't be initialized above */ + attr.wakeup_events = 1; + attr.sample_period = 1; + + for (i = 0; i < nsyscalls; ++i) { + attr.config = ids[i]; + evsels[i] = perf_evsel__new(&attr, i); + if (evsels[i] == NULL) { + pr_debug("perf_evsel__new\n"); + goto out_free_evlist; + } + + perf_evlist__add(evlist, evsels[i]); + + if (perf_evsel__open(evsels[i], cpus, threads) < 0) { + pr_debug("failed to open counter: %s, " + "tweak /proc/sys/kernel/perf_event_paranoid?\n", + strerror(errno)); + goto out_close_fd; + } + } + + if (perf_evlist__mmap(evlist, 128, true) < 0) { + pr_debug("failed to mmap events: %d (%s)\n", errno, + strerror(errno)); + goto out_close_fd; + } + + for (i = 0; i < nsyscalls; ++i) + for (j = 0; j < expected_nr_events[i]; ++j) { + int foo = syscalls[i](); + ++foo; + } + + while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { + struct perf_sample sample; + + if (event->header.type != PERF_RECORD_SAMPLE) { + pr_debug("unexpected %s event\n", + perf_event__name(event->header.type)); + goto out_munmap; + } + + err = perf_evlist__parse_sample(evlist, event, &sample); + if (err) { + pr_err("Can't parse sample, err = %d\n", err); + goto out_munmap; + } + + evsel = perf_evlist__id2evsel(evlist, sample.id); + if (evsel == NULL) { + pr_debug("event with id %" PRIu64 + " doesn't map to an evsel\n", sample.id); + goto out_munmap; + } + nr_events[evsel->idx]++; + } + + list_for_each_entry(evsel, &evlist->entries, node) { + if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { + pr_debug("expected %d %s events, got %d\n", + expected_nr_events[evsel->idx], + perf_evsel__name(evsel), nr_events[evsel->idx]); + goto out_munmap; + } + } + + err = 0; +out_munmap: + perf_evlist__munmap(evlist); +out_close_fd: + for (i = 0; i < nsyscalls; ++i) + perf_evsel__close_fd(evsels[i], 1, threads->nr); +out_free_evlist: + perf_evlist__delete(evlist); +out_free_cpus: + cpu_map__delete(cpus); +out_free_threads: + thread_map__delete(threads); + return err; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index c2887f2..1a925dd 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -5,6 +5,7 @@ int test__vmlinux_matches_kallsyms(void); int test__open_syscall_event(void); int test__open_syscall_event_on_all_cpus(void); +int test__basic_mmap(void); /* Util */ int trace_event__id(const char *evname); -- cgit v0.10.2 From 16d00fee703866c61c9006eff097952289335479 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:45 +0100 Subject: perf tests: Move test__PERF_RECORD into separate object Separating test__PERF_RECORD test from the builtin-test into perf-record object. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-6-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 337489e..a2d6153 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -435,6 +435,7 @@ LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o LIB_OBJS += $(OUTPUT)tests/open-syscall.o LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o LIB_OBJS += $(OUTPUT)tests/mmap-basic.o +LIB_OBJS += $(OUTPUT)tests/perf-record.o LIB_OBJS += $(OUTPUT)tests/util.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 609f592..7cb3928 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -31,313 +31,6 @@ -static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp) -{ - int i, cpu = -1, nrcpus = 1024; -realloc: - CPU_ZERO(maskp); - - if (sched_getaffinity(pid, sizeof(*maskp), maskp) == -1) { - if (errno == EINVAL && nrcpus < (1024 << 8)) { - nrcpus = nrcpus << 2; - goto realloc; - } - perror("sched_getaffinity"); - return -1; - } - - for (i = 0; i < nrcpus; i++) { - if (CPU_ISSET(i, maskp)) { - if (cpu == -1) - cpu = i; - else - CPU_CLR(i, maskp); - } - } - - return cpu; -} - -static int test__PERF_RECORD(void) -{ - struct perf_record_opts opts = { - .target = { - .uid = UINT_MAX, - .uses_mmap = true, - }, - .no_delay = true, - .freq = 10, - .mmap_pages = 256, - }; - cpu_set_t cpu_mask; - size_t cpu_mask_size = sizeof(cpu_mask); - struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); - struct perf_evsel *evsel; - struct perf_sample sample; - const char *cmd = "sleep"; - const char *argv[] = { cmd, "1", NULL, }; - char *bname; - u64 prev_time = 0; - bool found_cmd_mmap = false, - found_libc_mmap = false, - found_vdso_mmap = false, - found_ld_mmap = false; - int err = -1, errs = 0, i, wakeups = 0; - u32 cpu; - int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; - - if (evlist == NULL || argv == NULL) { - pr_debug("Not enough memory to create evlist\n"); - goto out; - } - - /* - * We need at least one evsel in the evlist, use the default - * one: "cycles". - */ - err = perf_evlist__add_default(evlist); - if (err < 0) { - pr_debug("Not enough memory to create evsel\n"); - goto out_delete_evlist; - } - - /* - * Create maps of threads and cpus to monitor. In this case - * we start with all threads and cpus (-1, -1) but then in - * perf_evlist__prepare_workload we'll fill in the only thread - * we're monitoring, the one forked there. - */ - err = perf_evlist__create_maps(evlist, &opts.target); - if (err < 0) { - pr_debug("Not enough memory to create thread/cpu maps\n"); - goto out_delete_evlist; - } - - /* - * Prepare the workload in argv[] to run, it'll fork it, and then wait - * for perf_evlist__start_workload() to exec it. This is done this way - * so that we have time to open the evlist (calling sys_perf_event_open - * on all the fds) and then mmap them. - */ - err = perf_evlist__prepare_workload(evlist, &opts, argv); - if (err < 0) { - pr_debug("Couldn't run the workload!\n"); - goto out_delete_evlist; - } - - /* - * Config the evsels, setting attr->comm on the first one, etc. - */ - evsel = perf_evlist__first(evlist); - evsel->attr.sample_type |= PERF_SAMPLE_CPU; - evsel->attr.sample_type |= PERF_SAMPLE_TID; - evsel->attr.sample_type |= PERF_SAMPLE_TIME; - perf_evlist__config_attrs(evlist, &opts); - - err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); - if (err < 0) { - pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); - goto out_delete_evlist; - } - - cpu = err; - - /* - * So that we can check perf_sample.cpu on all the samples. - */ - if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { - pr_debug("sched_setaffinity: %s\n", strerror(errno)); - goto out_delete_evlist; - } - - /* - * Call sys_perf_event_open on all the fds on all the evsels, - * grouping them if asked to. - */ - err = perf_evlist__open(evlist); - if (err < 0) { - pr_debug("perf_evlist__open: %s\n", strerror(errno)); - goto out_delete_evlist; - } - - /* - * mmap the first fd on a given CPU and ask for events for the other - * fds in the same CPU to be injected in the same mmap ring buffer - * (using ioctl(PERF_EVENT_IOC_SET_OUTPUT)). - */ - err = perf_evlist__mmap(evlist, opts.mmap_pages, false); - if (err < 0) { - pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); - goto out_delete_evlist; - } - - /* - * Now that all is properly set up, enable the events, they will - * count just on workload.pid, which will start... - */ - perf_evlist__enable(evlist); - - /* - * Now! - */ - perf_evlist__start_workload(evlist); - - while (1) { - int before = total_events; - - for (i = 0; i < evlist->nr_mmaps; i++) { - union perf_event *event; - - while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { - const u32 type = event->header.type; - const char *name = perf_event__name(type); - - ++total_events; - if (type < PERF_RECORD_MAX) - nr_events[type]++; - - err = perf_evlist__parse_sample(evlist, event, &sample); - if (err < 0) { - if (verbose) - perf_event__fprintf(event, stderr); - pr_debug("Couldn't parse sample\n"); - goto out_err; - } - - if (verbose) { - pr_info("%" PRIu64" %d ", sample.time, sample.cpu); - perf_event__fprintf(event, stderr); - } - - if (prev_time > sample.time) { - pr_debug("%s going backwards in time, prev=%" PRIu64 ", curr=%" PRIu64 "\n", - name, prev_time, sample.time); - ++errs; - } - - prev_time = sample.time; - - if (sample.cpu != cpu) { - pr_debug("%s with unexpected cpu, expected %d, got %d\n", - name, cpu, sample.cpu); - ++errs; - } - - if ((pid_t)sample.pid != evlist->workload.pid) { - pr_debug("%s with unexpected pid, expected %d, got %d\n", - name, evlist->workload.pid, sample.pid); - ++errs; - } - - if ((pid_t)sample.tid != evlist->workload.pid) { - pr_debug("%s with unexpected tid, expected %d, got %d\n", - name, evlist->workload.pid, sample.tid); - ++errs; - } - - if ((type == PERF_RECORD_COMM || - type == PERF_RECORD_MMAP || - type == PERF_RECORD_FORK || - type == PERF_RECORD_EXIT) && - (pid_t)event->comm.pid != evlist->workload.pid) { - pr_debug("%s with unexpected pid/tid\n", name); - ++errs; - } - - if ((type == PERF_RECORD_COMM || - type == PERF_RECORD_MMAP) && - event->comm.pid != event->comm.tid) { - pr_debug("%s with different pid/tid!\n", name); - ++errs; - } - - switch (type) { - case PERF_RECORD_COMM: - if (strcmp(event->comm.comm, cmd)) { - pr_debug("%s with unexpected comm!\n", name); - ++errs; - } - break; - case PERF_RECORD_EXIT: - goto found_exit; - case PERF_RECORD_MMAP: - bname = strrchr(event->mmap.filename, '/'); - if (bname != NULL) { - if (!found_cmd_mmap) - found_cmd_mmap = !strcmp(bname + 1, cmd); - if (!found_libc_mmap) - found_libc_mmap = !strncmp(bname + 1, "libc", 4); - if (!found_ld_mmap) - found_ld_mmap = !strncmp(bname + 1, "ld", 2); - } else if (!found_vdso_mmap) - found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]"); - break; - - case PERF_RECORD_SAMPLE: - /* Just ignore samples for now */ - break; - default: - pr_debug("Unexpected perf_event->header.type %d!\n", - type); - ++errs; - } - } - } - - /* - * We don't use poll here because at least at 3.1 times the - * PERF_RECORD_{!SAMPLE} events don't honour - * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does. - */ - if (total_events == before && false) - poll(evlist->pollfd, evlist->nr_fds, -1); - - sleep(1); - if (++wakeups > 5) { - pr_debug("No PERF_RECORD_EXIT event!\n"); - break; - } - } - -found_exit: - if (nr_events[PERF_RECORD_COMM] > 1) { - pr_debug("Excessive number of PERF_RECORD_COMM events!\n"); - ++errs; - } - - if (nr_events[PERF_RECORD_COMM] == 0) { - pr_debug("Missing PERF_RECORD_COMM for %s!\n", cmd); - ++errs; - } - - if (!found_cmd_mmap) { - pr_debug("PERF_RECORD_MMAP for %s missing!\n", cmd); - ++errs; - } - - if (!found_libc_mmap) { - pr_debug("PERF_RECORD_MMAP for %s missing!\n", "libc"); - ++errs; - } - - if (!found_ld_mmap) { - pr_debug("PERF_RECORD_MMAP for %s missing!\n", "ld"); - ++errs; - } - - if (!found_vdso_mmap) { - pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]"); - ++errs; - } -out_err: - perf_evlist__munmap(evlist); -out_delete_evlist: - perf_evlist__delete(evlist); -out: - return (err < 0 || errs > 0) ? -1 : 0; -} - - #if defined(__x86_64__) || defined(__i386__) #define barrier() asm volatile("" ::: "memory") diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c new file mode 100644 index 0000000..70e0d44 --- /dev/null +++ b/tools/perf/tests/perf-record.c @@ -0,0 +1,312 @@ +#include +#include "evlist.h" +#include "evsel.h" +#include "perf.h" +#include "debug.h" +#include "tests.h" + +static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp) +{ + int i, cpu = -1, nrcpus = 1024; +realloc: + CPU_ZERO(maskp); + + if (sched_getaffinity(pid, sizeof(*maskp), maskp) == -1) { + if (errno == EINVAL && nrcpus < (1024 << 8)) { + nrcpus = nrcpus << 2; + goto realloc; + } + perror("sched_getaffinity"); + return -1; + } + + for (i = 0; i < nrcpus; i++) { + if (CPU_ISSET(i, maskp)) { + if (cpu == -1) + cpu = i; + else + CPU_CLR(i, maskp); + } + } + + return cpu; +} + +int test__PERF_RECORD(void) +{ + struct perf_record_opts opts = { + .target = { + .uid = UINT_MAX, + .uses_mmap = true, + }, + .no_delay = true, + .freq = 10, + .mmap_pages = 256, + }; + cpu_set_t cpu_mask; + size_t cpu_mask_size = sizeof(cpu_mask); + struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); + struct perf_evsel *evsel; + struct perf_sample sample; + const char *cmd = "sleep"; + const char *argv[] = { cmd, "1", NULL, }; + char *bname; + u64 prev_time = 0; + bool found_cmd_mmap = false, + found_libc_mmap = false, + found_vdso_mmap = false, + found_ld_mmap = false; + int err = -1, errs = 0, i, wakeups = 0; + u32 cpu; + int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; + + if (evlist == NULL || argv == NULL) { + pr_debug("Not enough memory to create evlist\n"); + goto out; + } + + /* + * We need at least one evsel in the evlist, use the default + * one: "cycles". + */ + err = perf_evlist__add_default(evlist); + if (err < 0) { + pr_debug("Not enough memory to create evsel\n"); + goto out_delete_evlist; + } + + /* + * Create maps of threads and cpus to monitor. In this case + * we start with all threads and cpus (-1, -1) but then in + * perf_evlist__prepare_workload we'll fill in the only thread + * we're monitoring, the one forked there. + */ + err = perf_evlist__create_maps(evlist, &opts.target); + if (err < 0) { + pr_debug("Not enough memory to create thread/cpu maps\n"); + goto out_delete_evlist; + } + + /* + * Prepare the workload in argv[] to run, it'll fork it, and then wait + * for perf_evlist__start_workload() to exec it. This is done this way + * so that we have time to open the evlist (calling sys_perf_event_open + * on all the fds) and then mmap them. + */ + err = perf_evlist__prepare_workload(evlist, &opts, argv); + if (err < 0) { + pr_debug("Couldn't run the workload!\n"); + goto out_delete_evlist; + } + + /* + * Config the evsels, setting attr->comm on the first one, etc. + */ + evsel = perf_evlist__first(evlist); + evsel->attr.sample_type |= PERF_SAMPLE_CPU; + evsel->attr.sample_type |= PERF_SAMPLE_TID; + evsel->attr.sample_type |= PERF_SAMPLE_TIME; + perf_evlist__config_attrs(evlist, &opts); + + err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); + if (err < 0) { + pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); + goto out_delete_evlist; + } + + cpu = err; + + /* + * So that we can check perf_sample.cpu on all the samples. + */ + if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { + pr_debug("sched_setaffinity: %s\n", strerror(errno)); + goto out_delete_evlist; + } + + /* + * Call sys_perf_event_open on all the fds on all the evsels, + * grouping them if asked to. + */ + err = perf_evlist__open(evlist); + if (err < 0) { + pr_debug("perf_evlist__open: %s\n", strerror(errno)); + goto out_delete_evlist; + } + + /* + * mmap the first fd on a given CPU and ask for events for the other + * fds in the same CPU to be injected in the same mmap ring buffer + * (using ioctl(PERF_EVENT_IOC_SET_OUTPUT)). + */ + err = perf_evlist__mmap(evlist, opts.mmap_pages, false); + if (err < 0) { + pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); + goto out_delete_evlist; + } + + /* + * Now that all is properly set up, enable the events, they will + * count just on workload.pid, which will start... + */ + perf_evlist__enable(evlist); + + /* + * Now! + */ + perf_evlist__start_workload(evlist); + + while (1) { + int before = total_events; + + for (i = 0; i < evlist->nr_mmaps; i++) { + union perf_event *event; + + while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { + const u32 type = event->header.type; + const char *name = perf_event__name(type); + + ++total_events; + if (type < PERF_RECORD_MAX) + nr_events[type]++; + + err = perf_evlist__parse_sample(evlist, event, &sample); + if (err < 0) { + if (verbose) + perf_event__fprintf(event, stderr); + pr_debug("Couldn't parse sample\n"); + goto out_err; + } + + if (verbose) { + pr_info("%" PRIu64" %d ", sample.time, sample.cpu); + perf_event__fprintf(event, stderr); + } + + if (prev_time > sample.time) { + pr_debug("%s going backwards in time, prev=%" PRIu64 ", curr=%" PRIu64 "\n", + name, prev_time, sample.time); + ++errs; + } + + prev_time = sample.time; + + if (sample.cpu != cpu) { + pr_debug("%s with unexpected cpu, expected %d, got %d\n", + name, cpu, sample.cpu); + ++errs; + } + + if ((pid_t)sample.pid != evlist->workload.pid) { + pr_debug("%s with unexpected pid, expected %d, got %d\n", + name, evlist->workload.pid, sample.pid); + ++errs; + } + + if ((pid_t)sample.tid != evlist->workload.pid) { + pr_debug("%s with unexpected tid, expected %d, got %d\n", + name, evlist->workload.pid, sample.tid); + ++errs; + } + + if ((type == PERF_RECORD_COMM || + type == PERF_RECORD_MMAP || + type == PERF_RECORD_FORK || + type == PERF_RECORD_EXIT) && + (pid_t)event->comm.pid != evlist->workload.pid) { + pr_debug("%s with unexpected pid/tid\n", name); + ++errs; + } + + if ((type == PERF_RECORD_COMM || + type == PERF_RECORD_MMAP) && + event->comm.pid != event->comm.tid) { + pr_debug("%s with different pid/tid!\n", name); + ++errs; + } + + switch (type) { + case PERF_RECORD_COMM: + if (strcmp(event->comm.comm, cmd)) { + pr_debug("%s with unexpected comm!\n", name); + ++errs; + } + break; + case PERF_RECORD_EXIT: + goto found_exit; + case PERF_RECORD_MMAP: + bname = strrchr(event->mmap.filename, '/'); + if (bname != NULL) { + if (!found_cmd_mmap) + found_cmd_mmap = !strcmp(bname + 1, cmd); + if (!found_libc_mmap) + found_libc_mmap = !strncmp(bname + 1, "libc", 4); + if (!found_ld_mmap) + found_ld_mmap = !strncmp(bname + 1, "ld", 2); + } else if (!found_vdso_mmap) + found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]"); + break; + + case PERF_RECORD_SAMPLE: + /* Just ignore samples for now */ + break; + default: + pr_debug("Unexpected perf_event->header.type %d!\n", + type); + ++errs; + } + } + } + + /* + * We don't use poll here because at least at 3.1 times the + * PERF_RECORD_{!SAMPLE} events don't honour + * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does. + */ + if (total_events == before && false) + poll(evlist->pollfd, evlist->nr_fds, -1); + + sleep(1); + if (++wakeups > 5) { + pr_debug("No PERF_RECORD_EXIT event!\n"); + break; + } + } + +found_exit: + if (nr_events[PERF_RECORD_COMM] > 1) { + pr_debug("Excessive number of PERF_RECORD_COMM events!\n"); + ++errs; + } + + if (nr_events[PERF_RECORD_COMM] == 0) { + pr_debug("Missing PERF_RECORD_COMM for %s!\n", cmd); + ++errs; + } + + if (!found_cmd_mmap) { + pr_debug("PERF_RECORD_MMAP for %s missing!\n", cmd); + ++errs; + } + + if (!found_libc_mmap) { + pr_debug("PERF_RECORD_MMAP for %s missing!\n", "libc"); + ++errs; + } + + if (!found_ld_mmap) { + pr_debug("PERF_RECORD_MMAP for %s missing!\n", "ld"); + ++errs; + } + + if (!found_vdso_mmap) { + pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]"); + ++errs; + } +out_err: + perf_evlist__munmap(evlist); +out_delete_evlist: + perf_evlist__delete(evlist); +out: + return (err < 0 || errs > 0) ? -1 : 0; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 1a925dd..374b039 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -6,6 +6,7 @@ int test__vmlinux_matches_kallsyms(void); int test__open_syscall_event(void); int test__open_syscall_event_on_all_cpus(void); int test__basic_mmap(void); +int test__PERF_RECORD(void); /* Util */ int trace_event__id(const char *evname); -- cgit v0.10.2 From bacf7e5d4055b65506292cf6412ec71e7948a9cf Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:46 +0100 Subject: perf tests: Move test__rdpmc into separate object Separating test__rdpmc test from the builtin-test into rdpmc object. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-7-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index a2d6153..2e5197a 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -436,6 +436,7 @@ LIB_OBJS += $(OUTPUT)tests/open-syscall.o LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o LIB_OBJS += $(OUTPUT)tests/mmap-basic.o LIB_OBJS += $(OUTPUT)tests/perf-record.o +LIB_OBJS += $(OUTPUT)tests/rdpmc.o LIB_OBJS += $(OUTPUT)tests/util.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 7cb3928..1e9a0ea 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -30,174 +30,6 @@ #include - -#if defined(__x86_64__) || defined(__i386__) - -#define barrier() asm volatile("" ::: "memory") - -static u64 rdpmc(unsigned int counter) -{ - unsigned int low, high; - - asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter)); - - return low | ((u64)high) << 32; -} - -static u64 rdtsc(void) -{ - unsigned int low, high; - - asm volatile("rdtsc" : "=a" (low), "=d" (high)); - - return low | ((u64)high) << 32; -} - -static u64 mmap_read_self(void *addr) -{ - struct perf_event_mmap_page *pc = addr; - u32 seq, idx, time_mult = 0, time_shift = 0; - u64 count, cyc = 0, time_offset = 0, enabled, running, delta; - - do { - seq = pc->lock; - barrier(); - - enabled = pc->time_enabled; - running = pc->time_running; - - if (enabled != running) { - cyc = rdtsc(); - time_mult = pc->time_mult; - time_shift = pc->time_shift; - time_offset = pc->time_offset; - } - - idx = pc->index; - count = pc->offset; - if (idx) - count += rdpmc(idx - 1); - - barrier(); - } while (pc->lock != seq); - - if (enabled != running) { - u64 quot, rem; - - quot = (cyc >> time_shift); - rem = cyc & ((1 << time_shift) - 1); - delta = time_offset + quot * time_mult + - ((rem * time_mult) >> time_shift); - - enabled += delta; - if (idx) - running += delta; - - quot = count / running; - rem = count % running; - count = quot * enabled + (rem * enabled) / running; - } - - return count; -} - -/* - * If the RDPMC instruction faults then signal this back to the test parent task: - */ -static void segfault_handler(int sig __maybe_unused, - siginfo_t *info __maybe_unused, - void *uc __maybe_unused) -{ - exit(-1); -} - -static int __test__rdpmc(void) -{ - volatile int tmp = 0; - u64 i, loops = 1000; - int n; - int fd; - void *addr; - struct perf_event_attr attr = { - .type = PERF_TYPE_HARDWARE, - .config = PERF_COUNT_HW_INSTRUCTIONS, - .exclude_kernel = 1, - }; - u64 delta_sum = 0; - struct sigaction sa; - - sigfillset(&sa.sa_mask); - sa.sa_sigaction = segfault_handler; - sigaction(SIGSEGV, &sa, NULL); - - fd = sys_perf_event_open(&attr, 0, -1, -1, 0); - if (fd < 0) { - pr_err("Error: sys_perf_event_open() syscall returned " - "with %d (%s)\n", fd, strerror(errno)); - return -1; - } - - addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); - if (addr == (void *)(-1)) { - pr_err("Error: mmap() syscall returned with (%s)\n", - strerror(errno)); - goto out_close; - } - - for (n = 0; n < 6; n++) { - u64 stamp, now, delta; - - stamp = mmap_read_self(addr); - - for (i = 0; i < loops; i++) - tmp++; - - now = mmap_read_self(addr); - loops *= 10; - - delta = now - stamp; - pr_debug("%14d: %14Lu\n", n, (long long)delta); - - delta_sum += delta; - } - - munmap(addr, page_size); - pr_debug(" "); -out_close: - close(fd); - - if (!delta_sum) - return -1; - - return 0; -} - -static int test__rdpmc(void) -{ - int status = 0; - int wret = 0; - int ret; - int pid; - - pid = fork(); - if (pid < 0) - return -1; - - if (!pid) { - ret = __test__rdpmc(); - - exit(ret); - } - - wret = waitpid(pid, &status, 0); - if (wret < 0 || status) - return -1; - - return 0; -} - -#endif - static int test__perf_pmu(void) { return perf_pmu__test(); diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/tests/rdpmc.c new file mode 100644 index 0000000..ff94886 --- /dev/null +++ b/tools/perf/tests/rdpmc.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include "types.h" +#include "perf.h" +#include "debug.h" +#include "tests.h" + +#if defined(__x86_64__) || defined(__i386__) + +#define barrier() asm volatile("" ::: "memory") + +static u64 rdpmc(unsigned int counter) +{ + unsigned int low, high; + + asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter)); + + return low | ((u64)high) << 32; +} + +static u64 rdtsc(void) +{ + unsigned int low, high; + + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + + return low | ((u64)high) << 32; +} + +static u64 mmap_read_self(void *addr) +{ + struct perf_event_mmap_page *pc = addr; + u32 seq, idx, time_mult = 0, time_shift = 0; + u64 count, cyc = 0, time_offset = 0, enabled, running, delta; + + do { + seq = pc->lock; + barrier(); + + enabled = pc->time_enabled; + running = pc->time_running; + + if (enabled != running) { + cyc = rdtsc(); + time_mult = pc->time_mult; + time_shift = pc->time_shift; + time_offset = pc->time_offset; + } + + idx = pc->index; + count = pc->offset; + if (idx) + count += rdpmc(idx - 1); + + barrier(); + } while (pc->lock != seq); + + if (enabled != running) { + u64 quot, rem; + + quot = (cyc >> time_shift); + rem = cyc & ((1 << time_shift) - 1); + delta = time_offset + quot * time_mult + + ((rem * time_mult) >> time_shift); + + enabled += delta; + if (idx) + running += delta; + + quot = count / running; + rem = count % running; + count = quot * enabled + (rem * enabled) / running; + } + + return count; +} + +/* + * If the RDPMC instruction faults then signal this back to the test parent task: + */ +static void segfault_handler(int sig __maybe_unused, + siginfo_t *info __maybe_unused, + void *uc __maybe_unused) +{ + exit(-1); +} + +static int __test__rdpmc(void) +{ + volatile int tmp = 0; + u64 i, loops = 1000; + int n; + int fd; + void *addr; + struct perf_event_attr attr = { + .type = PERF_TYPE_HARDWARE, + .config = PERF_COUNT_HW_INSTRUCTIONS, + .exclude_kernel = 1, + }; + u64 delta_sum = 0; + struct sigaction sa; + + sigfillset(&sa.sa_mask); + sa.sa_sigaction = segfault_handler; + sigaction(SIGSEGV, &sa, NULL); + + fd = sys_perf_event_open(&attr, 0, -1, -1, 0); + if (fd < 0) { + pr_err("Error: sys_perf_event_open() syscall returned " + "with %d (%s)\n", fd, strerror(errno)); + return -1; + } + + addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); + if (addr == (void *)(-1)) { + pr_err("Error: mmap() syscall returned with (%s)\n", + strerror(errno)); + goto out_close; + } + + for (n = 0; n < 6; n++) { + u64 stamp, now, delta; + + stamp = mmap_read_self(addr); + + for (i = 0; i < loops; i++) + tmp++; + + now = mmap_read_self(addr); + loops *= 10; + + delta = now - stamp; + pr_debug("%14d: %14Lu\n", n, (long long)delta); + + delta_sum += delta; + } + + munmap(addr, page_size); + pr_debug(" "); +out_close: + close(fd); + + if (!delta_sum) + return -1; + + return 0; +} + +int test__rdpmc(void) +{ + int status = 0; + int wret = 0; + int ret; + int pid; + + pid = fork(); + if (pid < 0) + return -1; + + if (!pid) { + ret = __test__rdpmc(); + + exit(ret); + } + + wret = waitpid(pid, &status, 0); + if (wret < 0 || status) + return -1; + + return 0; +} + +#endif diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 374b039..03d428d 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -7,6 +7,7 @@ int test__open_syscall_event(void); int test__open_syscall_event_on_all_cpus(void); int test__basic_mmap(void); int test__PERF_RECORD(void); +int test__rdpmc(void); /* Util */ int trace_event__id(const char *evname); -- cgit v0.10.2 From cfffae2ef7029d38e71d337fbc2a9c6cf1fa5aaf Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:47 +0100 Subject: perf tests: Move perf_evsel__roundtrip_name_test into separate object Separating perf_evsel__roundtrip_name_test test from the builtin-test into evsel-roundtrip-name object. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-8-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 2e5197a..ad6fcb5 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -437,6 +437,7 @@ LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o LIB_OBJS += $(OUTPUT)tests/mmap-basic.o LIB_OBJS += $(OUTPUT)tests/perf-record.o LIB_OBJS += $(OUTPUT)tests/rdpmc.o +LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o LIB_OBJS += $(OUTPUT)tests/util.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 1e9a0ea..93f5e91 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -35,116 +35,6 @@ static int test__perf_pmu(void) return perf_pmu__test(); } -static int perf_evsel__roundtrip_cache_name_test(void) -{ - char name[128]; - int type, op, err = 0, ret = 0, i, idx; - struct perf_evsel *evsel; - struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); - - if (evlist == NULL) - return -ENOMEM; - - for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { - for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { - /* skip invalid cache type */ - if (!perf_evsel__is_cache_op_valid(type, op)) - continue; - - for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { - __perf_evsel__hw_cache_type_op_res_name(type, op, i, - name, sizeof(name)); - err = parse_events(evlist, name, 0); - if (err) - ret = err; - } - } - } - - idx = 0; - evsel = perf_evlist__first(evlist); - - for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { - for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { - /* skip invalid cache type */ - if (!perf_evsel__is_cache_op_valid(type, op)) - continue; - - for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { - __perf_evsel__hw_cache_type_op_res_name(type, op, i, - name, sizeof(name)); - if (evsel->idx != idx) - continue; - - ++idx; - - if (strcmp(perf_evsel__name(evsel), name)) { - pr_debug("%s != %s\n", perf_evsel__name(evsel), name); - ret = -1; - } - - evsel = perf_evsel__next(evsel); - } - } - } - - perf_evlist__delete(evlist); - return ret; -} - -static int __perf_evsel__name_array_test(const char *names[], int nr_names) -{ - int i, err; - struct perf_evsel *evsel; - struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); - - if (evlist == NULL) - return -ENOMEM; - - for (i = 0; i < nr_names; ++i) { - err = parse_events(evlist, names[i], 0); - if (err) { - pr_debug("failed to parse event '%s', err %d\n", - names[i], err); - goto out_delete_evlist; - } - } - - err = 0; - list_for_each_entry(evsel, &evlist->entries, node) { - if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { - --err; - pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); - } - } - -out_delete_evlist: - perf_evlist__delete(evlist); - return err; -} - -#define perf_evsel__name_array_test(names) \ - __perf_evsel__name_array_test(names, ARRAY_SIZE(names)) - -static int perf_evsel__roundtrip_name_test(void) -{ - int err = 0, ret = 0; - - err = perf_evsel__name_array_test(perf_evsel__hw_names); - if (err) - ret = err; - - err = perf_evsel__name_array_test(perf_evsel__sw_names); - if (err) - ret = err; - - err = perf_evsel__roundtrip_cache_name_test(); - if (err) - ret = err; - - return ret; -} - static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, int size, bool should_be_signed) { @@ -382,7 +272,7 @@ static struct test { }, { .desc = "roundtrip evsel->name check", - .func = perf_evsel__roundtrip_name_test, + .func = test__perf_evsel__roundtrip_name_test, }, { .desc = "Check parsing of sched tracepoints fields", diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c new file mode 100644 index 0000000..e61fc82 --- /dev/null +++ b/tools/perf/tests/evsel-roundtrip-name.c @@ -0,0 +1,114 @@ +#include "evlist.h" +#include "evsel.h" +#include "parse-events.h" +#include "tests.h" + +static int perf_evsel__roundtrip_cache_name_test(void) +{ + char name[128]; + int type, op, err = 0, ret = 0, i, idx; + struct perf_evsel *evsel; + struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); + + if (evlist == NULL) + return -ENOMEM; + + for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { + for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { + /* skip invalid cache type */ + if (!perf_evsel__is_cache_op_valid(type, op)) + continue; + + for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { + __perf_evsel__hw_cache_type_op_res_name(type, op, i, + name, sizeof(name)); + err = parse_events(evlist, name, 0); + if (err) + ret = err; + } + } + } + + idx = 0; + evsel = perf_evlist__first(evlist); + + for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { + for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { + /* skip invalid cache type */ + if (!perf_evsel__is_cache_op_valid(type, op)) + continue; + + for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { + __perf_evsel__hw_cache_type_op_res_name(type, op, i, + name, sizeof(name)); + if (evsel->idx != idx) + continue; + + ++idx; + + if (strcmp(perf_evsel__name(evsel), name)) { + pr_debug("%s != %s\n", perf_evsel__name(evsel), name); + ret = -1; + } + + evsel = perf_evsel__next(evsel); + } + } + } + + perf_evlist__delete(evlist); + return ret; +} + +static int __perf_evsel__name_array_test(const char *names[], int nr_names) +{ + int i, err; + struct perf_evsel *evsel; + struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); + + if (evlist == NULL) + return -ENOMEM; + + for (i = 0; i < nr_names; ++i) { + err = parse_events(evlist, names[i], 0); + if (err) { + pr_debug("failed to parse event '%s', err %d\n", + names[i], err); + goto out_delete_evlist; + } + } + + err = 0; + list_for_each_entry(evsel, &evlist->entries, node) { + if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { + --err; + pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); + } + } + +out_delete_evlist: + perf_evlist__delete(evlist); + return err; +} + +#define perf_evsel__name_array_test(names) \ + __perf_evsel__name_array_test(names, ARRAY_SIZE(names)) + +int test__perf_evsel__roundtrip_name_test(void) +{ + int err = 0, ret = 0; + + err = perf_evsel__name_array_test(perf_evsel__hw_names); + if (err) + ret = err; + + err = perf_evsel__name_array_test(perf_evsel__sw_names); + if (err) + ret = err; + + err = perf_evsel__roundtrip_cache_name_test(); + if (err) + ret = err; + + return ret; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 03d428d..5897dd1 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -8,6 +8,7 @@ int test__open_syscall_event_on_all_cpus(void); int test__basic_mmap(void); int test__PERF_RECORD(void); int test__rdpmc(void); +int test__perf_evsel__roundtrip_name_test(void); /* Util */ int trace_event__id(const char *evname); -- cgit v0.10.2 From 5e24a0904ed4029f6778a214b6fe41b9265fd620 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:48 +0100 Subject: perf tests: Move perf_evsel__tp_sched_test into separate object Separating perf_evsel__tp_sched_test test from the builtin-test into evsel-tp-sched object. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-9-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index ad6fcb5..e510b53 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -438,6 +438,7 @@ LIB_OBJS += $(OUTPUT)tests/mmap-basic.o LIB_OBJS += $(OUTPUT)tests/perf-record.o LIB_OBJS += $(OUTPUT)tests/rdpmc.o LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o +LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o LIB_OBJS += $(OUTPUT)tests/util.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 93f5e91..c66caa7 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -35,87 +35,6 @@ static int test__perf_pmu(void) return perf_pmu__test(); } -static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, - int size, bool should_be_signed) -{ - struct format_field *field = perf_evsel__field(evsel, name); - int is_signed; - int ret = 0; - - if (field == NULL) { - pr_debug("%s: \"%s\" field not found!\n", evsel->name, name); - return -1; - } - - is_signed = !!(field->flags | FIELD_IS_SIGNED); - if (should_be_signed && !is_signed) { - pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n", - evsel->name, name, is_signed, should_be_signed); - ret = -1; - } - - if (field->size != size) { - pr_debug("%s: \"%s\" size (%d) should be %d!\n", - evsel->name, name, field->size, size); - ret = -1; - } - - return ret; -} - -static int perf_evsel__tp_sched_test(void) -{ - struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0); - int ret = 0; - - if (evsel == NULL) { - pr_debug("perf_evsel__new\n"); - return -1; - } - - if (perf_evsel__test_field(evsel, "prev_comm", 16, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "prev_pid", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "prev_prio", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "prev_state", 8, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "next_comm", 16, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "next_pid", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "next_prio", 4, true)) - ret = -1; - - perf_evsel__delete(evsel); - - evsel = perf_evsel__newtp("sched", "sched_wakeup", 0); - - if (perf_evsel__test_field(evsel, "comm", 16, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "pid", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "prio", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "success", 4, true)) - ret = -1; - - if (perf_evsel__test_field(evsel, "target_cpu", 4, true)) - ret = -1; - - return ret; -} - static int test__syscall_open_tp_fields(void) { struct perf_record_opts opts = { @@ -276,7 +195,7 @@ static struct test { }, { .desc = "Check parsing of sched tracepoints fields", - .func = perf_evsel__tp_sched_test, + .func = test__perf_evsel__tp_sched_test, }, { .desc = "Generate and check syscalls:sys_enter_open event fields", diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c new file mode 100644 index 0000000..a5d2fcc --- /dev/null +++ b/tools/perf/tests/evsel-tp-sched.c @@ -0,0 +1,84 @@ +#include "evsel.h" +#include "tests.h" +#include "event-parse.h" + +static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, + int size, bool should_be_signed) +{ + struct format_field *field = perf_evsel__field(evsel, name); + int is_signed; + int ret = 0; + + if (field == NULL) { + pr_debug("%s: \"%s\" field not found!\n", evsel->name, name); + return -1; + } + + is_signed = !!(field->flags | FIELD_IS_SIGNED); + if (should_be_signed && !is_signed) { + pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n", + evsel->name, name, is_signed, should_be_signed); + ret = -1; + } + + if (field->size != size) { + pr_debug("%s: \"%s\" size (%d) should be %d!\n", + evsel->name, name, field->size, size); + ret = -1; + } + + return ret; +} + +int test__perf_evsel__tp_sched_test(void) +{ + struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0); + int ret = 0; + + if (evsel == NULL) { + pr_debug("perf_evsel__new\n"); + return -1; + } + + if (perf_evsel__test_field(evsel, "prev_comm", 16, true)) + ret = -1; + + if (perf_evsel__test_field(evsel, "prev_pid", 4, true)) + ret = -1; + + if (perf_evsel__test_field(evsel, "prev_prio", 4, true)) + ret = -1; + + if (perf_evsel__test_field(evsel, "prev_state", 8, true)) + ret = -1; + + if (perf_evsel__test_field(evsel, "next_comm", 16, true)) + ret = -1; + + if (perf_evsel__test_field(evsel, "next_pid", 4, true)) + ret = -1; + + if (perf_evsel__test_field(evsel, "next_prio", 4, true)) + ret = -1; + + perf_evsel__delete(evsel); + + evsel = perf_evsel__newtp("sched", "sched_wakeup", 0); + + if (perf_evsel__test_field(evsel, "comm", 16, true)) + ret = -1; + + if (perf_evsel__test_field(evsel, "pid", 4, true)) + ret = -1; + + if (perf_evsel__test_field(evsel, "prio", 4, true)) + ret = -1; + + if (perf_evsel__test_field(evsel, "success", 4, true)) + ret = -1; + + if (perf_evsel__test_field(evsel, "target_cpu", 4, true)) + ret = -1; + + return ret; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 5897dd1..1ef265d 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -9,6 +9,7 @@ int test__basic_mmap(void); int test__PERF_RECORD(void); int test__rdpmc(void); int test__perf_evsel__roundtrip_name_test(void); +int test__perf_evsel__tp_sched_test(void); /* Util */ int trace_event__id(const char *evname); -- cgit v0.10.2 From dc447eed59037c1c65feab9c72d372b6249af978 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:49 +0100 Subject: perf tests: Move test__syscall_open_tp_fields into separate object Separating test__syscall_open_tp_fields test from the builtin-test into open-syscall-tp-fields object. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-10-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index e510b53..1e50559 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -434,6 +434,7 @@ LIB_OBJS += $(OUTPUT)tests/attr.o LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o LIB_OBJS += $(OUTPUT)tests/open-syscall.o LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o +LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o LIB_OBJS += $(OUTPUT)tests/mmap-basic.o LIB_OBJS += $(OUTPUT)tests/perf-record.o LIB_OBJS += $(OUTPUT)tests/rdpmc.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index c66caa7..bab8490 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -35,118 +35,6 @@ static int test__perf_pmu(void) return perf_pmu__test(); } -static int test__syscall_open_tp_fields(void) -{ - struct perf_record_opts opts = { - .target = { - .uid = UINT_MAX, - .uses_mmap = true, - }, - .no_delay = true, - .freq = 1, - .mmap_pages = 256, - .raw_samples = true, - }; - const char *filename = "/etc/passwd"; - int flags = O_RDONLY | O_DIRECTORY; - struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); - struct perf_evsel *evsel; - int err = -1, i, nr_events = 0, nr_polls = 0; - - if (evlist == NULL) { - pr_debug("%s: perf_evlist__new\n", __func__); - goto out; - } - - evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); - if (evsel == NULL) { - pr_debug("%s: perf_evsel__newtp\n", __func__); - goto out_delete_evlist; - } - - perf_evlist__add(evlist, evsel); - - err = perf_evlist__create_maps(evlist, &opts.target); - if (err < 0) { - pr_debug("%s: perf_evlist__create_maps\n", __func__); - goto out_delete_evlist; - } - - perf_evsel__config(evsel, &opts, evsel); - - evlist->threads->map[0] = getpid(); - - err = perf_evlist__open(evlist); - if (err < 0) { - pr_debug("perf_evlist__open: %s\n", strerror(errno)); - goto out_delete_evlist; - } - - err = perf_evlist__mmap(evlist, UINT_MAX, false); - if (err < 0) { - pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); - goto out_delete_evlist; - } - - perf_evlist__enable(evlist); - - /* - * Generate the event: - */ - open(filename, flags); - - while (1) { - int before = nr_events; - - for (i = 0; i < evlist->nr_mmaps; i++) { - union perf_event *event; - - while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { - const u32 type = event->header.type; - int tp_flags; - struct perf_sample sample; - - ++nr_events; - - if (type != PERF_RECORD_SAMPLE) - continue; - - err = perf_evsel__parse_sample(evsel, event, &sample); - if (err) { - pr_err("Can't parse sample, err = %d\n", err); - goto out_munmap; - } - - tp_flags = perf_evsel__intval(evsel, &sample, "flags"); - - if (flags != tp_flags) { - pr_debug("%s: Expected flags=%#x, got %#x\n", - __func__, flags, tp_flags); - goto out_munmap; - } - - goto out_ok; - } - } - - if (nr_events == before) - poll(evlist->pollfd, evlist->nr_fds, 10); - - if (++nr_polls > 5) { - pr_debug("%s: no events!\n", __func__); - goto out_munmap; - } - } -out_ok: - err = 0; -out_munmap: - perf_evlist__munmap(evlist); -out_delete_evlist: - perf_evlist__delete(evlist); -out: - return err; -} - static struct test { const char *desc; int (*func)(void); diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c new file mode 100644 index 0000000..b05b6a6 --- /dev/null +++ b/tools/perf/tests/open-syscall-tp-fields.c @@ -0,0 +1,117 @@ +#include "perf.h" +#include "evlist.h" +#include "evsel.h" +#include "thread_map.h" +#include "tests.h" + +int test__syscall_open_tp_fields(void) +{ + struct perf_record_opts opts = { + .target = { + .uid = UINT_MAX, + .uses_mmap = true, + }, + .no_delay = true, + .freq = 1, + .mmap_pages = 256, + .raw_samples = true, + }; + const char *filename = "/etc/passwd"; + int flags = O_RDONLY | O_DIRECTORY; + struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); + struct perf_evsel *evsel; + int err = -1, i, nr_events = 0, nr_polls = 0; + + if (evlist == NULL) { + pr_debug("%s: perf_evlist__new\n", __func__); + goto out; + } + + evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0); + if (evsel == NULL) { + pr_debug("%s: perf_evsel__newtp\n", __func__); + goto out_delete_evlist; + } + + perf_evlist__add(evlist, evsel); + + err = perf_evlist__create_maps(evlist, &opts.target); + if (err < 0) { + pr_debug("%s: perf_evlist__create_maps\n", __func__); + goto out_delete_evlist; + } + + perf_evsel__config(evsel, &opts, evsel); + + evlist->threads->map[0] = getpid(); + + err = perf_evlist__open(evlist); + if (err < 0) { + pr_debug("perf_evlist__open: %s\n", strerror(errno)); + goto out_delete_evlist; + } + + err = perf_evlist__mmap(evlist, UINT_MAX, false); + if (err < 0) { + pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); + goto out_delete_evlist; + } + + perf_evlist__enable(evlist); + + /* + * Generate the event: + */ + open(filename, flags); + + while (1) { + int before = nr_events; + + for (i = 0; i < evlist->nr_mmaps; i++) { + union perf_event *event; + + while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { + const u32 type = event->header.type; + int tp_flags; + struct perf_sample sample; + + ++nr_events; + + if (type != PERF_RECORD_SAMPLE) + continue; + + err = perf_evsel__parse_sample(evsel, event, &sample); + if (err) { + pr_err("Can't parse sample, err = %d\n", err); + goto out_munmap; + } + + tp_flags = perf_evsel__intval(evsel, &sample, "flags"); + + if (flags != tp_flags) { + pr_debug("%s: Expected flags=%#x, got %#x\n", + __func__, flags, tp_flags); + goto out_munmap; + } + + goto out_ok; + } + } + + if (nr_events == before) + poll(evlist->pollfd, evlist->nr_fds, 10); + + if (++nr_polls > 5) { + pr_debug("%s: no events!\n", __func__); + goto out_munmap; + } + } +out_ok: + err = 0; +out_munmap: + perf_evlist__munmap(evlist); +out_delete_evlist: + perf_evlist__delete(evlist); +out: + return err; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 1ef265d..f70f998 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -10,6 +10,7 @@ int test__PERF_RECORD(void); int test__rdpmc(void); int test__perf_evsel__roundtrip_name_test(void); int test__perf_evsel__tp_sched_test(void); +int test__syscall_open_tp_fields(void); /* Util */ int trace_event__id(const char *evname); -- cgit v0.10.2 From cff7f956ec4a1ede9b752cfae3c12f588292ad80 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:50 +0100 Subject: perf tests: Move pmu tests into separate object Separating pmu's object tests into pmu object under tests directory. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-11-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 1e50559..9af012f 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -440,6 +440,7 @@ LIB_OBJS += $(OUTPUT)tests/perf-record.o LIB_OBJS += $(OUTPUT)tests/rdpmc.o LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o +LIB_OBJS += $(OUTPUT)tests/pmu.o LIB_OBJS += $(OUTPUT)tests/util.o BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index bab8490..d3b95e0 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -30,11 +30,6 @@ #include -static int test__perf_pmu(void) -{ - return perf_pmu__test(); -} - static struct test { const char *desc; int (*func)(void); @@ -71,7 +66,7 @@ static struct test { }, { .desc = "Test perf pmu format parsing", - .func = test__perf_pmu, + .func = test__pmu, }, { .desc = "Test dso data interface", diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c new file mode 100644 index 0000000..a5f3798 --- /dev/null +++ b/tools/perf/tests/pmu.c @@ -0,0 +1,178 @@ +#include "parse-events.h" +#include "pmu.h" +#include "util.h" +#include "tests.h" + +/* Simulated format definitions. */ +static struct test_format { + const char *name; + const char *value; +} test_formats[] = { + { "krava01", "config:0-1,62-63\n", }, + { "krava02", "config:10-17\n", }, + { "krava03", "config:5\n", }, + { "krava11", "config1:0,2,4,6,8,20-28\n", }, + { "krava12", "config1:63\n", }, + { "krava13", "config1:45-47\n", }, + { "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", }, + { "krava22", "config2:8,18,48,58\n", }, + { "krava23", "config2:28-29,38\n", }, +}; + +#define TEST_FORMATS_CNT (sizeof(test_formats) / sizeof(struct test_format)) + +/* Simulated users input. */ +static struct parse_events__term test_terms[] = { + { + .config = (char *) "krava01", + .val.num = 15, + .type_val = PARSE_EVENTS__TERM_TYPE_NUM, + .type_term = PARSE_EVENTS__TERM_TYPE_USER, + }, + { + .config = (char *) "krava02", + .val.num = 170, + .type_val = PARSE_EVENTS__TERM_TYPE_NUM, + .type_term = PARSE_EVENTS__TERM_TYPE_USER, + }, + { + .config = (char *) "krava03", + .val.num = 1, + .type_val = PARSE_EVENTS__TERM_TYPE_NUM, + .type_term = PARSE_EVENTS__TERM_TYPE_USER, + }, + { + .config = (char *) "krava11", + .val.num = 27, + .type_val = PARSE_EVENTS__TERM_TYPE_NUM, + .type_term = PARSE_EVENTS__TERM_TYPE_USER, + }, + { + .config = (char *) "krava12", + .val.num = 1, + .type_val = PARSE_EVENTS__TERM_TYPE_NUM, + .type_term = PARSE_EVENTS__TERM_TYPE_USER, + }, + { + .config = (char *) "krava13", + .val.num = 2, + .type_val = PARSE_EVENTS__TERM_TYPE_NUM, + .type_term = PARSE_EVENTS__TERM_TYPE_USER, + }, + { + .config = (char *) "krava21", + .val.num = 119, + .type_val = PARSE_EVENTS__TERM_TYPE_NUM, + .type_term = PARSE_EVENTS__TERM_TYPE_USER, + }, + { + .config = (char *) "krava22", + .val.num = 11, + .type_val = PARSE_EVENTS__TERM_TYPE_NUM, + .type_term = PARSE_EVENTS__TERM_TYPE_USER, + }, + { + .config = (char *) "krava23", + .val.num = 2, + .type_val = PARSE_EVENTS__TERM_TYPE_NUM, + .type_term = PARSE_EVENTS__TERM_TYPE_USER, + }, +}; +#define TERMS_CNT (sizeof(test_terms) / sizeof(struct parse_events__term)) + +/* + * Prepare format directory data, exported by kernel + * at /sys/bus/event_source/devices//format. + */ +static char *test_format_dir_get(void) +{ + static char dir[PATH_MAX]; + unsigned int i; + + snprintf(dir, PATH_MAX, "/tmp/perf-pmu-test-format-XXXXXX"); + if (!mkdtemp(dir)) + return NULL; + + for (i = 0; i < TEST_FORMATS_CNT; i++) { + static char name[PATH_MAX]; + struct test_format *format = &test_formats[i]; + FILE *file; + + snprintf(name, PATH_MAX, "%s/%s", dir, format->name); + + file = fopen(name, "w"); + if (!file) + return NULL; + + if (1 != fwrite(format->value, strlen(format->value), 1, file)) + break; + + fclose(file); + } + + return dir; +} + +/* Cleanup format directory. */ +static int test_format_dir_put(char *dir) +{ + char buf[PATH_MAX]; + snprintf(buf, PATH_MAX, "rm -f %s/*\n", dir); + if (system(buf)) + return -1; + + snprintf(buf, PATH_MAX, "rmdir %s\n", dir); + return system(buf); +} + +static struct list_head *test_terms_list(void) +{ + static LIST_HEAD(terms); + unsigned int i; + + for (i = 0; i < TERMS_CNT; i++) + list_add_tail(&test_terms[i].list, &terms); + + return &terms; +} + +#undef TERMS_CNT + +int test__pmu(void) +{ + char *format = test_format_dir_get(); + LIST_HEAD(formats); + struct list_head *terms = test_terms_list(); + int ret; + + if (!format) + return -EINVAL; + + do { + struct perf_event_attr attr; + + memset(&attr, 0, sizeof(attr)); + + ret = perf_pmu__format_parse(format, &formats); + if (ret) + break; + + ret = perf_pmu__config_terms(&formats, &attr, terms); + if (ret) + break; + + ret = -EINVAL; + + if (attr.config != 0xc00000000002a823) + break; + if (attr.config1 != 0x8000400000000145) + break; + if (attr.config2 != 0x0400000020041d07) + break; + + ret = 0; + } while (0); + + test_format_dir_put(format); + return ret; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index f70f998..88a55df 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -11,6 +11,7 @@ int test__rdpmc(void); int test__perf_evsel__roundtrip_name_test(void); int test__perf_evsel__tp_sched_test(void); int test__syscall_open_tp_fields(void); +int test__pmu(void); /* Util */ int trace_event__id(const char *evname); diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 18e8480..9bdc60c 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -22,7 +22,7 @@ static LIST_HEAD(pmus); * Parse & process all the sysfs attributes located under * the directory specified in 'dir' parameter. */ -static int pmu_format_parse(char *dir, struct list_head *head) +int perf_pmu__format_parse(char *dir, struct list_head *head) { struct dirent *evt_ent; DIR *format_dir; @@ -77,7 +77,7 @@ static int pmu_format(char *name, struct list_head *format) if (stat(path, &st) < 0) return 0; /* no error if format does not exist */ - if (pmu_format_parse(path, format)) + if (perf_pmu__format_parse(path, format)) return -1; return 0; @@ -446,8 +446,9 @@ static int pmu_config_term(struct list_head *formats, return 0; } -static int pmu_config(struct list_head *formats, struct perf_event_attr *attr, - struct list_head *head_terms) +int perf_pmu__config_terms(struct list_head *formats, + struct perf_event_attr *attr, + struct list_head *head_terms) { struct parse_events__term *term; @@ -467,7 +468,7 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, struct list_head *head_terms) { attr->type = pmu->type; - return pmu_config(&pmu->format, attr, head_terms); + return perf_pmu__config_terms(&pmu->format, attr, head_terms); } static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu, @@ -551,177 +552,3 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to) for (b = from; b <= to; b++) set_bit(b, bits); } - -/* Simulated format definitions. */ -static struct test_format { - const char *name; - const char *value; -} test_formats[] = { - { "krava01", "config:0-1,62-63\n", }, - { "krava02", "config:10-17\n", }, - { "krava03", "config:5\n", }, - { "krava11", "config1:0,2,4,6,8,20-28\n", }, - { "krava12", "config1:63\n", }, - { "krava13", "config1:45-47\n", }, - { "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", }, - { "krava22", "config2:8,18,48,58\n", }, - { "krava23", "config2:28-29,38\n", }, -}; - -#define TEST_FORMATS_CNT (sizeof(test_formats) / sizeof(struct test_format)) - -/* Simulated users input. */ -static struct parse_events__term test_terms[] = { - { - .config = (char *) "krava01", - .val.num = 15, - .type_val = PARSE_EVENTS__TERM_TYPE_NUM, - .type_term = PARSE_EVENTS__TERM_TYPE_USER, - }, - { - .config = (char *) "krava02", - .val.num = 170, - .type_val = PARSE_EVENTS__TERM_TYPE_NUM, - .type_term = PARSE_EVENTS__TERM_TYPE_USER, - }, - { - .config = (char *) "krava03", - .val.num = 1, - .type_val = PARSE_EVENTS__TERM_TYPE_NUM, - .type_term = PARSE_EVENTS__TERM_TYPE_USER, - }, - { - .config = (char *) "krava11", - .val.num = 27, - .type_val = PARSE_EVENTS__TERM_TYPE_NUM, - .type_term = PARSE_EVENTS__TERM_TYPE_USER, - }, - { - .config = (char *) "krava12", - .val.num = 1, - .type_val = PARSE_EVENTS__TERM_TYPE_NUM, - .type_term = PARSE_EVENTS__TERM_TYPE_USER, - }, - { - .config = (char *) "krava13", - .val.num = 2, - .type_val = PARSE_EVENTS__TERM_TYPE_NUM, - .type_term = PARSE_EVENTS__TERM_TYPE_USER, - }, - { - .config = (char *) "krava21", - .val.num = 119, - .type_val = PARSE_EVENTS__TERM_TYPE_NUM, - .type_term = PARSE_EVENTS__TERM_TYPE_USER, - }, - { - .config = (char *) "krava22", - .val.num = 11, - .type_val = PARSE_EVENTS__TERM_TYPE_NUM, - .type_term = PARSE_EVENTS__TERM_TYPE_USER, - }, - { - .config = (char *) "krava23", - .val.num = 2, - .type_val = PARSE_EVENTS__TERM_TYPE_NUM, - .type_term = PARSE_EVENTS__TERM_TYPE_USER, - }, -}; -#define TERMS_CNT (sizeof(test_terms) / sizeof(struct parse_events__term)) - -/* - * Prepare format directory data, exported by kernel - * at /sys/bus/event_source/devices//format. - */ -static char *test_format_dir_get(void) -{ - static char dir[PATH_MAX]; - unsigned int i; - - snprintf(dir, PATH_MAX, "/tmp/perf-pmu-test-format-XXXXXX"); - if (!mkdtemp(dir)) - return NULL; - - for (i = 0; i < TEST_FORMATS_CNT; i++) { - static char name[PATH_MAX]; - struct test_format *format = &test_formats[i]; - FILE *file; - - snprintf(name, PATH_MAX, "%s/%s", dir, format->name); - - file = fopen(name, "w"); - if (!file) - return NULL; - - if (1 != fwrite(format->value, strlen(format->value), 1, file)) - break; - - fclose(file); - } - - return dir; -} - -/* Cleanup format directory. */ -static int test_format_dir_put(char *dir) -{ - char buf[PATH_MAX]; - snprintf(buf, PATH_MAX, "rm -f %s/*\n", dir); - if (system(buf)) - return -1; - - snprintf(buf, PATH_MAX, "rmdir %s\n", dir); - return system(buf); -} - -static struct list_head *test_terms_list(void) -{ - static LIST_HEAD(terms); - unsigned int i; - - for (i = 0; i < TERMS_CNT; i++) - list_add_tail(&test_terms[i].list, &terms); - - return &terms; -} - -#undef TERMS_CNT - -int perf_pmu__test(void) -{ - char *format = test_format_dir_get(); - LIST_HEAD(formats); - struct list_head *terms = test_terms_list(); - int ret; - - if (!format) - return -EINVAL; - - do { - struct perf_event_attr attr; - - memset(&attr, 0, sizeof(attr)); - - ret = pmu_format_parse(format, &formats); - if (ret) - break; - - ret = pmu_config(&formats, &attr, terms); - if (ret) - break; - - ret = -EINVAL; - - if (attr.config != 0xc00000000002a823) - break; - if (attr.config1 != 0x8000400000000145) - break; - if (attr.config2 != 0x0400000020041d07) - break; - - ret = 0; - } while (0); - - test_format_dir_put(format); - return ret; -} diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 39f3aba..07d553f 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -37,6 +37,9 @@ struct perf_pmu { struct perf_pmu *perf_pmu__find(char *name); int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, struct list_head *head_terms); +int perf_pmu__config_terms(struct list_head *formats, + struct perf_event_attr *attr, + struct list_head *head_terms); int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms); struct list_head *perf_pmu__alias(struct perf_pmu *pmu, struct list_head *head_terms); @@ -46,6 +49,7 @@ void perf_pmu_error(struct list_head *list, char *name, char const *msg); int perf_pmu__new_format(struct list_head *list, char *name, int config, unsigned long *bits); void perf_pmu__set_format(unsigned long *bits, long from, long to); +int perf_pmu__format_parse(char *dir, struct list_head *head); struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); -- cgit v0.10.2 From c81251e808fe2386e71990ecd49c408bb7cb4666 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:51 +0100 Subject: perf tests: Final cleanup for builtin-test move Final function renames to match test__* style and include cleanup. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-12-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 054182e..0047264 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -178,7 +178,6 @@ extern bool test_attr__enabled; void test_attr__init(void); void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu, int fd, int group_fd, unsigned long flags); -int test_attr__run(void); static inline int sys_perf_event_open(struct perf_event_attr *attr, diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c index 6e2feee..25638a9 100644 --- a/tools/perf/tests/attr.c +++ b/tools/perf/tests/attr.c @@ -27,6 +27,7 @@ #include "../perf.h" #include "util.h" #include "exec_cmd.h" +#include "tests.h" #define ENV "PERF_TEST_ATTR" @@ -151,7 +152,7 @@ static int run_dir(const char *d, const char *perf) return system(cmd); } -int test_attr__run(void) +int test__attr(void) { struct stat st; char path_perf[PATH_MAX]; diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index d3b95e0..186f675 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -4,31 +4,11 @@ * Builtin regression testing command: ever growing number of sanity tests */ #include "builtin.h" - -#include "util/cache.h" -#include "util/color.h" -#include "util/debug.h" -#include "util/debugfs.h" -#include "util/evlist.h" -#include "util/machine.h" -#include "util/parse-options.h" -#include "util/parse-events.h" -#include "util/symbol.h" -#include "util/thread_map.h" -#include "util/pmu.h" -#include "event-parse.h" -#include "../../include/linux/hw_breakpoint.h" - -#include - -#include "util/cpumap.h" -#include "util/evsel.h" -#include - #include "tests.h" - -#include - +#include "debug.h" +#include "color.h" +#include "parse-options.h" +#include "symbol.h" static struct test { const char *desc; @@ -52,7 +32,7 @@ static struct test { }, { .desc = "parse events tests", - .func = parse_events__test, + .func = test__parse_events, }, #if defined(__x86_64__) || defined(__i386__) { @@ -70,7 +50,7 @@ static struct test { }, { .desc = "Test dso data interface", - .func = dso__test_data, + .func = test__dso_data, }, { .desc = "roundtrip evsel->name check", @@ -86,7 +66,7 @@ static struct test { }, { .desc = "struct perf_event_attr setup", - .func = test_attr__run, + .func = test__attr, }, { .func = NULL, diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c index 0cd42fc..b5198f5 100644 --- a/tools/perf/tests/dso-data.c +++ b/tools/perf/tests/dso-data.c @@ -8,6 +8,7 @@ #include "machine.h" #include "symbol.h" +#include "tests.h" #define TEST_ASSERT_VAL(text, cond) \ do { \ @@ -95,7 +96,7 @@ struct test_data_offset offsets[] = { }, }; -int dso__test_data(void) +int test__dso_data(void) { struct machine machine; struct dso *dso; diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index b49c2ee..f2a82d0 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -4,6 +4,7 @@ #include "evlist.h" #include "sysfs.h" #include "../../../include/linux/hw_breakpoint.h" +#include "tests.h" #define TEST_ASSERT_VAL(text, cond) \ do { \ @@ -1086,7 +1087,7 @@ static int test_pmu_events(void) return ret; } -int parse_events__test(void) +int test__parse_events(void) { int ret1, ret2 = 0; diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 88a55df..fc121ed 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -12,6 +12,9 @@ int test__perf_evsel__roundtrip_name_test(void); int test__perf_evsel__tp_sched_test(void); int test__syscall_open_tp_fields(void); int test__pmu(void); +int test__attr(void); +int test__dso_data(void); +int test__parse_events(void); /* Util */ int trace_event__id(const char *evname); diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index ac9a6aa..f639937 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -99,7 +99,6 @@ void parse_events__set_leader(char *name, struct list_head *list); void parse_events_update_lists(struct list_head *list_event, struct list_head *list_all); void parse_events_error(void *data, void *scanner, char const *msg); -int parse_events__test(void); void print_events(const char *event_glob, bool name_only); void print_events_type(u8 type); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 04ccf29..de68f98 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -224,7 +224,6 @@ size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); size_t symbol__fprintf(struct symbol *sym, FILE *fp); bool symbol_type__is_a(char symbol_type, enum map_type map_type); -int dso__test_data(void); int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, struct symsrc *runtime_ss, symbol_filter_t filter, int kmodule); -- cgit v0.10.2 From f95e0818cbd026a8f2277895c65fcc9cc5b28cf6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 10 Nov 2012 01:46:52 +0100 Subject: perf tests: Check for mkstemp return value in dso-data test Adding check for mkstemp return error value in dso-data test. Reported-by: Arnaldo Carvalho de Melo Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352508412-16914-13-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c index b5198f5..5eaffa2 100644 --- a/tools/perf/tests/dso-data.c +++ b/tools/perf/tests/dso-data.c @@ -26,6 +26,10 @@ static char *test_file(int size) unsigned char *buf; fd = mkstemp(templ); + if (fd < 0) { + perror("mkstemp failed"); + return NULL; + } buf = malloc(size); if (!buf) { -- cgit v0.10.2 From 61e945150fe0ec4c20b7a3663b90c7ab705a88b4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 10 Nov 2012 19:41:15 -0300 Subject: perf tools: Stop using 'self' in pstack As suggested by tglx long ago. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-zgcldbjno41jn02b15760k4p@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c index 13d36fa..daa17ae 100644 --- a/tools/perf/util/pstack.c +++ b/tools/perf/util/pstack.c @@ -17,59 +17,59 @@ struct pstack { struct pstack *pstack__new(unsigned short max_nr_entries) { - struct pstack *self = zalloc((sizeof(*self) + - max_nr_entries * sizeof(void *))); - if (self != NULL) - self->max_nr_entries = max_nr_entries; - return self; + struct pstack *pstack = zalloc((sizeof(*pstack) + + max_nr_entries * sizeof(void *))); + if (pstack != NULL) + pstack->max_nr_entries = max_nr_entries; + return pstack; } -void pstack__delete(struct pstack *self) +void pstack__delete(struct pstack *pstack) { - free(self); + free(pstack); } -bool pstack__empty(const struct pstack *self) +bool pstack__empty(const struct pstack *pstack) { - return self->top == 0; + return pstack->top == 0; } -void pstack__remove(struct pstack *self, void *key) +void pstack__remove(struct pstack *pstack, void *key) { - unsigned short i = self->top, last_index = self->top - 1; + unsigned short i = pstack->top, last_index = pstack->top - 1; while (i-- != 0) { - if (self->entries[i] == key) { + if (pstack->entries[i] == key) { if (i < last_index) - memmove(self->entries + i, - self->entries + i + 1, + memmove(pstack->entries + i, + pstack->entries + i + 1, (last_index - i) * sizeof(void *)); - --self->top; + --pstack->top; return; } } pr_err("%s: %p not on the pstack!\n", __func__, key); } -void pstack__push(struct pstack *self, void *key) +void pstack__push(struct pstack *pstack, void *key) { - if (self->top == self->max_nr_entries) { - pr_err("%s: top=%d, overflow!\n", __func__, self->top); + if (pstack->top == pstack->max_nr_entries) { + pr_err("%s: top=%d, overflow!\n", __func__, pstack->top); return; } - self->entries[self->top++] = key; + pstack->entries[pstack->top++] = key; } -void *pstack__pop(struct pstack *self) +void *pstack__pop(struct pstack *pstack) { void *ret; - if (self->top == 0) { + if (pstack->top == 0) { pr_err("%s: underflow!\n", __func__); return NULL; } - ret = self->entries[--self->top]; - self->entries[self->top] = NULL; + ret = pstack->entries[--pstack->top]; + pstack->entries[pstack->top] = NULL; return ret; } -- cgit v0.10.2 From 30193d78d82a68247aa628a2414dc0f76c5b8093 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 12 Nov 2012 13:20:03 -0300 Subject: perf hists: Initialize all of he->stat with zeroes Not just nr_events and period. Reported-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-8nodd6b4bytyf1snf96oy531@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 7c6e73b..cb17e2a 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -742,9 +742,8 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, he = hist_entry__new(pair); if (he) { - he->stat.nr_events = 0; - he->stat.period = 0; - he->hists = hists; + memset(&he->stat, 0, sizeof(he->stat)); + he->hists = hists; rb_link_node(&he->rb_node, parent, p); rb_insert_color(&he->rb_node, &hists->entries); hists__inc_nr_entries(hists, he); -- cgit v0.10.2 From 4f746c95f18ad4d85599d9c157da7e6da766c3d9 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 12 Nov 2012 14:14:00 +0900 Subject: perf tools: Fix compile error on NO_NEWT=1 build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC builtin-annotate.o In file included from util/evsel.h:10:0, from util/evlist.h:8, from builtin-annotate.c:20: util/hist.h: In function ‘script_browse’: util/hist.h:198:45: error: unused parameter ‘script_opt’ [-Werror=unused-parameter] cc1: all warnings being treated as errors make: *** [builtin-annotate.o] Error 1 make: *** Waiting for unfinished jobs.... Signed-off-by: Namhyung Kim Cc: Feng Tang Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352697240-422-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 1278c2c..8b091a5 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -195,7 +195,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self return 0; } -static inline int script_browse(const char *script_opt) +static inline int script_browse(const char *script_opt __maybe_unused) { return 0; } -- cgit v0.10.2 From 0020ce23864d16f66e5667013b8b43d1df3e142e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 12 Nov 2012 11:50:17 +0900 Subject: perf tools: Add gtk. config option for launching GTK browser Add config option for launching GTK browser for the specified command by default. Currently only 'report' command is supported. Adding following line to the perfconfig file will have a same effect of specifying --gtk option on command line (unless other related options are not given). $ cat ~/.perfconfig [gtk] report = true Signed-off-by: Namhyung Kim Acked-by: Pekka Enberg Cc: Ingo Molnar Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352688617-25570-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/perf.c b/tools/perf/perf.c index a0ae290..0f661fb 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -85,21 +85,26 @@ int check_pager_config(const char *cmd) return c.val; } -static int tui_command_config(const char *var, const char *value, void *data) +static int browser_command_config(const char *var, const char *value, void *data) { struct pager_config *c = data; if (!prefixcmp(var, "tui.") && !strcmp(var + 4, c->cmd)) c->val = perf_config_bool(var, value); + if (!prefixcmp(var, "gtk.") && !strcmp(var + 4, c->cmd)) + c->val = perf_config_bool(var, value) ? 2 : 0; return 0; } -/* returns 0 for "no tui", 1 for "use tui", and -1 for "not specified" */ -static int check_tui_config(const char *cmd) +/* + * returns 0 for "no tui", 1 for "use tui", 2 for "use gtk", + * and -1 for "not specified" + */ +static int check_browser_config(const char *cmd) { struct pager_config c; c.cmd = cmd; c.val = -1; - perf_config(tui_command_config, &c); + perf_config(browser_command_config, &c); return c.val; } @@ -302,7 +307,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) prefix = NULL; /* setup_perf_directory(); */ if (use_browser == -1) - use_browser = check_tui_config(p->cmd); + use_browser = check_browser_config(p->cmd); if (use_pager == -1 && p->option & RUN_SETUP) use_pager = check_pager_config(p->cmd); -- cgit v0.10.2 From 6064803313bad9ae4cae233a9d56678adb2b6e7c Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Sun, 11 Nov 2012 23:20:50 +0900 Subject: perf tools: Use sscanf for parsing /proc/pid/maps When reading those files to synthesize MMAP events. It makes the code shorter and cleaner. Signed-off-by: Namhyung Kim Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1352643651-13891-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index ca9ca28..3cf2c3e 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -193,55 +193,43 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, event->header.misc = PERF_RECORD_MISC_USER; while (1) { - char bf[BUFSIZ], *pbf = bf; - int n; + char bf[BUFSIZ]; + char prot[5]; + char execname[PATH_MAX]; + char anonstr[] = "//anon"; size_t size; + if (fgets(bf, sizeof(bf), fp) == NULL) break; + /* ensure null termination since stack will be reused. */ + strcpy(execname, ""); + /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ - n = hex2u64(pbf, &event->mmap.start); - if (n < 0) - continue; - pbf += n + 1; - n = hex2u64(pbf, &event->mmap.len); - if (n < 0) + sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n", + &event->mmap.start, &event->mmap.len, prot, + &event->mmap.pgoff, execname); + + if (prot[2] != 'x') continue; - pbf += n + 3; - if (*pbf == 'x') { /* vm_exec */ - char anonstr[] = "//anon\n"; - char *execname = strchr(bf, '/'); - - /* Catch VDSO */ - if (execname == NULL) - execname = strstr(bf, "[vdso]"); - - /* Catch anonymous mmaps */ - if ((execname == NULL) && !strstr(bf, "[")) - execname = anonstr; - - if (execname == NULL) - continue; - - pbf += 3; - n = hex2u64(pbf, &event->mmap.pgoff); - - size = strlen(execname); - execname[size - 1] = '\0'; /* Remove \n */ - memcpy(event->mmap.filename, execname, size); - size = PERF_ALIGN(size, sizeof(u64)); - event->mmap.len -= event->mmap.start; - event->mmap.header.size = (sizeof(event->mmap) - - (sizeof(event->mmap.filename) - size)); - memset(event->mmap.filename + size, 0, machine->id_hdr_size); - event->mmap.header.size += machine->id_hdr_size; - event->mmap.pid = tgid; - event->mmap.tid = pid; - - if (process(tool, event, &synth_sample, machine) != 0) { - rc = -1; - break; - } + + if (!strcmp(execname, "")) + strcpy(execname, anonstr); + + size = strlen(execname) + 1; + memcpy(event->mmap.filename, execname, size); + size = PERF_ALIGN(size, sizeof(u64)); + event->mmap.len -= event->mmap.start; + event->mmap.header.size = (sizeof(event->mmap) - + (sizeof(event->mmap.filename) - size)); + memset(event->mmap.filename + size, 0, machine->id_hdr_size); + event->mmap.header.size += machine->id_hdr_size; + event->mmap.pid = tgid; + event->mmap.tid = pid; + + if (process(tool, event, &synth_sample, machine) != 0) { + rc = -1; + break; } } -- cgit v0.10.2 From cac21425578abddc4e9f529845832a57ba27ce0f Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 12 Nov 2012 18:34:00 +0100 Subject: perf tools: Fix attributes for '{}' defined event groups Fixing events attributes for groups defined via '{}'. Currently 'enable_on_exec' attribute in record command and both 'disabled ' and 'enable_on_exec' attributes in stat command are set based on the 'group' option. This eliminates proper setup for '{}' defined groups as they don't set 'group' option. Making above attributes values based on the 'evsel->leader' as this is common to both group definition. Moving perf_evlist__set_leader call within builtin-record ahead perf_evlist__config_attrs call, because the latter needs possible group leader links in place. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352741644-16809-2-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 5783c32..3717027 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -230,11 +230,15 @@ static int perf_record__open(struct perf_record *rec) struct perf_record_opts *opts = &rec->opts; int rc = 0; - perf_evlist__config_attrs(evlist, opts); - + /* + * Set the evsel leader links before we configure attributes, + * since some might depend on this info. + */ if (opts->group) perf_evlist__set_leader(evlist); + perf_evlist__config_attrs(evlist, opts); + list_for_each_entry(pos, &evlist->entries, node) { struct perf_event_attr *attr = &pos->attr; /* diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 6888960..557081e 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -129,8 +129,7 @@ static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS]; static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; static struct stats walltime_nsecs_stats; -static int create_perf_stat_counter(struct perf_evsel *evsel, - struct perf_evsel *first) +static int create_perf_stat_counter(struct perf_evsel *evsel) { struct perf_event_attr *attr = &evsel->attr; bool exclude_guest_missing = false; @@ -153,7 +152,7 @@ retry: return 0; } - if (!perf_target__has_task(&target) && (!group || evsel == first)) { + if (!perf_target__has_task(&target) && (!evsel->leader)) { attr->disabled = 1; attr->enable_on_exec = 1; } @@ -272,7 +271,7 @@ static int read_counter(struct perf_evsel *counter) static int __run_perf_stat(int argc __maybe_unused, const char **argv) { unsigned long long t0, t1; - struct perf_evsel *counter, *first; + struct perf_evsel *counter; int status = 0; int child_ready_pipe[2], go_pipe[2]; const bool forks = (argc > 0); @@ -332,10 +331,8 @@ static int __run_perf_stat(int argc __maybe_unused, const char **argv) if (group) perf_evlist__set_leader(evsel_list); - first = perf_evlist__first(evsel_list); - list_for_each_entry(counter, &evsel_list->entries, node) { - if (create_perf_stat_counter(counter, first) < 0) { + if (create_perf_stat_counter(counter) < 0) { /* * PPC returns ENXIO for HW counters until 2.6.37 * (behavior changed with commit b0a873e). diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1 index 39bf860..013572f 100644 --- a/tools/perf/tests/attr/test-record-group1 +++ b/tools/perf/tests/attr/test-record-group1 @@ -15,6 +15,4 @@ config=1 sample_type=327 mmap=0 comm=0 -# TODO this is disabled for --group option, enabled otherwise -# check why.. -enable_on_exec=1 +enable_on_exec=0 diff --git a/tools/perf/tests/attr/test-stat-group1 b/tools/perf/tests/attr/test-stat-group1 index 5ae2718..2a1f86e 100644 --- a/tools/perf/tests/attr/test-stat-group1 +++ b/tools/perf/tests/attr/test-stat-group1 @@ -11,7 +11,5 @@ group_fd=-1 fd=2 group_fd=1 config=1 -# TODO both disabled and enable_on_exec are disabled for --group option, -# enabled otherwise, check why.. -disabled=1 -enable_on_exec=1 +disabled=0 +enable_on_exec=0 diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c index b05b6a6..1c52fdc 100644 --- a/tools/perf/tests/open-syscall-tp-fields.c +++ b/tools/perf/tests/open-syscall-tp-fields.c @@ -41,7 +41,7 @@ int test__syscall_open_tp_fields(void) goto out_delete_evlist; } - perf_evsel__config(evsel, &opts, evsel); + perf_evsel__config(evsel, &opts); evlist->threads->map[0] = getpid(); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index a41dc4a..04acae0 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -52,15 +52,13 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, void perf_evlist__config_attrs(struct perf_evlist *evlist, struct perf_record_opts *opts) { - struct perf_evsel *evsel, *first; + struct perf_evsel *evsel; if (evlist->cpus->map[0] < 0) opts->no_inherit = true; - first = perf_evlist__first(evlist); - list_for_each_entry(evsel, &evlist->entries, node) { - perf_evsel__config(evsel, opts, first); + perf_evsel__config(evsel, opts); if (evlist->nr_entries > 1) evsel->attr.sample_type |= PERF_SAMPLE_ID; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 618d411..6d4a5f6 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -404,8 +404,8 @@ const char *perf_evsel__name(struct perf_evsel *evsel) return evsel->name ?: "unknown"; } -void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, - struct perf_evsel *first) +void perf_evsel__config(struct perf_evsel *evsel, + struct perf_record_opts *opts) { struct perf_event_attr *attr = &evsel->attr; int track = !evsel->idx; /* only the first counter needs these */ @@ -486,10 +486,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, attr->mmap = track; attr->comm = track; - if (perf_target__none(&opts->target) && - (!opts->group || evsel == first)) { + if (perf_target__none(&opts->target) && (!evsel->leader)) attr->enable_on_exec = 1; - } } int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 6f94d6d..32d7ec7 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -92,8 +92,7 @@ void perf_evsel__exit(struct perf_evsel *evsel); void perf_evsel__delete(struct perf_evsel *evsel); void perf_evsel__config(struct perf_evsel *evsel, - struct perf_record_opts *opts, - struct perf_evsel *first); + struct perf_record_opts *opts); bool perf_evsel__is_cache_op_valid(u8 type, u8 op); -- cgit v0.10.2 From 774cb499ca9ab0e5950a149d1fe102b125da1cee Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 12 Nov 2012 18:34:01 +0100 Subject: perf tools: Fix 'disabled' attribute config for record command Currently the record command sets all events initially as disabled. There's non conditional perf_evlist__enable call, that enables all events before we exec tracee program. That actually screws whole enable_on_exec logic, because the event is enabled before the traced program got executed. What we actually want is: 1) For any type of traced program: - all independent events and group leaders are disabled - all group members are enabled Group members are ruled by group leaders. They need to be enabled, because the group scheduling relies on that. 2) For traced programs executed by perf: - all independent events and group leaders have enable_on_exec set - we don't specifically enable or disable any event during the record command Independent events and group leaders are initially disabled and get enabled by exec. Group members are ruled by group leaders as stated in 1). 3) For traced programs attached by perf (pid/tid): - we specifically enable or disable all events during the record command When attaching events to already running traced we enable/disable events specifically, as there's no initial traced exec call. Fixing appropriate perf_event_attr test case to cover this change. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352741644-16809-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 3717027..268b356 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -701,7 +701,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) } } - perf_evlist__enable(evsel_list); + /* + * When perf is starting the traced process, all the events + * (apart from group members) have enable_on_exec=1 set, + * so don't spoil it by prematurely enabling them. + */ + if (!perf_target__none(&opts->target)) + perf_evlist__enable(evsel_list); /* * Let the child rip @@ -724,7 +730,12 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) waking++; } - if (done) + /* + * When perf is starting the traced process, at the end events + * die with the process and we wait for that. Thus no need to + * disable events in this case. + */ + if (done && !perf_target__none(&opts->target)) perf_evlist__disable(evsel_list); } diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group index b945f77..a6599e9 100644 --- a/tools/perf/tests/attr/test-record-group +++ b/tools/perf/tests/attr/test-record-group @@ -15,3 +15,4 @@ sample_type=327 mmap=0 comm=0 enable_on_exec=0 +disabled=0 diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1 index 013572f..5a8359d 100644 --- a/tools/perf/tests/attr/test-record-group1 +++ b/tools/perf/tests/attr/test-record-group1 @@ -16,3 +16,4 @@ sample_type=327 mmap=0 comm=0 enable_on_exec=0 +disabled=0 diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 6d4a5f6..fc4faaa 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -404,13 +404,40 @@ const char *perf_evsel__name(struct perf_evsel *evsel) return evsel->name ?: "unknown"; } +/* + * The enable_on_exec/disabled value strategy: + * + * 1) For any type of traced program: + * - all independent events and group leaders are disabled + * - all group members are enabled + * + * Group members are ruled by group leaders. They need to + * be enabled, because the group scheduling relies on that. + * + * 2) For traced programs executed by perf: + * - all independent events and group leaders have + * enable_on_exec set + * - we don't specifically enable or disable any event during + * the record command + * + * Independent events and group leaders are initially disabled + * and get enabled by exec. Group members are ruled by group + * leaders as stated in 1). + * + * 3) For traced programs attached by perf (pid/tid): + * - we specifically enable or disable all events during + * the record command + * + * When attaching events to already running traced we + * enable/disable events specifically, as there's no + * initial traced exec call. + */ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts) { struct perf_event_attr *attr = &evsel->attr; int track = !evsel->idx; /* only the first counter needs these */ - attr->disabled = 1; attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1; attr->inherit = !opts->no_inherit; attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | @@ -486,6 +513,19 @@ void perf_evsel__config(struct perf_evsel *evsel, attr->mmap = track; attr->comm = track; + /* + * XXX see the function comment above + * + * Disabling only independent events or group leaders, + * keeping group members enabled. + */ + if (!evsel->leader) + attr->disabled = 1; + + /* + * Setting enable_on_exec for independent events and + * group leaders for traced executed by perf. + */ if (perf_target__none(&opts->target) && (!evsel->leader)) attr->enable_on_exec = 1; } -- cgit v0.10.2 From 2711926a416733b853977a0e014c713955ad0d8a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 12 Nov 2012 18:34:02 +0100 Subject: perf tools: Ensure single disable call per event in record comand It's possible we issue the event disable ioctl multiple times until we read the final portion of the mmap buffer. Ensuring just single disable ioctl call for event, because there's no need to do that more than once. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352741644-16809-4-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 268b356..f3151d3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -502,6 +502,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) struct perf_evlist *evsel_list = rec->evlist; const char *output_name = rec->output_name; struct perf_session *session; + bool disabled = false; rec->progname = argv[0]; @@ -735,8 +736,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) * die with the process and we wait for that. Thus no need to * disable events in this case. */ - if (done && !perf_target__none(&opts->target)) + if (done && !disabled && !perf_target__none(&opts->target)) { perf_evlist__disable(evsel_list); + disabled = true; + } } if (quiet || signr == SIGUSR1) -- cgit v0.10.2 From 3fe4430dd66837d8fcdb63c167e908655fc842e3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 12 Nov 2012 18:34:03 +0100 Subject: perf tools: Omit group members from perf_evlist__disable/enable There's no need to disable/enable ordinary group member events, because they are initialy enabled and get scheduled by the leader. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352741644-16809-5-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 04acae0..e9d2d5d 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -222,6 +222,8 @@ void perf_evlist__disable(struct perf_evlist *evlist) for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { list_for_each_entry(pos, &evlist->entries, node) { + if (pos->leader) + continue; for (thread = 0; thread < evlist->threads->nr; thread++) ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_DISABLE, 0); @@ -236,6 +238,8 @@ void perf_evlist__enable(struct perf_evlist *evlist) for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) { list_for_each_entry(pos, &evlist->entries, node) { + if (pos->leader) + continue; for (thread = 0; thread < evlist->threads->nr; thread++) ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_ENABLE, 0); -- cgit v0.10.2 From 534123f458f196bcc269f97d20ccf125925c2e7b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 13 Nov 2012 15:32:58 +0100 Subject: perf tools: Add basic event modifier sanity check Updating event parser to allow any non zero string containing [ukhpGH] characters for event modifier. The modifier sanity is checked later in parse-event object logic. The check validates modifier to contain only one instance of any modifier (apart from 'p') present. v2: - added length check suggested Namhyung Kim Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20121113143258.GA2481@krava.brq.redhat.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index c0b785b..020323a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -722,6 +722,27 @@ static int get_event_modifier(struct event_modifier *mod, char *str, return 0; } +/* + * Basic modifier sanity check to validate it contains only one + * instance of any modifier (apart from 'p') present. + */ +static int check_modifier(char *str) +{ + char *p = str; + + /* The sizeof includes 0 byte as well. */ + if (strlen(str) > (sizeof("ukhGHppp") - 1)) + return -1; + + while (*p) { + if (*p != 'p' && strchr(p + 1, *p)) + return -1; + p++; + } + + return 0; +} + int parse_events__modifier_event(struct list_head *list, char *str, bool add) { struct perf_evsel *evsel; @@ -730,6 +751,9 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) if (str == NULL) return 0; + if (check_modifier(str)) + return -EINVAL; + if (!add && get_event_modifier(&mod, str, NULL)) return -EINVAL; diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 66959fa..e9d1134 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -82,7 +82,7 @@ num_hex 0x[a-fA-F0-9]+ num_raw_hex [a-fA-F0-9]+ name [a-zA-Z_*?][a-zA-Z0-9_*?]* name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* -modifier_event [ukhpGH]{1,8} +modifier_event [ukhpGH]+ modifier_bp [rwx]{1,3} %% -- cgit v0.10.2 From 7da5c85dd34dd67846fec965e4bf1f761eecca05 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 13 Nov 2012 22:30:31 +0900 Subject: perf ui tui: Move progress.c under ui/tui directory Current ui_progress functions are implemented for TUI only. So move the file under the tui directory. This is needed for providing an UI- agnostic wrapper. Signed-off-by: Namhyung Kim Cc: Ingo Molnar Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352813436-14173-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 9af012f..50e85c8 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -617,11 +617,11 @@ ifndef NO_NEWT LIB_OBJS += $(OUTPUT)ui/browsers/hists.o LIB_OBJS += $(OUTPUT)ui/browsers/map.o LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o - LIB_OBJS += $(OUTPUT)ui/progress.o LIB_OBJS += $(OUTPUT)ui/util.o LIB_OBJS += $(OUTPUT)ui/tui/setup.o LIB_OBJS += $(OUTPUT)ui/tui/util.o LIB_OBJS += $(OUTPUT)ui/tui/helpline.o + LIB_OBJS += $(OUTPUT)ui/tui/progress.o LIB_H += ui/browser.h LIB_H += ui/browsers/map.h LIB_H += ui/keysyms.h diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c deleted file mode 100644 index 13aa64e..0000000 --- a/tools/perf/ui/progress.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "../cache.h" -#include "progress.h" -#include "libslang.h" -#include "ui.h" -#include "browser.h" - -void ui_progress__update(u64 curr, u64 total, const char *title) -{ - int bar, y; - /* - * FIXME: We should have a per UI backend way of showing progress, - * stdio will just show a percentage as NN%, etc. - */ - if (use_browser <= 0) - return; - - if (total == 0) - return; - - ui__refresh_dimensions(true); - pthread_mutex_lock(&ui__lock); - y = SLtt_Screen_Rows / 2 - 2; - SLsmg_set_color(0); - SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols); - SLsmg_gotorc(y++, 1); - SLsmg_write_string((char *)title); - SLsmg_set_color(HE_COLORSET_SELECTED); - bar = ((SLtt_Screen_Cols - 2) * curr) / total; - SLsmg_fill_region(y, 1, 1, bar, ' '); - SLsmg_refresh(); - pthread_mutex_unlock(&ui__lock); -} diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c new file mode 100644 index 0000000..f8dc986 --- /dev/null +++ b/tools/perf/ui/tui/progress.c @@ -0,0 +1,32 @@ +#include "../cache.h" +#include "../progress.h" +#include "../libslang.h" +#include "../ui.h" +#include "../browser.h" + +void ui_progress__update(u64 curr, u64 total, const char *title) +{ + int bar, y; + /* + * FIXME: We should have a per UI backend way of showing progress, + * stdio will just show a percentage as NN%, etc. + */ + if (use_browser <= 0) + return; + + if (total == 0) + return; + + ui__refresh_dimensions(true); + pthread_mutex_lock(&ui__lock); + y = SLtt_Screen_Rows / 2 - 2; + SLsmg_set_color(0); + SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols); + SLsmg_gotorc(y++, 1); + SLsmg_write_string((char *)title); + SLsmg_set_color(HE_COLORSET_SELECTED); + bar = ((SLtt_Screen_Cols - 2) * curr) / total; + SLsmg_fill_region(y, 1, 1, bar, ' '); + SLsmg_refresh(); + pthread_mutex_unlock(&ui__lock); +} -- cgit v0.10.2 From 688f2f5b99311b127ea43efdbf47bb2e3c7a2e32 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 13 Nov 2012 22:30:32 +0900 Subject: perf ui: Introduce generic ui_progress helper Make ui_progress functions generic so that UI frontend code will add its callbacks. Signed-off-by: Namhyung Kim Cc: Ingo Molnar Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352813436-14173-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 50e85c8..f8466b4 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -423,6 +423,7 @@ LIB_OBJS += $(OUTPUT)util/vdso.o LIB_OBJS += $(OUTPUT)util/stat.o LIB_OBJS += $(OUTPUT)ui/helpline.o +LIB_OBJS += $(OUTPUT)ui/progress.o LIB_OBJS += $(OUTPUT)ui/hist.o LIB_OBJS += $(OUTPUT)ui/stdio/hist.o diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c index ccb046a..c06942a 100644 --- a/tools/perf/ui/gtk/util.c +++ b/tools/perf/ui/gtk/util.c @@ -111,14 +111,3 @@ struct perf_error_ops perf_gtk_eops = { .warning = perf_gtk__warning_statusbar, #endif }; - -/* - * FIXME: Functions below should be implemented properly. - * For now, just add stubs for NO_NEWT=1 build. - */ -#ifndef NEWT_SUPPORT -void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused, - const char *title __maybe_unused) -{ -} -#endif diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c new file mode 100644 index 0000000..f5e4d1b --- /dev/null +++ b/tools/perf/ui/progress.c @@ -0,0 +1,20 @@ +#include "../cache.h" +#include "progress.h" + +static void nop_progress_update(u64 curr __maybe_unused, + u64 total __maybe_unused, + const char *title __maybe_unused) +{ +} + +static struct ui_progress default_progress_fns = +{ + .update = nop_progress_update, +}; + +struct ui_progress *progress_fns = &default_progress_fns; + +void ui_progress__update(u64 curr, u64 total, const char *title) +{ + return progress_fns->update(curr, total, title); +} diff --git a/tools/perf/ui/progress.h b/tools/perf/ui/progress.h index d9c205b..717814b 100644 --- a/tools/perf/ui/progress.h +++ b/tools/perf/ui/progress.h @@ -3,6 +3,14 @@ #include <../types.h> +struct ui_progress { + void (*update)(u64, u64, const char *); +}; + +extern struct ui_progress *progress_fns; + +void ui_progress__init(void); + void ui_progress__update(u64 curr, u64 total, const char *title); #endif diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c index f8dc986..6c2184d 100644 --- a/tools/perf/ui/tui/progress.c +++ b/tools/perf/ui/tui/progress.c @@ -4,7 +4,7 @@ #include "../ui.h" #include "../browser.h" -void ui_progress__update(u64 curr, u64 total, const char *title) +static void tui_progress__update(u64 curr, u64 total, const char *title) { int bar, y; /* @@ -30,3 +30,13 @@ void ui_progress__update(u64 curr, u64 total, const char *title) SLsmg_refresh(); pthread_mutex_unlock(&ui__lock); } + +static struct ui_progress tui_progress_fns = +{ + .update = tui_progress__update, +}; + +void ui_progress__init(void) +{ + progress_fns = &tui_progress_fns; +} diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c index 60debb8..81efa19 100644 --- a/tools/perf/ui/tui/setup.c +++ b/tools/perf/ui/tui/setup.c @@ -118,6 +118,7 @@ int ui__init(void) newtSetSuspendCallback(newt_suspend, NULL); ui_helpline__init(); ui_browser__init(); + ui_progress__init(); signal(SIGSEGV, ui__signal); signal(SIGFPE, ui__signal); -- cgit v0.10.2 From a753579c3ec096bba9d24e1594a07dbb25aca8e4 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 13 Nov 2012 22:30:33 +0900 Subject: perf ui gtk: Implement ui_progress functions Implement progress update function for GTK2 front end. Note that since it will be called before gtk main loop so that we should call gtk event loop handler directly. Signed-off-by: Namhyung Kim Cc: Ingo Molnar Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352813436-14173-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index f8466b4..5a9075e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -648,6 +648,7 @@ ifndef NO_GTK2 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o LIB_OBJS += $(OUTPUT)ui/gtk/util.o LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o + LIB_OBJS += $(OUTPUT)ui/gtk/progress.o # Make sure that it'd be included only once. ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),) LIB_OBJS += $(OUTPUT)ui/setup.o diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h index 687af0b..856320e 100644 --- a/tools/perf/ui/gtk/gtk.h +++ b/tools/perf/ui/gtk/gtk.h @@ -30,6 +30,7 @@ struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window); int perf_gtk__deactivate_context(struct perf_gtk_context **ctx); void perf_gtk__init_helpline(void); +void perf_gtk__init_progress(void); void perf_gtk__init_hpp(void); #ifndef HAVE_GTK_INFO_BAR diff --git a/tools/perf/ui/gtk/progress.c b/tools/perf/ui/gtk/progress.c new file mode 100644 index 0000000..903426f --- /dev/null +++ b/tools/perf/ui/gtk/progress.c @@ -0,0 +1,50 @@ +#include + +#include "gtk.h" +#include "../progress.h" +#include "util.h" + +static GtkWidget *dialog; +static GtkWidget *progress; + +static void gtk_progress_update(u64 curr, u64 total, const char *title) +{ + double fraction = total ? 1.0 * curr / total : 0.0; + char buf[1024]; + + if (dialog == NULL) { + GtkWidget *vbox = gtk_vbox_new(TRUE, 5); + GtkWidget *label = gtk_label_new(title); + + dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); + progress = gtk_progress_bar_new(); + + gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, FALSE, 3); + gtk_box_pack_start(GTK_BOX(vbox), progress, TRUE, TRUE, 3); + + gtk_container_add(GTK_CONTAINER(dialog), vbox); + + gtk_window_set_title(GTK_WINDOW(dialog), "perf"); + gtk_window_resize(GTK_WINDOW(dialog), 300, 80); + gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); + + gtk_widget_show_all(dialog); + } + + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction); + snprintf(buf, sizeof(buf), "%"PRIu64" / %"PRIu64, curr, total); + gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), buf); + + /* we didn't call gtk_main yet, so do it manually */ + while (gtk_events_pending()) + gtk_main_iteration(); +} + +static struct ui_progress gtk_progress_fns = { + .update = gtk_progress_update, +}; + +void perf_gtk__init_progress(void) +{ + progress_fns = >k_progress_fns; +} diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c index 3c4c6ef..6c2dd2e 100644 --- a/tools/perf/ui/gtk/setup.c +++ b/tools/perf/ui/gtk/setup.c @@ -8,7 +8,9 @@ int perf_gtk__init(void) { perf_error__register(&perf_gtk_eops); perf_gtk__init_helpline(); + perf_gtk__init_progress(); perf_gtk__init_hpp(); + return gtk_init_check(NULL, NULL) ? 0 : -1; } -- cgit v0.10.2 From a5580f3ecb295a514f9522daf0ef7158f73ec2d6 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 13 Nov 2012 22:30:34 +0900 Subject: perf ui: Add ui_progress__finish() Sometimes we need to know when the progress bar should disappear. Checking curr >= total wasn't enough since there're cases not met that condition for the last call. So add a new ->finish callback to identify this explicitly. Currently only GTK frontend needs it. Signed-off-by: Namhyung Kim Cc: Ingo Molnar Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352813436-14173-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/ui/gtk/progress.c b/tools/perf/ui/gtk/progress.c index 903426f..482bcf3 100644 --- a/tools/perf/ui/gtk/progress.c +++ b/tools/perf/ui/gtk/progress.c @@ -40,8 +40,17 @@ static void gtk_progress_update(u64 curr, u64 total, const char *title) gtk_main_iteration(); } +static void gtk_progress_finish(void) +{ + /* this will also destroy all of its children */ + gtk_widget_destroy(dialog); + + dialog = NULL; +} + static struct ui_progress gtk_progress_fns = { .update = gtk_progress_update, + .finish = gtk_progress_finish, }; void perf_gtk__init_progress(void) diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c index f5e4d1b..3ec69560 100644 --- a/tools/perf/ui/progress.c +++ b/tools/perf/ui/progress.c @@ -18,3 +18,9 @@ void ui_progress__update(u64 curr, u64 total, const char *title) { return progress_fns->update(curr, total, title); } + +void ui_progress__finish(void) +{ + if (progress_fns->finish) + progress_fns->finish(); +} diff --git a/tools/perf/ui/progress.h b/tools/perf/ui/progress.h index 717814b..257cc22 100644 --- a/tools/perf/ui/progress.h +++ b/tools/perf/ui/progress.h @@ -5,6 +5,7 @@ struct ui_progress { void (*update)(u64, u64, const char *); + void (*finish)(void); }; extern struct ui_progress *progress_fns; @@ -12,5 +13,6 @@ extern struct ui_progress *progress_fns; void ui_progress__init(void); void ui_progress__update(u64 curr, u64 total, const char *title); +void ui_progress__finish(void); #endif diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index dec9875..83e8d23 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -26,6 +26,7 @@ int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); static inline void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused, const char *title __maybe_unused) {} +static inline void ui_progress__finish(void) {} #define ui__error(format, arg...) ui__warning(format, ##arg) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 15abe40..ce6f511 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1458,6 +1458,7 @@ more: session->ordered_samples.next_flush = ULLONG_MAX; err = flush_sample_queue(session, tool); out_err: + ui_progress__finish(); perf_session__warn_about_errors(session, tool); perf_session_free_sample_buffers(session); return err; -- cgit v0.10.2 From 59ed16b315681a08cf8aa13ee949e9405801f442 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 13 Nov 2012 22:30:35 +0900 Subject: perf ui: Always compile browser setup code We now have proper fallback logic, so always build it regardless of TUI or GTK setting. Signed-off-by: Namhyung Kim Cc: Ingo Molnar Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1352813436-14173-5-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 5a9075e..a7c6aa8 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -422,6 +422,7 @@ LIB_OBJS += $(OUTPUT)util/intlist.o LIB_OBJS += $(OUTPUT)util/vdso.o LIB_OBJS += $(OUTPUT)util/stat.o +LIB_OBJS += $(OUTPUT)ui/setup.o LIB_OBJS += $(OUTPUT)ui/helpline.o LIB_OBJS += $(OUTPUT)ui/progress.o LIB_OBJS += $(OUTPUT)ui/hist.o @@ -612,7 +613,6 @@ ifndef NO_NEWT BASIC_CFLAGS += -I/usr/include/slang BASIC_CFLAGS += -DNEWT_SUPPORT EXTLIBS += -lnewt -lslang - LIB_OBJS += $(OUTPUT)ui/setup.o LIB_OBJS += $(OUTPUT)ui/browser.o LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o LIB_OBJS += $(OUTPUT)ui/browsers/hists.o @@ -651,7 +651,6 @@ ifndef NO_GTK2 LIB_OBJS += $(OUTPUT)ui/gtk/progress.o # Make sure that it'd be included only once. ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),) - LIB_OBJS += $(OUTPUT)ui/setup.o LIB_OBJS += $(OUTPUT)ui/util.o endif endif diff --git a/tools/perf/ui/ui.h b/tools/perf/ui/ui.h index 7b67045..d86359c 100644 --- a/tools/perf/ui/ui.h +++ b/tools/perf/ui/ui.h @@ -3,9 +3,37 @@ #include #include +#include extern pthread_mutex_t ui__lock; +extern int use_browser; + +void setup_browser(bool fallback_to_pager); +void exit_browser(bool wait_for_ok); + +#ifdef NEWT_SUPPORT +int ui__init(void); +void ui__exit(bool wait_for_ok); +#else +static inline int ui__init(void) +{ + return -1; +} +static inline void ui__exit(bool wait_for_ok __maybe_unused) {} +#endif + +#ifdef GTK2_SUPPORT +int perf_gtk__init(void); +void perf_gtk__exit(bool wait_for_ok); +#else +static inline int perf_gtk__init(void) +{ + return -1; +} +static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {} +#endif + void ui__refresh_dimensions(bool force); #endif /* _PERF_UI_H_ */ diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 2bd5137..26e3672 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -5,6 +5,7 @@ #include "util.h" #include "strbuf.h" #include "../perf.h" +#include "../ui/ui.h" #define CMD_EXEC_PATH "--exec-path" #define CMD_PERF_DIR "--perf-dir=" @@ -31,44 +32,6 @@ extern const char *pager_program; extern int pager_in_use(void); extern int pager_use_color; -extern int use_browser; - -#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT) -void setup_browser(bool fallback_to_pager); -void exit_browser(bool wait_for_ok); - -#ifdef NEWT_SUPPORT -int ui__init(void); -void ui__exit(bool wait_for_ok); -#else -static inline int ui__init(void) -{ - return -1; -} -static inline void ui__exit(bool wait_for_ok __maybe_unused) {} -#endif - -#ifdef GTK2_SUPPORT -int perf_gtk__init(void); -void perf_gtk__exit(bool wait_for_ok); -#else -static inline int perf_gtk__init(void) -{ - return -1; -} -static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {} -#endif - -#else /* NEWT_SUPPORT || GTK2_SUPPORT */ - -static inline void setup_browser(bool fallback_to_pager) -{ - if (fallback_to_pager) - setup_pager(); -} -static inline void exit_browser(bool wait_for_ok __maybe_unused) {} -#endif /* NEWT_SUPPORT || GTK2_SUPPORT */ - char *alias_lookup(const char *alias); int split_cmdline(char *cmdline, const char ***argv); -- cgit v0.10.2 From 0bca6cff89c6e7d1e383993cccf0f59146874a34 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 5 Nov 2012 15:15:24 +0000 Subject: tools: Define a Makefile function to do subdir processing Define a Makefile function that can be called with $(call ...) to wrap the subdir make invocations in tools/Makefile. This will allow us in the next patch to insert bits in there to honour O= flags when called from the top-level Makefile. Signed-off-by: David Howells Cc: Borislav Petkov Cc: Ingo Molnar Cc: Linus Torvalds Cc: Namhyung Kim Cc: Paul Mackerras Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1378.1352379110@warthog.procyon.org.uk Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/Makefile b/tools/Makefile index 3ae4394..1f9a529 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -31,44 +31,44 @@ help: @echo ' clean: a summary clean target to clean _all_ folders' cpupower: FORCE - $(QUIET_SUBDIR0)power/$@/ $(QUIET_SUBDIR1) + $(call descend,power/$@) firewire lguest perf usb virtio vm: FORCE - $(QUIET_SUBDIR0)$@/ $(QUIET_SUBDIR1) + $(call descend,$@) selftests: FORCE - $(QUIET_SUBDIR0)testing/$@/ $(QUIET_SUBDIR1) + $(call descend,testing/$@) turbostat x86_energy_perf_policy: FORCE - $(QUIET_SUBDIR0)power/x86/$@/ $(QUIET_SUBDIR1) + $(call descend,power/x86/$@) cpupower_install: - $(QUIET_SUBDIR0)power/$(@:_install=)/ $(QUIET_SUBDIR1) install + $(call descend,power/$(@:_install=),install) firewire_install lguest_install perf_install usb_install virtio_install vm_install: - $(QUIET_SUBDIR0)$(@:_install=)/ $(QUIET_SUBDIR1) install + $(call descend,$(@:_install=),install) selftests_install: - $(QUIET_SUBDIR0)testing/$(@:_clean=)/ $(QUIET_SUBDIR1) install + $(call descend,testing/$(@:_clean=),install) turbostat_install x86_energy_perf_policy_install: - $(QUIET_SUBDIR0)power/x86/$(@:_install=)/ $(QUIET_SUBDIR1) install + $(call descend,power/x86/$(@:_install=),install) install: cpupower_install firewire_install lguest_install perf_install \ selftests_install turbostat_install usb_install virtio_install \ vm_install x86_energy_perf_policy_install cpupower_clean: - $(QUIET_SUBDIR0)power/cpupower/ $(QUIET_SUBDIR1) clean + $(call descend,power/cpupower,clean) firewire_clean lguest_clean perf_clean usb_clean virtio_clean vm_clean: - $(QUIET_SUBDIR0)$(@:_clean=)/ $(QUIET_SUBDIR1) clean + $(call descend,$(@:_clean=),clean) selftests_clean: - $(QUIET_SUBDIR0)testing/$(@:_clean=)/ $(QUIET_SUBDIR1) clean + $(call descend,testing/$(@:_clean=),clean) turbostat_clean x86_energy_perf_policy_clean: - $(QUIET_SUBDIR0)power/x86/$(@:_clean=)/ $(QUIET_SUBDIR1) clean + $(call descend,power/x86/$(@:_clean=),clean) clean: cpupower_clean firewire_clean lguest_clean perf_clean selftests_clean \ turbostat_clean usb_clean virtio_clean vm_clean \ diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include index 96ce80a..4a9e317 100644 --- a/tools/scripts/Makefile.include +++ b/tools/scripts/Makefile.include @@ -41,6 +41,14 @@ else NO_SUBDIR = : endif +# +# Define a callable command for descending to a new directory +# +# Call by doing: $(call descend,directory[,target]) +# +descend = \ + $(QUIET_SUBDIR0)$(1) $(QUIET_SUBDIR1) $(2) + QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir QUIET_SUBDIR1 = -- cgit v0.10.2 From 9db48cd5ccd0d127e991c15509a0241a18043e91 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 5 Nov 2012 21:02:08 +0000 Subject: tools: Honour the O= flag when tool build called from a higher Makefile Honour the O= flag that was passed to a higher level Makefile and then passed down as part of a tool build. To make this work, the top-level Makefile passes the original O= flag and subdir=tools to the tools/Makefile, and that in turn passes subdir=$(O)/$(subdir)/foodir when building tool foo in directory $(O)/$(subdir)/foodir (where the intervening slashes aren't added if an element is missing). For example, take perf. This is found in tools/perf/. Assume we're building into directory ~/zebra/, so we pass O=~/zebra to make. Dependening on where we run the build from, we see: make run in dir $(OUTPUT) dir ======================= ================== linux ~/zebra/tools/perf/ linux/tools ~/zebra/perf/ linux/tools/perf ~/zebra/ and if O= is not set, we get: make run in dir $(OUTPUT) dir ======================= ================== linux linux/tools/perf/ linux/tools linux/tools/perf/ linux/tools/perf linux/tools/perf/ The output directories are created by the descend function if they don't already exist. Signed-off-by: David Howells Cc: Borislav Petkov Cc: Ingo Molnar Cc: Linus Torvalds Cc: Namhyung Kim Cc: Paul Mackerras Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1378.1352379110@warthog.procyon.org.uk Signed-off-by: Arnaldo Carvalho de Melo diff --git a/Makefile b/Makefile index 14c93b3..08a31d8 100644 --- a/Makefile +++ b/Makefile @@ -1321,10 +1321,12 @@ kernelversion: # Clear a bunch of variables before executing the submake tools/: FORCE - $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ + $(Q)mkdir -p $(objtree)/tools + $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/ tools/%: FORCE - $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ $* + $(Q)mkdir -p $(objtree)/tools + $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/ $* # Single targets # --------------------------------------------------------------------------- diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include index 4a9e317..87467b1 100644 --- a/tools/scripts/Makefile.include +++ b/tools/scripts/Makefile.include @@ -1,8 +1,11 @@ -ifeq ("$(origin O)", "command line") +ifeq ($(origin O), command line) dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),) ABSOLUTE_O := $(shell cd $(O) ; pwd) - OUTPUT := $(ABSOLUTE_O)/ + OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/) COMMAND_O := O=$(ABSOLUTE_O) +ifeq ($(objtree),) + objtree := $(O) +endif endif ifneq ($(OUTPUT),) @@ -47,9 +50,10 @@ endif # Call by doing: $(call descend,directory[,target]) # descend = \ - $(QUIET_SUBDIR0)$(1) $(QUIET_SUBDIR1) $(2) + +mkdir -p $(OUTPUT)$(1) && \ + $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) -QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir +QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir QUIET_SUBDIR1 = ifneq ($(findstring $(MAKEFLAGS),s),s) @@ -64,5 +68,10 @@ ifndef V $(MAKE) $(PRINT_DIR) -C $$subdir QUIET_FLEX = @echo ' ' FLEX $@; QUIET_BISON = @echo ' ' BISON $@; + + descend = \ + @echo ' ' DESCEND $(1); \ + mkdir -p $(OUTPUT)$(1) && \ + $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) endif endif -- cgit v0.10.2 From 1668fc6505bd0796e34ee7f65eee69e81daaabe9 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 13 Nov 2012 14:14:38 -0300 Subject: tools: Pass the target in descend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixing: [acme@sandy linux]$ cd tools [acme@sandy tools]$ make clean DESCEND power/cpupower CC lib/cpufreq.o CC lib/sysfs.o LD libcpupower.so.0.0.0 CC utils/helpers/amd.o utils/helpers/amd.c:7:21: error: pci/pci.h: No such file or directory In file included from utils/helpers/amd.c:9: ./utils/helpers/helpers.h:137: warning: ‘struct pci_access’ declared inside parameter list ./utils/helpers/helpers.h:137: warning: its scope is only this definition or declaration, which is probably not what you want ./utils/helpers/helpers.h:139: warning: ‘struct pci_access’ declared inside parameter list utils/helpers/amd.c: In function ‘amd_pci_get_num_boost_states’: utils/helpers/amd.c:120: warning: passing argument 1 of ‘pci_slot_func_init’ from incompatible pointer type ./utils/helpers/helpers.h:138: note: expected ‘struct pci_access **’ but argument is of type ‘struct pci_access **’ utils/helpers/amd.c:125: warning: implicit declaration of function ‘pci_read_byte’ utils/helpers/amd.c:132: warning: implicit declaration of function ‘pci_cleanup’ make[1]: *** [utils/helpers/amd.o] Error 1 make: *** [cpupower_clean] Error 2 [acme@sandy tools]$ Reported-by: Arnaldo Carvalho de Melo Signed-off-by: David Howells Cc: Borislav Petkov Cc: Ingo Molnar Cc: Linus Torvalds Cc: Namhyung Kim Cc: Paul Mackerras Cc: Thomas Gleixner Link: http://lkml.kernel.org/n/tip-tviyimq6x6nm77sj5lt4t19f@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include index 87467b1..2964b96 100644 --- a/tools/scripts/Makefile.include +++ b/tools/scripts/Makefile.include @@ -51,7 +51,7 @@ endif # descend = \ +mkdir -p $(OUTPUT)$(1) && \ - $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) + $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2) QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir QUIET_SUBDIR1 = @@ -72,6 +72,6 @@ ifndef V descend = \ @echo ' ' DESCEND $(1); \ mkdir -p $(OUTPUT)$(1) && \ - $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) + $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2) endif endif -- cgit v0.10.2 From 1483c2ae90738e7453bfe446a3bbcdd0ba9abf36 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Wed, 31 Oct 2012 11:21:28 -0700 Subject: perf powerpc: Use uapi/unistd.h to fix build error Use the 'unistd.h' from arch/powerpc/include/uapi to build the perf tool. Signed-off-by: Sukadev Bhattiprolu Acked-by: David Howells Cc: Anton Blanchard Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Robert Richter Cc: linuxppc-dev@ozlabs.org Link: http://lkml.kernel.org/r/20121107191818.GA16211@us.ibm.com Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 0047264..f53ee0b 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -26,7 +26,7 @@ void get_term_dimensions(struct winsize *ws); #endif #ifdef __powerpc__ -#include "../../arch/powerpc/include/asm/unistd.h" +#include "../../arch/powerpc/include/uapi/asm/unistd.h" #define rmb() asm volatile ("sync" ::: "memory") #define cpu_relax() asm volatile ("" ::: "memory"); #define CPUINFO_PROC "cpu" -- cgit v0.10.2 From 07ac002f2fcc74c5be47b656d9201d5de84dc53d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 13 Nov 2012 17:27:28 -0300 Subject: perf evsel: Introduce is_group_member method To clarify what is being tested, instead of assuming that evsel->leader == NULL means either an 'isolated' evsel or a 'group leader'. Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-lvdbvimaxw9nc5een5vmem0c@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 557081e..c247fac 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -152,7 +152,8 @@ retry: return 0; } - if (!perf_target__has_task(&target) && (!evsel->leader)) { + if (!perf_target__has_task(&target) && + !perf_evsel__is_group_member(evsel)) { attr->disabled = 1; attr->enable_on_exec = 1; } diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index f2a82d0..42a0c8c 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -521,7 +521,7 @@ static int test__group1(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); + TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); /* cycles:upp */ evsel = perf_evsel__next(evsel); @@ -557,7 +557,7 @@ static int test__group2(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); + TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); /* cache-references + :u modifier */ evsel = perf_evsel__next(evsel); @@ -583,7 +583,7 @@ static int test__group2(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); + TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); return 0; } @@ -606,7 +606,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); + TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong group name", !strcmp(leader->group_name, "group1")); @@ -636,7 +636,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); + TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); TEST_ASSERT_VAL("wrong group name", !strcmp(leader->group_name, "group2")); @@ -663,7 +663,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); + TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); return 0; } @@ -687,7 +687,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); + TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); /* instructions:kp + p */ evsel = perf_evsel__next(evsel); @@ -724,7 +724,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); + TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); /* instructions + G */ evsel = perf_evsel__next(evsel); @@ -751,7 +751,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); + TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); /* instructions:G */ evsel = perf_evsel__next(evsel); @@ -777,7 +777,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); - TEST_ASSERT_VAL("wrong leader", evsel->leader == NULL); + TEST_ASSERT_VAL("wrong leader", !perf_evsel__is_group_member(evsel)); return 0; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index e9d2d5d..7052934 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -222,7 +222,7 @@ void perf_evlist__disable(struct perf_evlist *evlist) for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { list_for_each_entry(pos, &evlist->entries, node) { - if (pos->leader) + if (perf_evsel__is_group_member(pos)) continue; for (thread = 0; thread < evlist->threads->nr; thread++) ioctl(FD(pos, cpu, thread), @@ -238,7 +238,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) { list_for_each_entry(pos, &evlist->entries, node) { - if (pos->leader) + if (perf_evsel__is_group_member(pos)) continue; for (thread = 0; thread < evlist->threads->nr; thread++) ioctl(FD(pos, cpu, thread), diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index fc4faaa..1fb636c 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -519,14 +519,14 @@ void perf_evsel__config(struct perf_evsel *evsel, * Disabling only independent events or group leaders, * keeping group members enabled. */ - if (!evsel->leader) + if (!perf_evsel__is_group_member(evsel)) attr->disabled = 1; /* * Setting enable_on_exec for independent events and * group leaders for traced executed by perf. */ - if (perf_target__none(&opts->target) && (!evsel->leader)) + if (perf_target__none(&opts->target) && !perf_evsel__is_group_member(evsel)) attr->enable_on_exec = 1; } @@ -707,7 +707,7 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread) struct perf_evsel *leader = evsel->leader; int fd; - if (!leader) + if (!perf_evsel__is_group_member(evsel)) return -1; /* diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 32d7ec7..a4c1dd4 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -3,6 +3,7 @@ #include #include +#include #include "../../../include/uapi/linux/perf_event.h" #include "types.h" #include "xyarray.h" @@ -224,4 +225,9 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel) { return list_entry(evsel->node.next, struct perf_evsel, node); } + +static inline bool perf_evsel__is_group_member(const struct perf_evsel *evsel) +{ + return evsel->leader != NULL; +} #endif /* __PERF_EVSEL_H */ -- cgit v0.10.2