diff options
| -rw-r--r-- | tools/perf/builtin-test.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index e0c3f471f22..6c991529f62 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c | |||
| @@ -234,6 +234,85 @@ out: | |||
| 234 | return err; | 234 | return err; |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | #include "util/evsel.h" | ||
| 238 | #include <sys/types.h> | ||
| 239 | |||
| 240 | static int trace_event__id(const char *event_name) | ||
| 241 | { | ||
| 242 | char *filename; | ||
| 243 | int err = -1, fd; | ||
| 244 | |||
| 245 | if (asprintf(&filename, | ||
| 246 | "/sys/kernel/debug/tracing/events/syscalls/%s/id", | ||
| 247 | event_name) < 0) | ||
| 248 | return -1; | ||
| 249 | |||
| 250 | fd = open(filename, O_RDONLY); | ||
| 251 | if (fd >= 0) { | ||
| 252 | char id[16]; | ||
| 253 | if (read(fd, id, sizeof(id)) > 0) | ||
| 254 | err = atoi(id); | ||
| 255 | close(fd); | ||
| 256 | } | ||
| 257 | |||
| 258 | free(filename); | ||
| 259 | return err; | ||
| 260 | } | ||
| 261 | |||
| 262 | static int test__open_syscall_event(void) | ||
| 263 | { | ||
| 264 | int err = -1, fd; | ||
| 265 | struct thread_map *threads; | ||
| 266 | struct perf_evsel *evsel; | ||
| 267 | unsigned int nr_open_calls = 111, i; | ||
| 268 | int id = trace_event__id("sys_enter_open"); | ||
| 269 | |||
| 270 | if (id < 0) { | ||
| 271 | pr_debug("trace_event__id(\"sys_enter_open\") "); | ||
| 272 | return -1; | ||
| 273 | } | ||
| 274 | |||
| 275 | threads = thread_map__new(-1, getpid()); | ||
| 276 | if (threads == NULL) { | ||
| 277 | pr_debug("thread_map__new "); | ||
| 278 | return -1; | ||
| 279 | } | ||
| 280 | |||
| 281 | evsel = perf_evsel__new(PERF_TYPE_TRACEPOINT, id, 0); | ||
| 282 | if (evsel == NULL) { | ||
| 283 | pr_debug("perf_evsel__new "); | ||
| 284 | goto out_thread_map_delete; | ||
| 285 | } | ||
| 286 | |||
| 287 | if (perf_evsel__open_per_thread(evsel, threads) < 0) { | ||
| 288 | pr_debug("perf_evsel__open_per_thread "); | ||
| 289 | goto out_evsel_delete; | ||
| 290 | } | ||
| 291 | |||
| 292 | for (i = 0; i < nr_open_calls; ++i) { | ||
| 293 | fd = open("/etc/passwd", O_RDONLY); | ||
| 294 | close(fd); | ||
| 295 | } | ||
| 296 | |||
| 297 | if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) { | ||
| 298 | pr_debug("perf_evsel__open_read_on_cpu "); | ||
| 299 | goto out_close_fd; | ||
| 300 | } | ||
| 301 | |||
| 302 | if (evsel->counts->cpu[0].val != nr_open_calls) | ||
| 303 | pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %Ld ", | ||
| 304 | nr_open_calls, evsel->counts->cpu[0].val); | ||
| 305 | |||
| 306 | err = 0; | ||
| 307 | out_close_fd: | ||
| 308 | perf_evsel__close_fd(evsel, 1, threads->nr); | ||
| 309 | out_evsel_delete: | ||
| 310 | perf_evsel__delete(evsel); | ||
| 311 | out_thread_map_delete: | ||
| 312 | thread_map__delete(threads); | ||
| 313 | return err; | ||
| 314 | } | ||
| 315 | |||
| 237 | static struct test { | 316 | static struct test { |
| 238 | const char *desc; | 317 | const char *desc; |
| 239 | int (*func)(void); | 318 | int (*func)(void); |
| @@ -243,6 +322,10 @@ static struct test { | |||
| 243 | .func = test__vmlinux_matches_kallsyms, | 322 | .func = test__vmlinux_matches_kallsyms, |
| 244 | }, | 323 | }, |
| 245 | { | 324 | { |
| 325 | .desc = "detect open syscall event", | ||
| 326 | .func = test__open_syscall_event, | ||
| 327 | }, | ||
| 328 | { | ||
| 246 | .func = NULL, | 329 | .func = NULL, |
| 247 | }, | 330 | }, |
| 248 | }; | 331 | }; |
