root/tools/perf/tests/event-times.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. attach__enable_on_exec
  2. detach__enable_on_exec
  3. attach__current_disabled
  4. attach__current_enabled
  5. detach__disable
  6. attach__cpu_disabled
  7. attach__cpu_enabled
  8. test_times
  9. test__event_times

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/compiler.h>
   3 #include <linux/string.h>
   4 #include <errno.h>
   5 #include <inttypes.h>
   6 #include <string.h>
   7 #include <sys/wait.h>
   8 #include <perf/cpumap.h>
   9 #include "tests.h"
  10 #include "evlist.h"
  11 #include "evsel.h"
  12 #include "debug.h"
  13 #include "parse-events.h"
  14 #include "thread_map.h"
  15 #include "target.h"
  16 
  17 static int attach__enable_on_exec(struct evlist *evlist)
  18 {
  19         struct evsel *evsel = evlist__last(evlist);
  20         struct target target = {
  21                 .uid = UINT_MAX,
  22         };
  23         const char *argv[] = { "true", NULL, };
  24         char sbuf[STRERR_BUFSIZE];
  25         int err;
  26 
  27         pr_debug("attaching to spawned child, enable on exec\n");
  28 
  29         err = perf_evlist__create_maps(evlist, &target);
  30         if (err < 0) {
  31                 pr_debug("Not enough memory to create thread/cpu maps\n");
  32                 return err;
  33         }
  34 
  35         err = perf_evlist__prepare_workload(evlist, &target, argv, false, NULL);
  36         if (err < 0) {
  37                 pr_debug("Couldn't run the workload!\n");
  38                 return err;
  39         }
  40 
  41         evsel->core.attr.enable_on_exec = 1;
  42 
  43         err = evlist__open(evlist);
  44         if (err < 0) {
  45                 pr_debug("perf_evlist__open: %s\n",
  46                          str_error_r(errno, sbuf, sizeof(sbuf)));
  47                 return err;
  48         }
  49 
  50         return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
  51 }
  52 
  53 static int detach__enable_on_exec(struct evlist *evlist)
  54 {
  55         waitpid(evlist->workload.pid, NULL, 0);
  56         return 0;
  57 }
  58 
  59 static int attach__current_disabled(struct evlist *evlist)
  60 {
  61         struct evsel *evsel = evlist__last(evlist);
  62         struct perf_thread_map *threads;
  63         int err;
  64 
  65         pr_debug("attaching to current thread as disabled\n");
  66 
  67         threads = thread_map__new(-1, getpid(), UINT_MAX);
  68         if (threads == NULL) {
  69                 pr_debug("thread_map__new\n");
  70                 return -1;
  71         }
  72 
  73         evsel->core.attr.disabled = 1;
  74 
  75         err = perf_evsel__open_per_thread(evsel, threads);
  76         if (err) {
  77                 pr_debug("Failed to open event cpu-clock:u\n");
  78                 return err;
  79         }
  80 
  81         perf_thread_map__put(threads);
  82         return evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;
  83 }
  84 
  85 static int attach__current_enabled(struct evlist *evlist)
  86 {
  87         struct evsel *evsel = evlist__last(evlist);
  88         struct perf_thread_map *threads;
  89         int err;
  90 
  91         pr_debug("attaching to current thread as enabled\n");
  92 
  93         threads = thread_map__new(-1, getpid(), UINT_MAX);
  94         if (threads == NULL) {
  95                 pr_debug("failed to call thread_map__new\n");
  96                 return -1;
  97         }
  98 
  99         err = perf_evsel__open_per_thread(evsel, threads);
 100 
 101         perf_thread_map__put(threads);
 102         return err == 0 ? TEST_OK : TEST_FAIL;
 103 }
 104 
 105 static int detach__disable(struct evlist *evlist)
 106 {
 107         struct evsel *evsel = evlist__last(evlist);
 108 
 109         return evsel__enable(evsel);
 110 }
 111 
 112 static int attach__cpu_disabled(struct evlist *evlist)
 113 {
 114         struct evsel *evsel = evlist__last(evlist);
 115         struct perf_cpu_map *cpus;
 116         int err;
 117 
 118         pr_debug("attaching to CPU 0 as enabled\n");
 119 
 120         cpus = perf_cpu_map__new("0");
 121         if (cpus == NULL) {
 122                 pr_debug("failed to call perf_cpu_map__new\n");
 123                 return -1;
 124         }
 125 
 126         evsel->core.attr.disabled = 1;
 127 
 128         err = perf_evsel__open_per_cpu(evsel, cpus);
 129         if (err) {
 130                 if (err == -EACCES)
 131                         return TEST_SKIP;
 132 
 133                 pr_debug("Failed to open event cpu-clock:u\n");
 134                 return err;
 135         }
 136 
 137         perf_cpu_map__put(cpus);
 138         return evsel__enable(evsel);
 139 }
 140 
 141 static int attach__cpu_enabled(struct evlist *evlist)
 142 {
 143         struct evsel *evsel = evlist__last(evlist);
 144         struct perf_cpu_map *cpus;
 145         int err;
 146 
 147         pr_debug("attaching to CPU 0 as enabled\n");
 148 
 149         cpus = perf_cpu_map__new("0");
 150         if (cpus == NULL) {
 151                 pr_debug("failed to call perf_cpu_map__new\n");
 152                 return -1;
 153         }
 154 
 155         err = perf_evsel__open_per_cpu(evsel, cpus);
 156         if (err == -EACCES)
 157                 return TEST_SKIP;
 158 
 159         perf_cpu_map__put(cpus);
 160         return err ? TEST_FAIL : TEST_OK;
 161 }
 162 
 163 static int test_times(int (attach)(struct evlist *),
 164                       int (detach)(struct evlist *))
 165 {
 166         struct perf_counts_values count;
 167         struct evlist *evlist = NULL;
 168         struct evsel *evsel;
 169         int err = -1, i;
 170 
 171         evlist = evlist__new();
 172         if (!evlist) {
 173                 pr_debug("failed to create event list\n");
 174                 goto out_err;
 175         }
 176 
 177         err = parse_events(evlist, "cpu-clock:u", NULL);
 178         if (err) {
 179                 pr_debug("failed to parse event cpu-clock:u\n");
 180                 goto out_err;
 181         }
 182 
 183         evsel = evlist__last(evlist);
 184         evsel->core.attr.read_format |=
 185                 PERF_FORMAT_TOTAL_TIME_ENABLED |
 186                 PERF_FORMAT_TOTAL_TIME_RUNNING;
 187 
 188         err = attach(evlist);
 189         if (err == TEST_SKIP) {
 190                 pr_debug("  SKIP  : not enough rights\n");
 191                 return err;
 192         }
 193 
 194         TEST_ASSERT_VAL("failed to attach", !err);
 195 
 196         for (i = 0; i < 100000000; i++) { }
 197 
 198         TEST_ASSERT_VAL("failed to detach", !detach(evlist));
 199 
 200         perf_evsel__read(&evsel->core, 0, 0, &count);
 201 
 202         err = !(count.ena == count.run);
 203 
 204         pr_debug("  %s: ena %" PRIu64", run %" PRIu64"\n",
 205                  !err ? "OK    " : "FAILED",
 206                  count.ena, count.run);
 207 
 208 out_err:
 209         evlist__delete(evlist);
 210         return !err ? TEST_OK : TEST_FAIL;
 211 }
 212 
 213 /*
 214  * This test creates software event 'cpu-clock'
 215  * attaches it in several ways (explained below)
 216  * and checks that enabled and running times
 217  * match.
 218  */
 219 int test__event_times(struct test *test __maybe_unused, int subtest __maybe_unused)
 220 {
 221         int err, ret = 0;
 222 
 223 #define _T(attach, detach)                      \
 224         err = test_times(attach, detach);       \
 225         if (err && (ret == TEST_OK || ret == TEST_SKIP))        \
 226                 ret = err;
 227 
 228         /* attach on newly spawned process after exec */
 229         _T(attach__enable_on_exec,   detach__enable_on_exec)
 230         /* attach on current process as enabled */
 231         _T(attach__current_enabled,  detach__disable)
 232         /* attach on current process as disabled */
 233         _T(attach__current_disabled, detach__disable)
 234         /* attach on cpu as disabled */
 235         _T(attach__cpu_disabled,     detach__disable)
 236         /* attach on cpu as enabled */
 237         _T(attach__cpu_enabled,      detach__disable)
 238 
 239 #undef _T
 240         return ret;
 241 }

/* [<][>][^][v][top][bottom][index][help] */