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