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 <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
  24static int libperf_print(enum libperf_print_level level,
  25                         const char *fmt, va_list ap)
  26{
  27        return vfprintf(stderr, fmt, ap);
  28}
  29
  30static int test_stat_cpu(void)
  31{
  32        struct perf_cpu_map *cpus;
  33        struct perf_evlist *evlist;
  34        struct perf_evsel *evsel, *leader;
  35        struct perf_event_attr attr1 = {
  36                .type   = PERF_TYPE_SOFTWARE,
  37                .config = PERF_COUNT_SW_CPU_CLOCK,
  38        };
  39        struct perf_event_attr attr2 = {
  40                .type   = PERF_TYPE_SOFTWARE,
  41                .config = PERF_COUNT_SW_TASK_CLOCK,
  42        };
  43        int err, idx;
  44
  45        cpus = perf_cpu_map__new(NULL);
  46        __T("failed to create cpus", cpus);
  47
  48        evlist = perf_evlist__new();
  49        __T("failed to create evlist", evlist);
  50
  51        evsel = leader = perf_evsel__new(&attr1);
  52        __T("failed to create evsel1", evsel);
  53
  54        perf_evlist__add(evlist, evsel);
  55
  56        evsel = perf_evsel__new(&attr2);
  57        __T("failed to create evsel2", evsel);
  58
  59        perf_evlist__add(evlist, evsel);
  60
  61        perf_evlist__set_leader(evlist);
  62        __T("failed to set leader", leader->leader == leader);
  63        __T("failed to set leader", evsel->leader  == leader);
  64
  65        perf_evlist__set_maps(evlist, cpus, NULL);
  66
  67        err = perf_evlist__open(evlist);
  68        __T("failed to open evsel", err == 0);
  69
  70        perf_evlist__for_each_evsel(evlist, evsel) {
  71                cpus = perf_evsel__cpus(evsel);
  72
  73                for (idx = 0; idx < perf_cpu_map__nr(cpus); idx++) {
  74                        struct perf_counts_values counts = { .val = 0 };
  75
  76                        perf_evsel__read(evsel, idx, 0, &counts);
  77                        __T("failed to read value for evsel", counts.val != 0);
  78                }
  79        }
  80
  81        perf_evlist__close(evlist);
  82        perf_evlist__delete(evlist);
  83
  84        perf_cpu_map__put(cpus);
  85        return 0;
  86}
  87
  88static int test_stat_thread(void)
  89{
  90        struct perf_counts_values counts = { .val = 0 };
  91        struct perf_thread_map *threads;
  92        struct perf_evlist *evlist;
  93        struct perf_evsel *evsel, *leader;
  94        struct perf_event_attr attr1 = {
  95                .type   = PERF_TYPE_SOFTWARE,
  96                .config = PERF_COUNT_SW_CPU_CLOCK,
  97        };
  98        struct perf_event_attr attr2 = {
  99                .type   = PERF_TYPE_SOFTWARE,
 100                .config = PERF_COUNT_SW_TASK_CLOCK,
 101        };
 102        int err;
 103
 104        threads = perf_thread_map__new_dummy();
 105        __T("failed to create threads", threads);
 106
 107        perf_thread_map__set_pid(threads, 0, 0);
 108
 109        evlist = perf_evlist__new();
 110        __T("failed to create evlist", evlist);
 111
 112        evsel = leader = perf_evsel__new(&attr1);
 113        __T("failed to create evsel1", evsel);
 114
 115        perf_evlist__add(evlist, evsel);
 116
 117        evsel = perf_evsel__new(&attr2);
 118        __T("failed to create evsel2", evsel);
 119
 120        perf_evlist__add(evlist, evsel);
 121
 122        perf_evlist__set_leader(evlist);
 123        __T("failed to set leader", leader->leader == leader);
 124        __T("failed to set leader", evsel->leader  == leader);
 125
 126        perf_evlist__set_maps(evlist, NULL, threads);
 127
 128        err = perf_evlist__open(evlist);
 129        __T("failed to open evsel", err == 0);
 130
 131        perf_evlist__for_each_evsel(evlist, evsel) {
 132                perf_evsel__read(evsel, 0, 0, &counts);
 133                __T("failed to read value for evsel", counts.val != 0);
 134        }
 135
 136        perf_evlist__close(evlist);
 137        perf_evlist__delete(evlist);
 138
 139        perf_thread_map__put(threads);
 140        return 0;
 141}
 142
 143static int test_stat_thread_enable(void)
 144{
 145        struct perf_counts_values counts = { .val = 0 };
 146        struct perf_thread_map *threads;
 147        struct perf_evlist *evlist;
 148        struct perf_evsel *evsel, *leader;
 149        struct perf_event_attr attr1 = {
 150                .type     = PERF_TYPE_SOFTWARE,
 151                .config   = PERF_COUNT_SW_CPU_CLOCK,
 152                .disabled = 1,
 153        };
 154        struct perf_event_attr attr2 = {
 155                .type     = PERF_TYPE_SOFTWARE,
 156                .config   = PERF_COUNT_SW_TASK_CLOCK,
 157                .disabled = 1,
 158        };
 159        int err;
 160
 161        threads = perf_thread_map__new_dummy();
 162        __T("failed to create threads", threads);
 163
 164        perf_thread_map__set_pid(threads, 0, 0);
 165
 166        evlist = perf_evlist__new();
 167        __T("failed to create evlist", evlist);
 168
 169        evsel = leader = perf_evsel__new(&attr1);
 170        __T("failed to create evsel1", evsel);
 171
 172        perf_evlist__add(evlist, evsel);
 173
 174        evsel = perf_evsel__new(&attr2);
 175        __T("failed to create evsel2", evsel);
 176
 177        perf_evlist__add(evlist, evsel);
 178
 179        perf_evlist__set_leader(evlist);
 180        __T("failed to set leader", leader->leader == leader);
 181        __T("failed to set leader", evsel->leader  == leader);
 182
 183        perf_evlist__set_maps(evlist, NULL, threads);
 184
 185        err = perf_evlist__open(evlist);
 186        __T("failed to open evsel", err == 0);
 187
 188        perf_evlist__for_each_evsel(evlist, evsel) {
 189                perf_evsel__read(evsel, 0, 0, &counts);
 190                __T("failed to read value for evsel", counts.val == 0);
 191        }
 192
 193        perf_evlist__enable(evlist);
 194
 195        perf_evlist__for_each_evsel(evlist, evsel) {
 196                perf_evsel__read(evsel, 0, 0, &counts);
 197                __T("failed to read value for evsel", counts.val != 0);
 198        }
 199
 200        perf_evlist__disable(evlist);
 201
 202        perf_evlist__close(evlist);
 203        perf_evlist__delete(evlist);
 204
 205        perf_thread_map__put(threads);
 206        return 0;
 207}
 208
 209static int test_mmap_thread(void)
 210{
 211        struct perf_evlist *evlist;
 212        struct perf_evsel *evsel;
 213        struct perf_mmap *map;
 214        struct perf_cpu_map *cpus;
 215        struct perf_thread_map *threads;
 216        struct perf_event_attr attr = {
 217                .type             = PERF_TYPE_TRACEPOINT,
 218                .sample_period    = 1,
 219                .wakeup_watermark = 1,
 220                .disabled         = 1,
 221        };
 222        char path[PATH_MAX];
 223        int id, err, pid, go_pipe[2];
 224        union perf_event *event;
 225        int count = 0;
 226
 227        snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
 228                 sysfs__mountpoint());
 229
 230        if (filename__read_int(path, &id)) {
 231                tests_failed++;
 232                fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
 233                return -1;
 234        }
 235
 236        attr.config = id;
 237
 238        err = pipe(go_pipe);
 239        __T("failed to create pipe", err == 0);
 240
 241        fflush(NULL);
 242
 243        pid = fork();
 244        if (!pid) {
 245                int i;
 246                char bf;
 247
 248                read(go_pipe[0], &bf, 1);
 249
 250                /* Generate 100 prctl calls. */
 251                for (i = 0; i < 100; i++)
 252                        prctl(0, 0, 0, 0, 0);
 253
 254                exit(0);
 255        }
 256
 257        threads = perf_thread_map__new_dummy();
 258        __T("failed to create threads", threads);
 259
 260        cpus = perf_cpu_map__dummy_new();
 261        __T("failed to create cpus", cpus);
 262
 263        perf_thread_map__set_pid(threads, 0, pid);
 264
 265        evlist = perf_evlist__new();
 266        __T("failed to create evlist", evlist);
 267
 268        evsel = perf_evsel__new(&attr);
 269        __T("failed to create evsel1", evsel);
 270        __T("failed to set leader", evsel->leader == evsel);
 271
 272        perf_evlist__add(evlist, evsel);
 273
 274        perf_evlist__set_maps(evlist, cpus, threads);
 275
 276        err = perf_evlist__open(evlist);
 277        __T("failed to open evlist", err == 0);
 278
 279        err = perf_evlist__mmap(evlist, 4);
 280        __T("failed to mmap evlist", err == 0);
 281
 282        perf_evlist__enable(evlist);
 283
 284        /* kick the child and wait for it to finish */
 285        write(go_pipe[1], "A", 1);
 286        waitpid(pid, NULL, 0);
 287
 288        /*
 289         * There's no need to call perf_evlist__disable,
 290         * monitored process is dead now.
 291         */
 292
 293        perf_evlist__for_each_mmap(evlist, map, false) {
 294                if (perf_mmap__read_init(map) < 0)
 295                        continue;
 296
 297                while ((event = perf_mmap__read_event(map)) != NULL) {
 298                        count++;
 299                        perf_mmap__consume(map);
 300                }
 301
 302                perf_mmap__read_done(map);
 303        }
 304
 305        /* calls perf_evlist__munmap/perf_evlist__close */
 306        perf_evlist__delete(evlist);
 307
 308        perf_thread_map__put(threads);
 309        perf_cpu_map__put(cpus);
 310
 311        /*
 312         * The generated prctl calls should match the
 313         * number of events in the buffer.
 314         */
 315        __T("failed count", count == 100);
 316
 317        return 0;
 318}
 319
 320static int test_mmap_cpus(void)
 321{
 322        struct perf_evlist *evlist;
 323        struct perf_evsel *evsel;
 324        struct perf_mmap *map;
 325        struct perf_cpu_map *cpus;
 326        struct perf_event_attr attr = {
 327                .type             = PERF_TYPE_TRACEPOINT,
 328                .sample_period    = 1,
 329                .wakeup_watermark = 1,
 330                .disabled         = 1,
 331        };
 332        cpu_set_t saved_mask;
 333        char path[PATH_MAX];
 334        int id, err, cpu, tmp;
 335        union perf_event *event;
 336        int count = 0;
 337
 338        snprintf(path, PATH_MAX, "%s/kernel/debug/tracing/events/syscalls/sys_enter_prctl/id",
 339                 sysfs__mountpoint());
 340
 341        if (filename__read_int(path, &id)) {
 342                fprintf(stderr, "error: failed to get tracepoint id: %s\n", path);
 343                return -1;
 344        }
 345
 346        attr.config = id;
 347
 348        cpus = perf_cpu_map__new(NULL);
 349        __T("failed to create cpus", cpus);
 350
 351        evlist = perf_evlist__new();
 352        __T("failed to create evlist", evlist);
 353
 354        evsel = perf_evsel__new(&attr);
 355        __T("failed to create evsel1", evsel);
 356        __T("failed to set leader", evsel->leader == evsel);
 357
 358        perf_evlist__add(evlist, evsel);
 359
 360        perf_evlist__set_maps(evlist, cpus, NULL);
 361
 362        err = perf_evlist__open(evlist);
 363        __T("failed to open evlist", err == 0);
 364
 365        err = perf_evlist__mmap(evlist, 4);
 366        __T("failed to mmap evlist", err == 0);
 367
 368        perf_evlist__enable(evlist);
 369
 370        err = sched_getaffinity(0, sizeof(saved_mask), &saved_mask);
 371        __T("sched_getaffinity failed", err == 0);
 372
 373        perf_cpu_map__for_each_cpu(cpu, tmp, cpus) {
 374                cpu_set_t mask;
 375
 376                CPU_ZERO(&mask);
 377                CPU_SET(cpu, &mask);
 378
 379                err = sched_setaffinity(0, sizeof(mask), &mask);
 380                __T("sched_setaffinity failed", err == 0);
 381
 382                prctl(0, 0, 0, 0, 0);
 383        }
 384
 385        err = sched_setaffinity(0, sizeof(saved_mask), &saved_mask);
 386        __T("sched_setaffinity failed", err == 0);
 387
 388        perf_evlist__disable(evlist);
 389
 390        perf_evlist__for_each_mmap(evlist, map, false) {
 391                if (perf_mmap__read_init(map) < 0)
 392                        continue;
 393
 394                while ((event = perf_mmap__read_event(map)) != NULL) {
 395                        count++;
 396                        perf_mmap__consume(map);
 397                }
 398
 399                perf_mmap__read_done(map);
 400        }
 401
 402        /* calls perf_evlist__munmap/perf_evlist__close */
 403        perf_evlist__delete(evlist);
 404
 405        /*
 406         * The generated prctl events should match the
 407         * number of cpus or be bigger (we are system-wide).
 408         */
 409        __T("failed count", count >= perf_cpu_map__nr(cpus));
 410
 411        perf_cpu_map__put(cpus);
 412
 413        return 0;
 414}
 415
 416int test_evlist(int argc, char **argv)
 417{
 418        __T_START;
 419
 420        libperf_init(libperf_print);
 421
 422        test_stat_cpu();
 423        test_stat_thread();
 424        test_stat_thread_enable();
 425        test_mmap_thread();
 426        test_mmap_cpus();
 427
 428        __T_END;
 429        return tests_failed == 0 ? 0 : -1;
 430}
 431