linux/tools/perf/tests/task-exit.c
<<
>>
Prefs
   1#include "evlist.h"
   2#include "evsel.h"
   3#include "thread_map.h"
   4#include "cpumap.h"
   5#include "tests.h"
   6
   7#include <signal.h>
   8
   9static int exited;
  10static int nr_exit;
  11
  12static void sig_handler(int sig __maybe_unused)
  13{
  14        exited = 1;
  15}
  16
  17/*
  18 * perf_evlist__prepare_workload will send a SIGUSR1 if the fork fails, since
  19 * we asked by setting its exec_error to this handler.
  20 */
  21static void workload_exec_failed_signal(int signo __maybe_unused,
  22                                        siginfo_t *info __maybe_unused,
  23                                        void *ucontext __maybe_unused)
  24{
  25        exited  = 1;
  26        nr_exit = -1;
  27}
  28
  29/*
  30 * This test will start a workload that does nothing then it checks
  31 * if the number of exit event reported by the kernel is 1 or not
  32 * in order to check the kernel returns correct number of event.
  33 */
  34int test__task_exit(int subtest __maybe_unused)
  35{
  36        int err = -1;
  37        union perf_event *event;
  38        struct perf_evsel *evsel;
  39        struct perf_evlist *evlist;
  40        struct target target = {
  41                .uid            = UINT_MAX,
  42                .uses_mmap      = true,
  43        };
  44        const char *argv[] = { "true", NULL };
  45        char sbuf[STRERR_BUFSIZE];
  46        struct cpu_map *cpus;
  47        struct thread_map *threads;
  48
  49        signal(SIGCHLD, sig_handler);
  50
  51        evlist = perf_evlist__new_default();
  52        if (evlist == NULL) {
  53                pr_debug("perf_evlist__new_default\n");
  54                return -1;
  55        }
  56
  57        /*
  58         * Create maps of threads and cpus to monitor. In this case
  59         * we start with all threads and cpus (-1, -1) but then in
  60         * perf_evlist__prepare_workload we'll fill in the only thread
  61         * we're monitoring, the one forked there.
  62         */
  63        cpus = cpu_map__dummy_new();
  64        threads = thread_map__new_by_tid(-1);
  65        if (!cpus || !threads) {
  66                err = -ENOMEM;
  67                pr_debug("Not enough memory to create thread/cpu maps\n");
  68                goto out_free_maps;
  69        }
  70
  71        perf_evlist__set_maps(evlist, cpus, threads);
  72
  73        cpus    = NULL;
  74        threads = NULL;
  75
  76        err = perf_evlist__prepare_workload(evlist, &target, argv, false,
  77                                            workload_exec_failed_signal);
  78        if (err < 0) {
  79                pr_debug("Couldn't run the workload!\n");
  80                goto out_delete_evlist;
  81        }
  82
  83        evsel = perf_evlist__first(evlist);
  84        evsel->attr.task = 1;
  85        evsel->attr.sample_freq = 0;
  86        evsel->attr.inherit = 0;
  87        evsel->attr.watermark = 0;
  88        evsel->attr.wakeup_events = 1;
  89        evsel->attr.exclude_kernel = 1;
  90
  91        err = perf_evlist__open(evlist);
  92        if (err < 0) {
  93                pr_debug("Couldn't open the evlist: %s\n",
  94                         str_error_r(-err, sbuf, sizeof(sbuf)));
  95                goto out_delete_evlist;
  96        }
  97
  98        if (perf_evlist__mmap(evlist, 128, true) < 0) {
  99                pr_debug("failed to mmap events: %d (%s)\n", errno,
 100                         str_error_r(errno, sbuf, sizeof(sbuf)));
 101                goto out_delete_evlist;
 102        }
 103
 104        perf_evlist__start_workload(evlist);
 105
 106retry:
 107        while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) {
 108                if (event->header.type == PERF_RECORD_EXIT)
 109                        nr_exit++;
 110
 111                perf_evlist__mmap_consume(evlist, 0);
 112        }
 113
 114        if (!exited || !nr_exit) {
 115                perf_evlist__poll(evlist, -1);
 116                goto retry;
 117        }
 118
 119        if (nr_exit != 1) {
 120                pr_debug("received %d EXIT records\n", nr_exit);
 121                err = -1;
 122        }
 123
 124out_free_maps:
 125        cpu_map__put(cpus);
 126        thread_map__put(threads);
 127out_delete_evlist:
 128        perf_evlist__delete(evlist);
 129        return err;
 130}
 131