0001
0002 #include <linux/compiler.h>
0003 #include <linux/string.h>
0004 #include <errno.h>
0005 #include <inttypes.h>
0006 #include <string.h>
0007 #include <sys/wait.h>
0008 #include <perf/cpumap.h>
0009 #include "tests.h"
0010 #include "evlist.h"
0011 #include "evsel.h"
0012 #include "debug.h"
0013 #include "parse-events.h"
0014 #include "thread_map.h"
0015 #include "target.h"
0016
0017 static int attach__enable_on_exec(struct evlist *evlist)
0018 {
0019 struct evsel *evsel = evlist__last(evlist);
0020 struct target target = {
0021 .uid = UINT_MAX,
0022 };
0023 const char *argv[] = { "true", NULL, };
0024 char sbuf[STRERR_BUFSIZE];
0025 int err;
0026
0027 pr_debug("attaching to spawned child, enable on exec\n");
0028
0029 err = evlist__create_maps(evlist, &target);
0030 if (err < 0) {
0031 pr_debug("Not enough memory to create thread/cpu maps\n");
0032 return err;
0033 }
0034
0035 err = evlist__prepare_workload(evlist, &target, argv, false, NULL);
0036 if (err < 0) {
0037 pr_debug("Couldn't run the workload!\n");
0038 return err;
0039 }
0040
0041 evsel->core.attr.enable_on_exec = 1;
0042
0043 err = evlist__open(evlist);
0044 if (err < 0) {
0045 pr_debug("perf_evlist__open: %s\n",
0046 str_error_r(errno, sbuf, sizeof(sbuf)));
0047 return err;
0048 }
0049
0050 return evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
0051 }
0052
0053 static int detach__enable_on_exec(struct evlist *evlist)
0054 {
0055 waitpid(evlist->workload.pid, NULL, 0);
0056 return 0;
0057 }
0058
0059 static int attach__current_disabled(struct evlist *evlist)
0060 {
0061 struct evsel *evsel = evlist__last(evlist);
0062 struct perf_thread_map *threads;
0063 int err;
0064
0065 pr_debug("attaching to current thread as disabled\n");
0066
0067 threads = thread_map__new(-1, getpid(), UINT_MAX);
0068 if (threads == NULL) {
0069 pr_debug("thread_map__new\n");
0070 return -1;
0071 }
0072
0073 evsel->core.attr.disabled = 1;
0074
0075 err = evsel__open_per_thread(evsel, threads);
0076 if (err) {
0077 pr_debug("Failed to open event cpu-clock:u\n");
0078 return err;
0079 }
0080
0081 perf_thread_map__put(threads);
0082 return evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;
0083 }
0084
0085 static int attach__current_enabled(struct evlist *evlist)
0086 {
0087 struct evsel *evsel = evlist__last(evlist);
0088 struct perf_thread_map *threads;
0089 int err;
0090
0091 pr_debug("attaching to current thread as enabled\n");
0092
0093 threads = thread_map__new(-1, getpid(), UINT_MAX);
0094 if (threads == NULL) {
0095 pr_debug("failed to call thread_map__new\n");
0096 return -1;
0097 }
0098
0099 err = evsel__open_per_thread(evsel, threads);
0100
0101 perf_thread_map__put(threads);
0102 return err == 0 ? TEST_OK : TEST_FAIL;
0103 }
0104
0105 static int detach__disable(struct evlist *evlist)
0106 {
0107 struct evsel *evsel = evlist__last(evlist);
0108
0109 return evsel__enable(evsel);
0110 }
0111
0112 static int attach__cpu_disabled(struct evlist *evlist)
0113 {
0114 struct evsel *evsel = evlist__last(evlist);
0115 struct perf_cpu_map *cpus;
0116 int err;
0117
0118 pr_debug("attaching to CPU 0 as enabled\n");
0119
0120 cpus = perf_cpu_map__new("0");
0121 if (cpus == NULL) {
0122 pr_debug("failed to call perf_cpu_map__new\n");
0123 return -1;
0124 }
0125
0126 evsel->core.attr.disabled = 1;
0127
0128 err = evsel__open_per_cpu(evsel, cpus, -1);
0129 if (err) {
0130 if (err == -EACCES)
0131 return TEST_SKIP;
0132
0133 pr_debug("Failed to open event cpu-clock:u\n");
0134 return err;
0135 }
0136
0137 perf_cpu_map__put(cpus);
0138 return evsel__enable(evsel);
0139 }
0140
0141 static int attach__cpu_enabled(struct evlist *evlist)
0142 {
0143 struct evsel *evsel = evlist__last(evlist);
0144 struct perf_cpu_map *cpus;
0145 int err;
0146
0147 pr_debug("attaching to CPU 0 as enabled\n");
0148
0149 cpus = perf_cpu_map__new("0");
0150 if (cpus == NULL) {
0151 pr_debug("failed to call perf_cpu_map__new\n");
0152 return -1;
0153 }
0154
0155 err = evsel__open_per_cpu(evsel, cpus, -1);
0156 if (err == -EACCES)
0157 return TEST_SKIP;
0158
0159 perf_cpu_map__put(cpus);
0160 return err ? TEST_FAIL : TEST_OK;
0161 }
0162
0163 static int test_times(int (attach)(struct evlist *),
0164 int (detach)(struct evlist *))
0165 {
0166 struct perf_counts_values count;
0167 struct evlist *evlist = NULL;
0168 struct evsel *evsel;
0169 int err = -1, i;
0170
0171 evlist = evlist__new();
0172 if (!evlist) {
0173 pr_debug("failed to create event list\n");
0174 goto out_err;
0175 }
0176
0177 err = parse_event(evlist, "cpu-clock:u");
0178 if (err) {
0179 pr_debug("failed to parse event cpu-clock:u\n");
0180 goto out_err;
0181 }
0182
0183 evsel = evlist__last(evlist);
0184 evsel->core.attr.read_format |=
0185 PERF_FORMAT_TOTAL_TIME_ENABLED |
0186 PERF_FORMAT_TOTAL_TIME_RUNNING;
0187
0188 err = attach(evlist);
0189 if (err == TEST_SKIP) {
0190 pr_debug(" SKIP : not enough rights\n");
0191 return err;
0192 }
0193
0194 TEST_ASSERT_VAL("failed to attach", !err);
0195
0196 for (i = 0; i < 100000000; i++) { }
0197
0198 TEST_ASSERT_VAL("failed to detach", !detach(evlist));
0199
0200 perf_evsel__read(&evsel->core, 0, 0, &count);
0201
0202 err = !(count.ena == count.run);
0203
0204 pr_debug(" %s: ena %" PRIu64", run %" PRIu64"\n",
0205 !err ? "OK " : "FAILED",
0206 count.ena, count.run);
0207
0208 out_err:
0209 evlist__delete(evlist);
0210 return !err ? TEST_OK : TEST_FAIL;
0211 }
0212
0213
0214
0215
0216
0217
0218
0219 static int test__event_times(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
0220 {
0221 int err, ret = 0;
0222
0223 #define _T(attach, detach) \
0224 err = test_times(attach, detach); \
0225 if (err && (ret == TEST_OK || ret == TEST_SKIP)) \
0226 ret = err;
0227
0228
0229 _T(attach__enable_on_exec, detach__enable_on_exec)
0230
0231 _T(attach__current_enabled, detach__disable)
0232
0233 _T(attach__current_disabled, detach__disable)
0234
0235 _T(attach__cpu_disabled, detach__disable)
0236
0237 _T(attach__cpu_enabled, detach__disable)
0238
0239 #undef _T
0240 return ret;
0241 }
0242
0243 DEFINE_SUITE("Event times", event_times);