0001
0002 #define _GNU_SOURCE
0003 #include <inttypes.h>
0004 #include <sched.h>
0005 #include <stdio.h>
0006 #include <stdarg.h>
0007 #include <unistd.h>
0008 #include <stdlib.h>
0009 #include <linux/perf_event.h>
0010 #include <linux/limits.h>
0011 #include <sys/types.h>
0012 #include <sys/wait.h>
0013 #include <sys/prctl.h>
0014 #include <perf/cpumap.h>
0015 #include <perf/threadmap.h>
0016 #include <perf/evlist.h>
0017 #include <perf/evsel.h>
0018 #include <perf/mmap.h>
0019 #include <perf/event.h>
0020 #include <internal/tests.h>
0021 #include <api/fs/fs.h>
0022 #include "tests.h"
0023 #include <internal/evsel.h>
0024
0025 #define EVENT_NUM 15
0026 #define WAIT_COUNT 100000000UL
0027
0028 static int libperf_print(enum libperf_print_level level,
0029 const char *fmt, va_list ap)
0030 {
0031 return vfprintf(stderr, fmt, ap);
0032 }
0033
0034 static int test_stat_cpu(void)
0035 {
0036 struct perf_cpu_map *cpus;
0037 struct perf_evlist *evlist;
0038 struct perf_evsel *evsel, *leader;
0039 struct perf_event_attr attr1 = {
0040 .type = PERF_TYPE_SOFTWARE,
0041 .config = PERF_COUNT_SW_CPU_CLOCK,
0042 };
0043 struct perf_event_attr attr2 = {
0044 .type = PERF_TYPE_SOFTWARE,
0045 .config = PERF_COUNT_SW_TASK_CLOCK,
0046 };
0047 int err, idx;
0048
0049 cpus = perf_cpu_map__new(NULL);
0050 __T("failed to create cpus", cpus);
0051
0052 evlist = perf_evlist__new();
0053 __T("failed to create evlist", evlist);
0054
0055 evsel = leader = perf_evsel__new(&attr1);
0056 __T("failed to create evsel1", evsel);
0057
0058 perf_evlist__add(evlist, evsel);
0059
0060 evsel = perf_evsel__new(&attr2);
0061 __T("failed to create evsel2", evsel);
0062
0063 perf_evlist__add(evlist, evsel);
0064
0065 perf_evlist__set_leader(evlist);
0066 __T("failed to set leader", leader->leader == leader);
0067 __T("failed to set leader", evsel->leader == leader);
0068
0069 perf_evlist__set_maps(evlist, cpus, NULL);
0070
0071 err = perf_evlist__open(evlist);
0072 __T("failed to open evlist", err == 0);
0073
0074 perf_evlist__for_each_evsel(evlist, evsel) {
0075 cpus = perf_evsel__cpus(evsel);
0076
0077 for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) {
0078 struct perf_counts_values counts = { .val = 0 };
0079
0080 perf_evsel__read(evsel, idx, 0, &counts);
0081 __T("failed to read value for evsel", counts.val != 0);
0082 }
0083 }
0084
0085 perf_evlist__close(evlist);
0086 perf_evlist__delete(evlist);
0087
0088 perf_cpu_map__put(cpus);
0089 return 0;
0090 }
0091
0092 static int test_stat_thread(void)
0093 {
0094 struct perf_counts_values counts = { .val = 0 };
0095 struct perf_thread_map *threads;
0096 struct perf_evlist *evlist;
0097 struct perf_evsel *evsel, *leader;
0098 struct perf_event_attr attr1 = {
0099 .type = PERF_TYPE_SOFTWARE,
0100 .config = PERF_COUNT_SW_CPU_CLOCK,
0101 };
0102 struct perf_event_attr attr2 = {
0103 .type = PERF_TYPE_SOFTWARE,
0104 .config = PERF_COUNT_SW_TASK_CLOCK,
0105 };
0106 int err;
0107
0108 threads = perf_thread_map__new_dummy();
0109 __T("failed to create threads", threads);
0110
0111 perf_thread_map__set_pid(threads, 0, 0);
0112
0113 evlist = perf_evlist__new();
0114 __T("failed to create evlist", evlist);
0115
0116 evsel = leader = perf_evsel__new(&attr1);
0117 __T("failed to create evsel1", evsel);
0118
0119 perf_evlist__add(evlist, evsel);
0120
0121 evsel = perf_evsel__new(&attr2);
0122 __T("failed to create evsel2", evsel);
0123
0124 perf_evlist__add(evlist, evsel);
0125
0126 perf_evlist__set_leader(evlist);
0127 __T("failed to set leader", leader->leader == leader);
0128 __T("failed to set leader", evsel->leader == leader);
0129
0130 perf_evlist__set_maps(evlist, NULL, threads);
0131
0132 err = perf_evlist__open(evlist);
0133 __T("failed to open evlist", err == 0);
0134
0135 perf_evlist__for_each_evsel(evlist, evsel) {
0136 perf_evsel__read(evsel, 0, 0, &counts);
0137 __T("failed to read value for evsel", counts.val != 0);
0138 }
0139
0140 perf_evlist__close(evlist);
0141 perf_evlist__delete(evlist);
0142
0143 perf_thread_map__put(threads);
0144 return 0;
0145 }
0146
0147 static int test_stat_thread_enable(void)
0148 {
0149 struct perf_counts_values counts = { .val = 0 };
0150 struct perf_thread_map *threads;
0151 struct perf_evlist *evlist;
0152 struct perf_evsel *evsel, *leader;
0153 struct perf_event_attr attr1 = {
0154 .type = PERF_TYPE_SOFTWARE,
0155 .config = PERF_COUNT_SW_CPU_CLOCK,
0156 .disabled = 1,
0157 };
0158 struct perf_event_attr attr2 = {
0159 .type = PERF_TYPE_SOFTWARE,
0160 .config = PERF_COUNT_SW_TASK_CLOCK,
0161 .disabled = 1,
0162 };
0163 int err;
0164
0165 threads = perf_thread_map__new_dummy();
0166 __T("failed to create threads", threads);
0167
0168 perf_thread_map__set_pid(threads, 0, 0);
0169
0170 evlist = perf_evlist__new();
0171 __T("failed to create evlist", evlist);
0172
0173 evsel = leader = perf_evsel__new(&attr1);
0174 __T("failed to create evsel1", evsel);
0175
0176 perf_evlist__add(evlist, evsel);
0177
0178 evsel = perf_evsel__new(&attr2);
0179 __T("failed to create evsel2", evsel);
0180
0181 perf_evlist__add(evlist, evsel);
0182
0183 perf_evlist__set_leader(evlist);
0184 __T("failed to set leader", leader->leader == leader);
0185 __T("failed to set leader", evsel->leader == leader);
0186
0187 perf_evlist__set_maps(evlist, NULL, threads);
0188
0189 err = perf_evlist__open(evlist);
0190 __T("failed to open evlist", err == 0);
0191
0192 perf_evlist__for_each_evsel(evlist, evsel) {
0193 perf_evsel__read(evsel, 0, 0, &counts);
0194 __T("failed to read value for evsel", counts.val == 0);
0195 }
0196
0197 perf_evlist__enable(evlist);
0198
0199 perf_evlist__for_each_evsel(evlist, evsel) {
0200 perf_evsel__read(evsel, 0, 0, &counts);
0201 __T("failed to read value for evsel", counts.val != 0);
0202 }
0203
0204 perf_evlist__disable(evlist);
0205
0206 perf_evlist__close(evlist);
0207 perf_evlist__delete(evlist);
0208
0209 perf_thread_map__put(threads);
0210 return 0;
0211 }
0212
0213 static int test_mmap_thread(void)
0214 {
0215 struct perf_evlist *evlist;
0216 struct perf_evsel *evsel;
0217 struct perf_mmap *map;
0218 struct perf_cpu_map *cpus;
0219 struct perf_thread_map *threads;
0220 struct perf_event_attr attr = {
0221 .type = PERF_TYPE_TRACEPOINT,
0222 .sample_period = 1,
0223 .wakeup_watermark = 1,
0224 .disabled = 1,
0225 };
0226 char path[PATH_MAX];
0227 int id, err, pid, go_pipe[2];
0228 union perf_event *event;
0229 int count = 0;
0230
0231 snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
0232 sysfs__mountpoint());
0233
0234 if (filename__read_int(path, &id)) {
0235 tests_failed++;
0236 fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
0237 return -1;
0238 }
0239
0240 attr.config = id;
0241
0242 err = pipe(go_pipe);
0243 __T("failed to create pipe", err == 0);
0244
0245 fflush(NULL);
0246
0247 pid = fork();
0248 if (!pid) {
0249 int i;
0250 char bf;
0251
0252 read(go_pipe[0], &bf, 1);
0253
0254
0255 for (i = 0; i < 100; i++)
0256 prctl(0, 0, 0, 0, 0);
0257
0258 exit(0);
0259 }
0260
0261 threads = perf_thread_map__new_dummy();
0262 __T("failed to create threads", threads);
0263
0264 cpus = perf_cpu_map__dummy_new();
0265 __T("failed to create cpus", cpus);
0266
0267 perf_thread_map__set_pid(threads, 0, pid);
0268
0269 evlist = perf_evlist__new();
0270 __T("failed to create evlist", evlist);
0271
0272 evsel = perf_evsel__new(&attr);
0273 __T("failed to create evsel1", evsel);
0274 __T("failed to set leader", evsel->leader == evsel);
0275
0276 perf_evlist__add(evlist, evsel);
0277
0278 perf_evlist__set_maps(evlist, cpus, threads);
0279
0280 err = perf_evlist__open(evlist);
0281 __T("failed to open evlist", err == 0);
0282
0283 err = perf_evlist__mmap(evlist, 4);
0284 __T("failed to mmap evlist", err == 0);
0285
0286 perf_evlist__enable(evlist);
0287
0288
0289 write(go_pipe[1], "A", 1);
0290 waitpid(pid, NULL, 0);
0291
0292
0293
0294
0295
0296
0297 perf_evlist__for_each_mmap(evlist, map, false) {
0298 if (perf_mmap__read_init(map) < 0)
0299 continue;
0300
0301 while ((event = perf_mmap__read_event(map)) != NULL) {
0302 count++;
0303 perf_mmap__consume(map);
0304 }
0305
0306 perf_mmap__read_done(map);
0307 }
0308
0309
0310 perf_evlist__delete(evlist);
0311
0312 perf_thread_map__put(threads);
0313 perf_cpu_map__put(cpus);
0314
0315
0316
0317
0318
0319 __T("failed count", count == 100);
0320
0321 return 0;
0322 }
0323
0324 static int test_mmap_cpus(void)
0325 {
0326 struct perf_evlist *evlist;
0327 struct perf_evsel *evsel;
0328 struct perf_mmap *map;
0329 struct perf_cpu_map *cpus;
0330 struct perf_event_attr attr = {
0331 .type = PERF_TYPE_TRACEPOINT,
0332 .sample_period = 1,
0333 .wakeup_watermark = 1,
0334 .disabled = 1,
0335 };
0336 cpu_set_t saved_mask;
0337 char path[PATH_MAX];
0338 int id, err, tmp;
0339 struct perf_cpu cpu;
0340 union perf_event *event;
0341 int count = 0;
0342
0343 snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
0344 sysfs__mountpoint());
0345
0346 if (filename__read_int(path, &id)) {
0347 fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
0348 return -1;
0349 }
0350
0351 attr.config = id;
0352
0353 cpus = perf_cpu_map__new(NULL);
0354 __T("failed to create cpus", cpus);
0355
0356 evlist = perf_evlist__new();
0357 __T("failed to create evlist", evlist);
0358
0359 evsel = perf_evsel__new(&attr);
0360 __T("failed to create evsel1", evsel);
0361 __T("failed to set leader", evsel->leader == evsel);
0362
0363 perf_evlist__add(evlist, evsel);
0364
0365 perf_evlist__set_maps(evlist, cpus, NULL);
0366
0367 err = perf_evlist__open(evlist);
0368 __T("failed to open evlist", err == 0);
0369
0370 err = perf_evlist__mmap(evlist, 4);
0371 __T("failed to mmap evlist", err == 0);
0372
0373 perf_evlist__enable(evlist);
0374
0375 err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
0376 __T("sched_getaffinity failed", err == 0);
0377
0378 perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
0379 cpu_set_t mask;
0380
0381 CPU_ZERO(&mask);
0382 CPU_SET(cpu.cpu, &mask);
0383
0384 err = sched_setaffinity(0, sizeof(mask), &mask);
0385 __T("sched_setaffinity failed", err == 0);
0386
0387 prctl(0, 0, 0, 0, 0);
0388 }
0389
0390 err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask);
0391 __T("sched_setaffinity failed", err == 0);
0392
0393 perf_evlist__disable(evlist);
0394
0395 perf_evlist__for_each_mmap(evlist, map, false) {
0396 if (perf_mmap__read_init(map) < 0)
0397 continue;
0398
0399 while ((event = perf_mmap__read_event(map)) != NULL) {
0400 count++;
0401 perf_mmap__consume(map);
0402 }
0403
0404 perf_mmap__read_done(map);
0405 }
0406
0407
0408 perf_evlist__delete(evlist);
0409
0410
0411
0412
0413
0414 __T("failed count", count >= perf_cpu_map__nr(cpus));
0415
0416 perf_cpu_map__put(cpus);
0417
0418 return 0;
0419 }
0420
0421 static double display_error(long long average,
0422 long long high,
0423 long long low,
0424 long long expected)
0425 {
0426 double error;
0427
0428 error = (((double)average - expected) / expected) * 100.0;
0429
0430 __T_VERBOSE(" Expected: %lld\n", expected);
0431 __T_VERBOSE(" High: %lld Low: %lld Average: %lld\n",
0432 high, low, average);
0433
0434 __T_VERBOSE(" Average Error = %.2f%%\n", error);
0435
0436 return error;
0437 }
0438
0439 static int test_stat_multiplexing(void)
0440 {
0441 struct perf_counts_values expected_counts = { .val = 0 };
0442 struct perf_counts_values counts[EVENT_NUM] = {{ .val = 0 },};
0443 struct perf_thread_map *threads;
0444 struct perf_evlist *evlist;
0445 struct perf_evsel *evsel;
0446 struct perf_event_attr attr = {
0447 .type = PERF_TYPE_HARDWARE,
0448 .config = PERF_COUNT_HW_INSTRUCTIONS,
0449 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
0450 PERF_FORMAT_TOTAL_TIME_RUNNING,
0451 .disabled = 1,
0452 };
0453 int err, i, nonzero = 0;
0454 unsigned long count;
0455 long long max = 0, min = 0, avg = 0;
0456 double error = 0.0;
0457 s8 scaled = 0;
0458
0459
0460 threads = perf_thread_map__new_dummy();
0461 __T("failed to create threads", threads);
0462
0463 perf_thread_map__set_pid(threads, 0, 0);
0464
0465 evsel = perf_evsel__new(&attr);
0466 __T("failed to create evsel", evsel);
0467
0468 err = perf_evsel__open(evsel, NULL, threads);
0469 __T("failed to open evsel", err == 0);
0470
0471 err = perf_evsel__enable(evsel);
0472 __T("failed to enable evsel", err == 0);
0473
0474
0475 count = WAIT_COUNT;
0476 while (count--)
0477 ;
0478
0479 perf_evsel__read(evsel, 0, 0, &expected_counts);
0480 __T("failed to read value for evsel", expected_counts.val != 0);
0481 __T("failed to read non-multiplexing event count",
0482 expected_counts.ena == expected_counts.run);
0483
0484 err = perf_evsel__disable(evsel);
0485 __T("failed to enable evsel", err == 0);
0486
0487 perf_evsel__close(evsel);
0488 perf_evsel__delete(evsel);
0489
0490 perf_thread_map__put(threads);
0491
0492
0493 threads = perf_thread_map__new_dummy();
0494 __T("failed to create threads", threads);
0495
0496 perf_thread_map__set_pid(threads, 0, 0);
0497
0498 evlist = perf_evlist__new();
0499 __T("failed to create evlist", evlist);
0500
0501 for (i = 0; i < EVENT_NUM; i++) {
0502 evsel = perf_evsel__new(&attr);
0503 __T("failed to create evsel", evsel);
0504
0505 perf_evlist__add(evlist, evsel);
0506 }
0507 perf_evlist__set_maps(evlist, NULL, threads);
0508
0509 err = perf_evlist__open(evlist);
0510 __T("failed to open evlist", err == 0);
0511
0512 perf_evlist__enable(evlist);
0513
0514
0515 count = WAIT_COUNT;
0516 while (count--)
0517 ;
0518
0519 i = 0;
0520 perf_evlist__for_each_evsel(evlist, evsel) {
0521 perf_evsel__read(evsel, 0, 0, &counts[i]);
0522 __T("failed to read value for evsel", counts[i].val != 0);
0523 i++;
0524 }
0525
0526 perf_evlist__disable(evlist);
0527
0528 min = counts[0].val;
0529 for (i = 0; i < EVENT_NUM; i++) {
0530 __T_VERBOSE("Event %2d -- Raw count = %" PRIu64 ", run = %" PRIu64 ", enable = %" PRIu64 "\n",
0531 i, counts[i].val, counts[i].run, counts[i].ena);
0532
0533 perf_counts_values__scale(&counts[i], true, &scaled);
0534 if (scaled == 1) {
0535 __T_VERBOSE("\t Scaled count = %" PRIu64 " (%.2lf%%, %" PRIu64 "/%" PRIu64 ")\n",
0536 counts[i].val,
0537 (double)counts[i].run / (double)counts[i].ena * 100.0,
0538 counts[i].run, counts[i].ena);
0539 } else if (scaled == -1) {
0540 __T_VERBOSE("\t Not Running\n");
0541 } else {
0542 __T_VERBOSE("\t Not Scaling\n");
0543 }
0544
0545 if (counts[i].val > max)
0546 max = counts[i].val;
0547
0548 if (counts[i].val < min)
0549 min = counts[i].val;
0550
0551 avg += counts[i].val;
0552
0553 if (counts[i].val != 0)
0554 nonzero++;
0555 }
0556
0557 if (nonzero != 0)
0558 avg = avg / nonzero;
0559 else
0560 avg = 0;
0561
0562 error = display_error(avg, max, min, expected_counts.val);
0563
0564 __T("Error out of range!", ((error <= 1.0) && (error >= -1.0)));
0565
0566 perf_evlist__close(evlist);
0567 perf_evlist__delete(evlist);
0568
0569 perf_thread_map__put(threads);
0570
0571 return 0;
0572 }
0573
0574 int test_evlist(int argc, char **argv)
0575 {
0576 __T_START;
0577
0578 libperf_init(libperf_print);
0579
0580 test_stat_cpu();
0581 test_stat_thread();
0582 test_stat_thread_enable();
0583 test_mmap_thread();
0584 test_mmap_cpus();
0585 test_stat_multiplexing();
0586
0587 __T_END;
0588 return tests_failed == 0 ? 0 : -1;
0589 }