diff options
| author | Jiri Olsa <jolsa@kernel.org> | 2016-03-24 08:52:20 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-03-30 10:14:08 -0400 |
| commit | b31d660df37c1701fd18d526faeb9a86f0fc7dd2 (patch) | |
| tree | d7140a55abc608911da907a50de4dd409d08b486 /tools/perf | |
| parent | e0be62cc0325d65e1b7ae55d23e3d224638c20a6 (diff) | |
perf tests: Add test to check for event times
This test creates software event 'cpu-clock' attaches it in several ways
and checks that enabled and running times match.
Committer notes:
Testing it:
[acme@jouet linux]$ perf test -v times
44: Test events times :
--- start ---
test child forked, pid 27170
attaching to spawned child, enable on exec
OK : ena 307328, run 307328
attaching to current thread as enabled
OK : ena 7826, run 7826
attaching to current thread as disabled
OK : ena 738, run 738
attaching to CPU 0 as enabled
SKIP : not enough rights
attaching to CPU 0 as enabled
SKIP : not enough rights
test child finished with -2
---- end ----
Test events times: Skip
[acme@jouet linux]$
[root@jouet ~]# perf test times
44: Test events times : Ok
[root@jouet ~]# perf test -v times
44: Test events times :
--- start ---
test child forked, pid 27306
attaching to spawned child, enable on exec
OK : ena 479290, run 479290
attaching to current thread as enabled
OK : ena 11356, run 11356
attaching to current thread as disabled
OK : ena 987, run 987
attaching to CPU 0 as enabled
OK : ena 3717, run 3717
attaching to CPU 0 as enabled
OK : ena 2323, run 2323
test child finished with 0
---- end ----
Test events times: Ok
[root@jouet ~]#
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1458823940-24583-7-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/tests/Build | 1 | ||||
| -rw-r--r-- | tools/perf/tests/builtin-test.c | 4 | ||||
| -rw-r--r-- | tools/perf/tests/event-times.c | 236 | ||||
| -rw-r--r-- | tools/perf/tests/tests.h | 1 |
4 files changed, 242 insertions, 0 deletions
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 1ba628ed049a..449fe97a555f 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build | |||
| @@ -37,6 +37,7 @@ perf-y += topology.o | |||
| 37 | perf-y += cpumap.o | 37 | perf-y += cpumap.o |
| 38 | perf-y += stat.o | 38 | perf-y += stat.o |
| 39 | perf-y += event_update.o | 39 | perf-y += event_update.o |
| 40 | perf-y += event-times.o | ||
| 40 | 41 | ||
| 41 | $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build | 42 | $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build |
| 42 | $(call rule_mkdir) | 43 | $(call rule_mkdir) |
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index f2b1dcac45d3..93c467015e71 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
| @@ -204,6 +204,10 @@ static struct test generic_tests[] = { | |||
| 204 | .func = test__event_update, | 204 | .func = test__event_update, |
| 205 | }, | 205 | }, |
| 206 | { | 206 | { |
| 207 | .desc = "Test events times", | ||
| 208 | .func = test__event_times, | ||
| 209 | }, | ||
| 210 | { | ||
| 207 | .func = NULL, | 211 | .func = NULL, |
| 208 | }, | 212 | }, |
| 209 | }; | 213 | }; |
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c new file mode 100644 index 000000000000..95fb744f6628 --- /dev/null +++ b/tools/perf/tests/event-times.c | |||
| @@ -0,0 +1,236 @@ | |||
| 1 | #include <linux/compiler.h> | ||
| 2 | #include <string.h> | ||
| 3 | #include "tests.h" | ||
| 4 | #include "evlist.h" | ||
| 5 | #include "evsel.h" | ||
| 6 | #include "util.h" | ||
| 7 | #include "debug.h" | ||
| 8 | #include "thread_map.h" | ||
| 9 | #include "target.h" | ||
| 10 | |||
| 11 | static int attach__enable_on_exec(struct perf_evlist *evlist) | ||
| 12 | { | ||
| 13 | struct perf_evsel *evsel = perf_evlist__last(evlist); | ||
| 14 | struct target target = { | ||
| 15 | .uid = UINT_MAX, | ||
| 16 | }; | ||
| 17 | const char *argv[] = { "true", NULL, }; | ||
| 18 | char sbuf[STRERR_BUFSIZE]; | ||
| 19 | int err; | ||
| 20 | |||
| 21 | pr_debug("attaching to spawned child, enable on exec\n"); | ||
| 22 | |||
| 23 | err = perf_evlist__create_maps(evlist, &target); | ||
| 24 | if (err < 0) { | ||
| 25 | pr_debug("Not enough memory to create thread/cpu maps\n"); | ||
| 26 | return err; | ||
| 27 | } | ||
| 28 | |||
| 29 | err = perf_evlist__prepare_workload(evlist, &target, argv, false, NULL); | ||
| 30 | if (err < 0) { | ||
| 31 | pr_debug("Couldn't run the workload!\n"); | ||
| 32 | return err; | ||
| 33 | } | ||
| 34 | |||
| 35 | evsel->attr.enable_on_exec = 1; | ||
| 36 | |||
| 37 | err = perf_evlist__open(evlist); | ||
| 38 | if (err < 0) { | ||
| 39 | pr_debug("perf_evlist__open: %s\n", | ||
| 40 | strerror_r(errno, sbuf, sizeof(sbuf))); | ||
| 41 | return err; | ||
| 42 | } | ||
| 43 | |||
| 44 | return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL; | ||
| 45 | } | ||
| 46 | |||
| 47 | static int detach__enable_on_exec(struct perf_evlist *evlist) | ||
| 48 | { | ||
| 49 | waitpid(evlist->workload.pid, NULL, 0); | ||
| 50 | return 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int attach__current_disabled(struct perf_evlist *evlist) | ||
| 54 | { | ||
| 55 | struct perf_evsel *evsel = perf_evlist__last(evlist); | ||
| 56 | struct thread_map *threads; | ||
| 57 | int err; | ||
| 58 | |||
| 59 | pr_debug("attaching to current thread as disabled\n"); | ||
| 60 | |||
| 61 | threads = thread_map__new(-1, getpid(), UINT_MAX); | ||
| 62 | if (threads == NULL) { | ||
| 63 | pr_debug("thread_map__new\n"); | ||
| 64 | return -1; | ||
| 65 | } | ||
| 66 | |||
| 67 | evsel->attr.disabled = 1; | ||
| 68 | |||
| 69 | err = perf_evsel__open_per_thread(evsel, threads); | ||
| 70 | if (err) { | ||
| 71 | pr_debug("Failed to open event cpu-clock:u\n"); | ||
| 72 | return err; | ||
| 73 | } | ||
| 74 | |||
| 75 | thread_map__put(threads); | ||
| 76 | return perf_evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int attach__current_enabled(struct perf_evlist *evlist) | ||
| 80 | { | ||
| 81 | struct perf_evsel *evsel = perf_evlist__last(evlist); | ||
| 82 | struct thread_map *threads; | ||
| 83 | int err; | ||
| 84 | |||
| 85 | pr_debug("attaching to current thread as enabled\n"); | ||
| 86 | |||
| 87 | threads = thread_map__new(-1, getpid(), UINT_MAX); | ||
| 88 | if (threads == NULL) { | ||
| 89 | pr_debug("failed to call thread_map__new\n"); | ||
| 90 | return -1; | ||
| 91 | } | ||
| 92 | |||
| 93 | err = perf_evsel__open_per_thread(evsel, threads); | ||
| 94 | |||
| 95 | thread_map__put(threads); | ||
| 96 | return err == 0 ? TEST_OK : TEST_FAIL; | ||
| 97 | } | ||
| 98 | |||
| 99 | static int detach__disable(struct perf_evlist *evlist) | ||
| 100 | { | ||
| 101 | struct perf_evsel *evsel = perf_evlist__last(evlist); | ||
| 102 | |||
| 103 | return perf_evsel__enable(evsel); | ||
| 104 | } | ||
| 105 | |||
| 106 | static int attach__cpu_disabled(struct perf_evlist *evlist) | ||
| 107 | { | ||
| 108 | struct perf_evsel *evsel = perf_evlist__last(evlist); | ||
| 109 | struct cpu_map *cpus; | ||
| 110 | int err; | ||
| 111 | |||
| 112 | pr_debug("attaching to CPU 0 as enabled\n"); | ||
| 113 | |||
| 114 | cpus = cpu_map__new("0"); | ||
| 115 | if (cpus == NULL) { | ||
| 116 | pr_debug("failed to call cpu_map__new\n"); | ||
| 117 | return -1; | ||
| 118 | } | ||
| 119 | |||
| 120 | evsel->attr.disabled = 1; | ||
| 121 | |||
| 122 | err = perf_evsel__open_per_cpu(evsel, cpus); | ||
| 123 | if (err) { | ||
| 124 | if (err == -EACCES) | ||
| 125 | return TEST_SKIP; | ||
| 126 | |||
| 127 | pr_debug("Failed to open event cpu-clock:u\n"); | ||
| 128 | return err; | ||
| 129 | } | ||
| 130 | |||
| 131 | cpu_map__put(cpus); | ||
| 132 | return perf_evsel__enable(evsel); | ||
| 133 | } | ||
| 134 | |||
| 135 | static int attach__cpu_enabled(struct perf_evlist *evlist) | ||
| 136 | { | ||
| 137 | struct perf_evsel *evsel = perf_evlist__last(evlist); | ||
| 138 | struct cpu_map *cpus; | ||
| 139 | int err; | ||
| 140 | |||
| 141 | pr_debug("attaching to CPU 0 as enabled\n"); | ||
| 142 | |||
| 143 | cpus = cpu_map__new("0"); | ||
| 144 | if (cpus == NULL) { | ||
| 145 | pr_debug("failed to call cpu_map__new\n"); | ||
| 146 | return -1; | ||
| 147 | } | ||
| 148 | |||
| 149 | err = perf_evsel__open_per_cpu(evsel, cpus); | ||
| 150 | if (err == -EACCES) | ||
| 151 | return TEST_SKIP; | ||
| 152 | |||
| 153 | cpu_map__put(cpus); | ||
| 154 | return err ? TEST_FAIL : TEST_OK; | ||
| 155 | } | ||
| 156 | |||
| 157 | static int test_times(int (attach)(struct perf_evlist *), | ||
| 158 | int (detach)(struct perf_evlist *)) | ||
| 159 | { | ||
| 160 | struct perf_counts_values count; | ||
| 161 | struct perf_evlist *evlist = NULL; | ||
| 162 | struct perf_evsel *evsel; | ||
| 163 | int err = -1, i; | ||
| 164 | |||
| 165 | evlist = perf_evlist__new(); | ||
| 166 | if (!evlist) { | ||
| 167 | pr_debug("failed to create event list\n"); | ||
| 168 | goto out_err; | ||
| 169 | } | ||
| 170 | |||
| 171 | err = parse_events(evlist, "cpu-clock:u", NULL); | ||
| 172 | if (err) { | ||
| 173 | pr_debug("failed to parse event cpu-clock:u\n"); | ||
| 174 | goto out_err; | ||
| 175 | } | ||
| 176 | |||
| 177 | evsel = perf_evlist__last(evlist); | ||
| 178 | evsel->attr.read_format |= | ||
| 179 | PERF_FORMAT_TOTAL_TIME_ENABLED | | ||
| 180 | PERF_FORMAT_TOTAL_TIME_RUNNING; | ||
| 181 | |||
| 182 | err = attach(evlist); | ||
| 183 | if (err == TEST_SKIP) { | ||
| 184 | pr_debug(" SKIP : not enough rights\n"); | ||
| 185 | return err; | ||
| 186 | } | ||
| 187 | |||
| 188 | TEST_ASSERT_VAL("failed to attach", !err); | ||
| 189 | |||
| 190 | for (i = 0; i < 100000000; i++) { } | ||
| 191 | |||
| 192 | TEST_ASSERT_VAL("failed to detach", !detach(evlist)); | ||
| 193 | |||
| 194 | perf_evsel__read(evsel, 0, 0, &count); | ||
| 195 | |||
| 196 | err = !(count.ena == count.run); | ||
| 197 | |||
| 198 | pr_debug(" %s: ena %" PRIu64", run %" PRIu64"\n", | ||
| 199 | !err ? "OK " : "FAILED", | ||
| 200 | count.ena, count.run); | ||
| 201 | |||
| 202 | out_err: | ||
| 203 | if (evlist) | ||
| 204 | perf_evlist__delete(evlist); | ||
| 205 | return !err ? TEST_OK : TEST_FAIL; | ||
| 206 | } | ||
| 207 | |||
| 208 | /* | ||
| 209 | * This test creates software event 'cpu-clock' | ||
| 210 | * attaches it in several ways (explained below) | ||
| 211 | * and checks that enabled and running times | ||
| 212 | * match. | ||
| 213 | */ | ||
| 214 | int test__event_times(int subtest __maybe_unused) | ||
| 215 | { | ||
| 216 | int err, ret = 0; | ||
| 217 | |||
| 218 | #define _T(attach, detach) \ | ||
| 219 | err = test_times(attach, detach); \ | ||
| 220 | if (err && (ret == TEST_OK || ret == TEST_SKIP)) \ | ||
| 221 | ret = err; | ||
| 222 | |||
| 223 | /* attach on newly spawned process after exec */ | ||
| 224 | _T(attach__enable_on_exec, detach__enable_on_exec) | ||
| 225 | /* attach on current process as enabled */ | ||
| 226 | _T(attach__current_enabled, detach__disable) | ||
| 227 | /* attach on current process as disabled */ | ||
| 228 | _T(attach__current_disabled, detach__disable) | ||
| 229 | /* attach on cpu as disabled */ | ||
| 230 | _T(attach__cpu_disabled, detach__disable) | ||
| 231 | /* attach on cpu as enabled */ | ||
| 232 | _T(attach__cpu_enabled, detach__disable) | ||
| 233 | |||
| 234 | #undef _T | ||
| 235 | return ret; | ||
| 236 | } | ||
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 82b2b5e6ba7c..0fc946989cf0 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h | |||
| @@ -85,6 +85,7 @@ int test__synthesize_stat_config(int subtest); | |||
| 85 | int test__synthesize_stat(int subtest); | 85 | int test__synthesize_stat(int subtest); |
| 86 | int test__synthesize_stat_round(int subtest); | 86 | int test__synthesize_stat_round(int subtest); |
| 87 | int test__event_update(int subtest); | 87 | int test__event_update(int subtest); |
| 88 | int test__event_times(int subtest); | ||
| 88 | 89 | ||
| 89 | #if defined(__arm__) || defined(__aarch64__) | 90 | #if defined(__arm__) || defined(__aarch64__) |
| 90 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 91 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
