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, cpu, tmp; 338 union perf_event *event; 339 int count = 0; 340 341 snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id", 342 sysfs__mountpoint()); 343 344 if (filename__read_int(path, &id)) { 345 fprintf(stderr, "error: failed to get tracepoint id: %s\n", path); 346 return -1; 347 } 348 349 attr.config = id; 350 351 cpus = perf_cpu_map__new(NULL); 352 __T("failed to create cpus", cpus); 353 354 evlist = perf_evlist__new(); 355 __T("failed to create evlist", evlist); 356 357 evsel = perf_evsel__new(&attr); 358 __T("failed to create evsel1", evsel); 359 __T("failed to set leader", evsel->leader == evsel); 360 361 perf_evlist__add(evlist, evsel); 362 363 perf_evlist__set_maps(evlist, cpus, NULL); 364 365 err = perf_evlist__open(evlist); 366 __T("failed to open evlist", err == 0); 367 368 err = perf_evlist__mmap(evlist, 4); 369 __T("failed to mmap evlist", err == 0); 370 371 perf_evlist__enable(evlist); 372 373 err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask); 374 __T("sched_getaffinity failed", err == 0); 375 376 perf_cpu_map__for_each_cpu(cpu, tmp, cpus) { 377 cpu_set_t mask; 378 379 CPU_ZERO(&mask); 380 CPU_SET(cpu, &mask); 381 382 err = sched_setaffinity(0, sizeof(mask), &mask); 383 __T("sched_setaffinity failed", err == 0); 384 385 prctl(0, 0, 0, 0, 0); 386 } 387 388 err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask); 389 __T("sched_setaffinity failed", err == 0); 390 391 perf_evlist__disable(evlist); 392 393 perf_evlist__for_each_mmap(evlist, map, false) { 394 if (perf_mmap__read_init(map) < 0) 395 continue; 396 397 while ((event = perf_mmap__read_event(map)) != NULL) { 398 count++; 399 perf_mmap__consume(map); 400 } 401 402 perf_mmap__read_done(map); 403 } 404 405 /* calls perf_evlist__munmap/perf_evlist__close */ 406 perf_evlist__delete(evlist); 407 408 /* 409 * The generated prctl events should match the 410 * number of cpus or be bigger (we are system-wide). 411 */ 412 __T("failed count", count >= perf_cpu_map__nr(cpus)); 413 414 perf_cpu_map__put(cpus); 415 416 return 0; 417 } 418 419 static double display_error(long long average, 420 long long high, 421 long long low, 422 long long expected) 423 { 424 double error; 425 426 error = (((double)average - expected) / expected) * 100.0; 427 428 __T_VERBOSE(" Expected: %lld\n", expected); 429 __T_VERBOSE(" High: %lld Low: %lld Average: %lld\n", 430 high, low, average); 431 432 __T_VERBOSE(" Average Error = %.2f%%\n", error); 433 434 return error; 435 } 436 437 static int test_stat_multiplexing(void) 438 { 439 struct perf_counts_values expected_counts = { .val = 0 }; 440 struct perf_counts_values counts[EVENT_NUM] = {{ .val = 0 },}; 441 struct perf_thread_map *threads; 442 struct perf_evlist *evlist; 443 struct perf_evsel *evsel; 444 struct perf_event_attr attr = { 445 .type = PERF_TYPE_HARDWARE, 446 .config = PERF_COUNT_HW_INSTRUCTIONS, 447 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 448 PERF_FORMAT_TOTAL_TIME_RUNNING, 449 .disabled = 1, 450 }; 451 int err, i, nonzero = 0; 452 unsigned long count; 453 long long max = 0, min = 0, avg = 0; 454 double error = 0.0; 455 s8 scaled = 0; 456 457 /* read for non-multiplexing event count */ 458 threads = perf_thread_map__new_dummy(); 459 __T("failed to create threads", threads); 460 461 perf_thread_map__set_pid(threads, 0, 0); 462 463 evsel = perf_evsel__new(&attr); 464 __T("failed to create evsel", evsel); 465 466 err = perf_evsel__open(evsel, NULL, threads); 467 __T("failed to open evsel", err == 0); 468 469 err = perf_evsel__enable(evsel); 470 __T("failed to enable evsel", err == 0); 471 472 /* wait loop */ 473 count = WAIT_COUNT; 474 while (count--) 475 ; 476 477 perf_evsel__read(evsel, 0, 0, &expected_counts); 478 __T("failed to read value for evsel", expected_counts.val != 0); 479 __T("failed to read non-multiplexing event count", 480 expected_counts.ena == expected_counts.run); 481 482 err = perf_evsel__disable(evsel); 483 __T("failed to enable evsel", err == 0); 484 485 perf_evsel__close(evsel); 486 perf_evsel__delete(evsel); 487 488 perf_thread_map__put(threads); 489 490 /* read for multiplexing event count */ 491 threads = perf_thread_map__new_dummy(); 492 __T("failed to create threads", threads); 493 494 perf_thread_map__set_pid(threads, 0, 0); 495 496 evlist = perf_evlist__new(); 497 __T("failed to create evlist", evlist); 498 499 for (i = 0; i < EVENT_NUM; i++) { 500 evsel = perf_evsel__new(&attr); 501 __T("failed to create evsel", evsel); 502 503 perf_evlist__add(evlist, evsel); 504 } 505 perf_evlist__set_maps(evlist, NULL, threads); 506 507 err = perf_evlist__open(evlist); 508 __T("failed to open evsel", err == 0); 509 510 perf_evlist__enable(evlist); 511 512 /* wait loop */ 513 count = WAIT_COUNT; 514 while (count--) 515 ; 516 517 i = 0; 518 perf_evlist__for_each_evsel(evlist, evsel) { 519 perf_evsel__read(evsel, 0, 0, &counts[i]); 520 __T("failed to read value for evsel", counts[i].val != 0); 521 i++; 522 } 523 524 perf_evlist__disable(evlist); 525 526 min = counts[0].val; 527 for (i = 0; i < EVENT_NUM; i++) { 528 __T_VERBOSE("Event %2d -- Raw count = %lu, run = %lu, enable = %lu\n", 529 i, counts[i].val, counts[i].run, counts[i].ena); 530 531 perf_counts_values__scale(&counts[i], true, &scaled); 532 if (scaled == 1) { 533 __T_VERBOSE("\t Scaled count = %lu (%.2lf%%, %lu/%lu)\n", 534 counts[i].val, 535 (double)counts[i].run / (double)counts[i].ena * 100.0, 536 counts[i].run, counts[i].ena); 537 } else if (scaled == -1) { 538 __T_VERBOSE("\t Not Running\n"); 539 } else { 540 __T_VERBOSE("\t Not Scaling\n"); 541 } 542 543 if (counts[i].val > max) 544 max = counts[i].val; 545 546 if (counts[i].val < min) 547 min = counts[i].val; 548 549 avg += counts[i].val; 550 551 if (counts[i].val != 0) 552 nonzero++; 553 } 554 555 if (nonzero != 0) 556 avg = avg / nonzero; 557 else 558 avg = 0; 559 560 error = display_error(avg, max, min, expected_counts.val); 561 562 __T("Error out of range!", ((error <= 1.0) && (error >= -1.0))); 563 564 perf_evlist__close(evlist); 565 perf_evlist__delete(evlist); 566 567 perf_thread_map__put(threads); 568 569 return 0; 570 } 571 572 int test_evlist(int argc, char **argv) 573 { 574 __T_START; 575 576 libperf_init(libperf_print); 577 578 test_stat_cpu(); 579 test_stat_thread(); 580 test_stat_thread_enable(); 581 test_mmap_thread(); 582 test_mmap_cpus(); 583 test_stat_multiplexing(); 584 585 __T_END; 586 return tests_failed == 0 ? 0 : -1; 587 } 588