1 // SPDX-License-Identifier: GPL-2.0 2 #define _GNU_SOURCE // needed for sched.h to get sched_[gs]etaffinity and CPU_(ZERO,SET) 3 #include <sched.h> 4 #include <stdio.h> 5 #include <stdarg.h> 6 #include <unistd.h> 7 #include <stdlib.h> 8 #include <linux/perf_event.h> 9 #include <linux/limits.h> 10 #include <sys/types.h> 11 #include <sys/wait.h> 12 #include <sys/prctl.h> 13 #include <perf/cpumap.h> 14 #include <perf/threadmap.h> 15 #include <perf/evlist.h> 16 #include <perf/evsel.h> 17 #include <perf/mmap.h> 18 #include <perf/event.h> 19 #include <internal/tests.h> 20 #include <api/fs/fs.h> 21 #include "tests.h" 22 #include <internal/evsel.h> 23 24 #define EVENT_NUM 15 25 #define WAIT_COUNT 100000000UL 26 27 static int libperf_print(enum libperf_print_level level, 28 const char *fmt, va_list ap) 29 { 30 return vfprintf(stderr, fmt, ap); 31 } 32 33 static int test_stat_cpu(void) 34 { 35 struct perf_cpu_map *cpus; 36 struct perf_evlist *evlist; 37 struct perf_evsel *evsel, *leader; 38 struct perf_event_attr attr1 = { 39 .type = PERF_TYPE_SOFTWARE, 40 .config = PERF_COUNT_SW_CPU_CLOCK, 41 }; 42 struct perf_event_attr attr2 = { 43 .type = PERF_TYPE_SOFTWARE, 44 .config = PERF_COUNT_SW_TASK_CLOCK, 45 }; 46 int err, idx; 47 48 cpus = perf_cpu_map__new(NULL); 49 __T("failed to create cpus", cpus); 50 51 evlist = perf_evlist__new(); 52 __T("failed to create evlist", evlist); 53 54 evsel = leader = perf_evsel__new(&attr1); 55 __T("failed to create evsel1", evsel); 56 57 perf_evlist__add(evlist, evsel); 58 59 evsel = perf_evsel__new(&attr2); 60 __T("failed to create evsel2", evsel); 61 62 perf_evlist__add(evlist, evsel); 63 64 perf_evlist__set_leader(evlist); 65 __T("failed to set leader", leader->leader == leader); 66 __T("failed to set leader", evsel->leader == leader); 67 68 perf_evlist__set_maps(evlist, cpus, NULL); 69 70 err = perf_evlist__open(evlist); 71 __T("failed to open evsel", err == 0); 72 73 perf_evlist__for_each_evsel(evlist, evsel) { 74 cpus = perf_evsel__cpus(evsel); 75 76 for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) { 77 struct perf_counts_values counts = { .val = 0 }; 78 79 perf_evsel__read(evsel, idx, 0, &counts); 80 __T("failed to read value for evsel", counts.val != 0); 81 } 82 } 83 84 perf_evlist__close(evlist); 85 perf_evlist__delete(evlist); 86 87 perf_cpu_map__put(cpus); 88 return 0; 89 } 90 91 static int test_stat_thread(void) 92 { 93 struct perf_counts_values counts = { .val = 0 }; 94 struct perf_thread_map *threads; 95 struct perf_evlist *evlist; 96 struct perf_evsel *evsel, *leader; 97 struct perf_event_attr attr1 = { 98 .type = PERF_TYPE_SOFTWARE, 99 .config = PERF_COUNT_SW_CPU_CLOCK, 100 }; 101 struct perf_event_attr attr2 = { 102 .type = PERF_TYPE_SOFTWARE, 103 .config = PERF_COUNT_SW_TASK_CLOCK, 104 }; 105 int err; 106 107 threads = perf_thread_map__new_dummy(); 108 __T("failed to create threads", threads); 109 110 perf_thread_map__set_pid(threads, 0, 0); 111 112 evlist = perf_evlist__new(); 113 __T("failed to create evlist", evlist); 114 115 evsel = leader = perf_evsel__new(&attr1); 116 __T("failed to create evsel1", evsel); 117 118 perf_evlist__add(evlist, evsel); 119 120 evsel = perf_evsel__new(&attr2); 121 __T("failed to create evsel2", evsel); 122 123 perf_evlist__add(evlist, evsel); 124 125 perf_evlist__set_leader(evlist); 126 __T("failed to set leader", leader->leader == leader); 127 __T("failed to set leader", evsel->leader == leader); 128 129 perf_evlist__set_maps(evlist, NULL, threads); 130 131 err = perf_evlist__open(evlist); 132 __T("failed to open evsel", err == 0); 133 134 perf_evlist__for_each_evsel(evlist, evsel) { 135 perf_evsel__read(evsel, 0, 0, &counts); 136 __T("failed to read value for evsel", counts.val != 0); 137 } 138 139 perf_evlist__close(evlist); 140 perf_evlist__delete(evlist); 141 142 perf_thread_map__put(threads); 143 return 0; 144 } 145 146 static int test_stat_thread_enable(void) 147 { 148 struct perf_counts_values counts = { .val = 0 }; 149 struct perf_thread_map *threads; 150 struct perf_evlist *evlist; 151 struct perf_evsel *evsel, *leader; 152 struct perf_event_attr attr1 = { 153 .type = PERF_TYPE_SOFTWARE, 154 .config = PERF_COUNT_SW_CPU_CLOCK, 155 .disabled = 1, 156 }; 157 struct perf_event_attr attr2 = { 158 .type = PERF_TYPE_SOFTWARE, 159 .config = PERF_COUNT_SW_TASK_CLOCK, 160 .disabled = 1, 161 }; 162 int err; 163 164 threads = perf_thread_map__new_dummy(); 165 __T("failed to create threads", threads); 166 167 perf_thread_map__set_pid(threads, 0, 0); 168 169 evlist = perf_evlist__new(); 170 __T("failed to create evlist", evlist); 171 172 evsel = leader = perf_evsel__new(&attr1); 173 __T("failed to create evsel1", evsel); 174 175 perf_evlist__add(evlist, evsel); 176 177 evsel = perf_evsel__new(&attr2); 178 __T("failed to create evsel2", evsel); 179 180 perf_evlist__add(evlist, evsel); 181 182 perf_evlist__set_leader(evlist); 183 __T("failed to set leader", leader->leader == leader); 184 __T("failed to set leader", evsel->leader == leader); 185 186 perf_evlist__set_maps(evlist, NULL, threads); 187 188 err = perf_evlist__open(evlist); 189 __T("failed to open evsel", err == 0); 190 191 perf_evlist__for_each_evsel(evlist, evsel) { 192 perf_evsel__read(evsel, 0, 0, &counts); 193 __T("failed to read value for evsel", counts.val == 0); 194 } 195 196 perf_evlist__enable(evlist); 197 198 perf_evlist__for_each_evsel(evlist, evsel) { 199 perf_evsel__read(evsel, 0, 0, &counts); 200 __T("failed to read value for evsel", counts.val != 0); 201 } 202 203 perf_evlist__disable(evlist); 204 205 perf_evlist__close(evlist); 206 perf_evlist__delete(evlist); 207 208 perf_thread_map__put(threads); 209 return 0; 210 } 211 212 static int test_mmap_thread(void) 213 { 214 struct perf_evlist *evlist; 215 struct perf_evsel *evsel; 216 struct perf_mmap *map; 217 struct perf_cpu_map *cpus; 218 struct perf_thread_map *threads; 219 struct perf_event_attr attr = { 220 .type = PERF_TYPE_TRACEPOINT, 221 .sample_period = 1, 222 .wakeup_watermark = 1, 223 .disabled = 1, 224 }; 225 char path[PATH_MAX]; 226 int id, err, pid, go_pipe[2]; 227 union perf_event *event; 228 int count = 0; 229 230 snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id", 231 sysfs__mountpoint()); 232 233 if (filename__read_int(path, &id)) { 234 tests_failed++; 235 fprintf(stderr, "error: failed to get tracepoint id: %s\n", path); 236 return -1; 237 } 238 239 attr.config = id; 240 241 err = pipe(go_pipe); 242 __T("failed to create pipe", err == 0); 243 244 fflush(NULL); 245 246 pid = fork(); 247 if (!pid) { 248 int i; 249 char bf; 250 251 read(go_pipe[0], &bf, 1); 252 253 /* Generate 100 prctl calls. */ 254 for (i = 0; i < 100; i++) 255 prctl(0, 0, 0, 0, 0); 256 257 exit(0); 258 } 259 260 threads = perf_thread_map__new_dummy(); 261 __T("failed to create threads", threads); 262 263 cpus = perf_cpu_map__dummy_new(); 264 __T("failed to create cpus", cpus); 265 266 perf_thread_map__set_pid(threads, 0, pid); 267 268 evlist = perf_evlist__new(); 269 __T("failed to create evlist", evlist); 270 271 evsel = perf_evsel__new(&attr); 272 __T("failed to create evsel1", evsel); 273 __T("failed to set leader", evsel->leader == evsel); 274 275 perf_evlist__add(evlist, evsel); 276 277 perf_evlist__set_maps(evlist, cpus, threads); 278 279 err = perf_evlist__open(evlist); 280 __T("failed to open evlist", err == 0); 281 282 err = perf_evlist__mmap(evlist, 4); 283 __T("failed to mmap evlist", err == 0); 284 285 perf_evlist__enable(evlist); 286 287 /* kick the child and wait for it to finish */ 288 write(go_pipe[1], "A", 1); 289 waitpid(pid, NULL, 0); 290 291 /* 292 * There's no need to call perf_evlist__disable, 293 * monitored process is dead now. 294 */ 295 296 perf_evlist__for_each_mmap(evlist, map, false) { 297 if (perf_mmap__read_init(map) < 0) 298 continue; 299 300 while ((event = perf_mmap__read_event(map)) != NULL) { 301 count++; 302 perf_mmap__consume(map); 303 } 304 305 perf_mmap__read_done(map); 306 } 307 308 /* calls perf_evlist__munmap/perf_evlist__close */ 309 perf_evlist__delete(evlist); 310 311 perf_thread_map__put(threads); 312 perf_cpu_map__put(cpus); 313 314 /* 315 * The generated prctl calls should match the 316 * number of events in the buffer. 317 */ 318 __T("failed count", count == 100); 319 320 return 0; 321 } 322 323 static int test_mmap_cpus(void) 324 { 325 struct perf_evlist *evlist; 326 struct perf_evsel *evsel; 327 struct perf_mmap *map; 328 struct perf_cpu_map *cpus; 329 struct perf_event_attr attr = { 330 .type = PERF_TYPE_TRACEPOINT, 331 .sample_period = 1, 332 .wakeup_watermark = 1, 333 .disabled = 1, 334 }; 335 cpu_set_t saved_mask; 336 char path[PATH_MAX]; 337 int id, err, tmp; 338 struct perf_cpu cpu; 339 union perf_event *event; 340 int count = 0; 341 342 snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id", 343 sysfs__mountpoint()); 344 345 if (filename__read_int(path, &id)) { 346 fprintf(stderr, "error: failed to get tracepoint id: %s\n", path); 347 return -1; 348 } 349 350 attr.config = id; 351 352 cpus = perf_cpu_map__new(NULL); 353 __T("failed to create cpus", cpus); 354 355 evlist = perf_evlist__new(); 356 __T("failed to create evlist", evlist); 357 358 evsel = perf_evsel__new(&attr); 359 __T("failed to create evsel1", evsel); 360 __T("failed to set leader", evsel->leader == evsel); 361 362 perf_evlist__add(evlist, evsel); 363 364 perf_evlist__set_maps(evlist, cpus, NULL); 365 366 err = perf_evlist__open(evlist); 367 __T("failed to open evlist", err == 0); 368 369 err = perf_evlist__mmap(evlist, 4); 370 __T("failed to mmap evlist", err == 0); 371 372 perf_evlist__enable(evlist); 373 374 err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask); 375 __T("sched_getaffinity failed", err == 0); 376 377 perf_cpu_map__for_each_cpu(cpu, tmp, cpus) { 378 cpu_set_t mask; 379 380 CPU_ZERO(&mask); 381 CPU_SET(cpu.cpu, &mask); 382 383 err = sched_setaffinity(0, sizeof(mask), &mask); 384 __T("sched_setaffinity failed", err == 0); 385 386 prctl(0, 0, 0, 0, 0); 387 } 388 389 err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask); 390 __T("sched_setaffinity failed", err == 0); 391 392 perf_evlist__disable(evlist); 393 394 perf_evlist__for_each_mmap(evlist, map, false) { 395 if (perf_mmap__read_init(map) < 0) 396 continue; 397 398 while ((event = perf_mmap__read_event(map)) != NULL) { 399 count++; 400 perf_mmap__consume(map); 401 } 402 403 perf_mmap__read_done(map); 404 } 405 406 /* calls perf_evlist__munmap/perf_evlist__close */ 407 perf_evlist__delete(evlist); 408 409 /* 410 * The generated prctl events should match the 411 * number of cpus or be bigger (we are system-wide). 412 */ 413 __T("failed count", count >= perf_cpu_map__nr(cpus)); 414 415 perf_cpu_map__put(cpus); 416 417 return 0; 418 } 419 420 static double display_error(long long average, 421 long long high, 422 long long low, 423 long long expected) 424 { 425 double error; 426 427 error = (((double)average - expected) / expected) * 100.0; 428 429 __T_VERBOSE(" Expected: %lld\n", expected); 430 __T_VERBOSE(" High: %lld Low: %lld Average: %lld\n", 431 high, low, average); 432 433 __T_VERBOSE(" Average Error = %.2f%%\n", error); 434 435 return error; 436 } 437 438 static int test_stat_multiplexing(void) 439 { 440 struct perf_counts_values expected_counts = { .val = 0 }; 441 struct perf_counts_values counts[EVENT_NUM] = {{ .val = 0 },}; 442 struct perf_thread_map *threads; 443 struct perf_evlist *evlist; 444 struct perf_evsel *evsel; 445 struct perf_event_attr attr = { 446 .type = PERF_TYPE_HARDWARE, 447 .config = PERF_COUNT_HW_INSTRUCTIONS, 448 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 449 PERF_FORMAT_TOTAL_TIME_RUNNING, 450 .disabled = 1, 451 }; 452 int err, i, nonzero = 0; 453 unsigned long count; 454 long long max = 0, min = 0, avg = 0; 455 double error = 0.0; 456 s8 scaled = 0; 457 458 /* read for non-multiplexing event count */ 459 threads = perf_thread_map__new_dummy(); 460 __T("failed to create threads", threads); 461 462 perf_thread_map__set_pid(threads, 0, 0); 463 464 evsel = perf_evsel__new(&attr); 465 __T("failed to create evsel", evsel); 466 467 err = perf_evsel__open(evsel, NULL, threads); 468 __T("failed to open evsel", err == 0); 469 470 err = perf_evsel__enable(evsel); 471 __T("failed to enable evsel", err == 0); 472 473 /* wait loop */ 474 count = WAIT_COUNT; 475 while (count--) 476 ; 477 478 perf_evsel__read(evsel, 0, 0, &expected_counts); 479 __T("failed to read value for evsel", expected_counts.val != 0); 480 __T("failed to read non-multiplexing event count", 481 expected_counts.ena == expected_counts.run); 482 483 err = perf_evsel__disable(evsel); 484 __T("failed to enable evsel", err == 0); 485 486 perf_evsel__close(evsel); 487 perf_evsel__delete(evsel); 488 489 perf_thread_map__put(threads); 490 491 /* read for multiplexing event count */ 492 threads = perf_thread_map__new_dummy(); 493 __T("failed to create threads", threads); 494 495 perf_thread_map__set_pid(threads, 0, 0); 496 497 evlist = perf_evlist__new(); 498 __T("failed to create evlist", evlist); 499 500 for (i = 0; i < EVENT_NUM; i++) { 501 evsel = perf_evsel__new(&attr); 502 __T("failed to create evsel", evsel); 503 504 perf_evlist__add(evlist, evsel); 505 } 506 perf_evlist__set_maps(evlist, NULL, threads); 507 508 err = perf_evlist__open(evlist); 509 __T("failed to open evsel", err == 0); 510 511 perf_evlist__enable(evlist); 512 513 /* wait loop */ 514 count = WAIT_COUNT; 515 while (count--) 516 ; 517 518 i = 0; 519 perf_evlist__for_each_evsel(evlist, evsel) { 520 perf_evsel__read(evsel, 0, 0, &counts[i]); 521 __T("failed to read value for evsel", counts[i].val != 0); 522 i++; 523 } 524 525 perf_evlist__disable(evlist); 526 527 min = counts[0].val; 528 for (i = 0; i < EVENT_NUM; i++) { 529 __T_VERBOSE("Event %2d -- Raw count = %lu, run = %lu, enable = %lu\n", 530 i, counts[i].val, counts[i].run, counts[i].ena); 531 532 perf_counts_values__scale(&counts[i], true, &scaled); 533 if (scaled == 1) { 534 __T_VERBOSE("\t Scaled count = %lu (%.2lf%%, %lu/%lu)\n", 535 counts[i].val, 536 (double)counts[i].run / (double)counts[i].ena * 100.0, 537 counts[i].run, counts[i].ena); 538 } else if (scaled == -1) { 539 __T_VERBOSE("\t Not Running\n"); 540 } else { 541 __T_VERBOSE("\t Not Scaling\n"); 542 } 543 544 if (counts[i].val > max) 545 max = counts[i].val; 546 547 if (counts[i].val < min) 548 min = counts[i].val; 549 550 avg += counts[i].val; 551 552 if (counts[i].val != 0) 553 nonzero++; 554 } 555 556 if (nonzero != 0) 557 avg = avg / nonzero; 558 else 559 avg = 0; 560 561 error = display_error(avg, max, min, expected_counts.val); 562 563 __T("Error out of range!", ((error <= 1.0) && (error >= -1.0))); 564 565 perf_evlist__close(evlist); 566 perf_evlist__delete(evlist); 567 568 perf_thread_map__put(threads); 569 570 return 0; 571 } 572 573 int test_evlist(int argc, char **argv) 574 { 575 __T_START; 576 577 libperf_init(libperf_print); 578 579 test_stat_cpu(); 580 test_stat_thread(); 581 test_stat_thread_enable(); 582 test_mmap_thread(); 583 test_mmap_cpus(); 584 test_stat_multiplexing(); 585 586 __T_END; 587 return tests_failed == 0 ? 0 : -1; 588 } 589