Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/compiler.h>
0003 #include <linux/string.h>
0004 #include <errno.h>
0005 #include <inttypes.h>
0006 #include <string.h>
0007 #include <sys/wait.h>
0008 #include <perf/cpumap.h>
0009 #include "tests.h"
0010 #include "evlist.h"
0011 #include "evsel.h"
0012 #include "debug.h"
0013 #include "parse-events.h"
0014 #include "thread_map.h"
0015 #include "target.h"
0016 
0017 static int attach__enable_on_exec(struct evlist *evlist)
0018 {
0019     struct evsel *evsel = evlist__last(evlist);
0020     struct target target = {
0021         .uid = UINT_MAX,
0022     };
0023     const char *argv[] = { "true", NULL, };
0024     char sbuf[STRERR_BUFSIZE];
0025     int err;
0026 
0027     pr_debug("attaching to spawned child, enable on exec\n");
0028 
0029     err = evlist__create_maps(evlist, &target);
0030     if (err < 0) {
0031         pr_debug("Not enough memory to create thread/cpu maps\n");
0032         return err;
0033     }
0034 
0035     err = evlist__prepare_workload(evlist, &target, argv, false, NULL);
0036     if (err < 0) {
0037         pr_debug("Couldn't run the workload!\n");
0038         return err;
0039     }
0040 
0041     evsel->core.attr.enable_on_exec = 1;
0042 
0043     err = evlist__open(evlist);
0044     if (err < 0) {
0045         pr_debug("perf_evlist__open: %s\n",
0046              str_error_r(errno, sbuf, sizeof(sbuf)));
0047         return err;
0048     }
0049 
0050     return evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
0051 }
0052 
0053 static int detach__enable_on_exec(struct evlist *evlist)
0054 {
0055     waitpid(evlist->workload.pid, NULL, 0);
0056     return 0;
0057 }
0058 
0059 static int attach__current_disabled(struct evlist *evlist)
0060 {
0061     struct evsel *evsel = evlist__last(evlist);
0062     struct perf_thread_map *threads;
0063     int err;
0064 
0065     pr_debug("attaching to current thread as disabled\n");
0066 
0067     threads = thread_map__new(-1, getpid(), UINT_MAX);
0068     if (threads == NULL) {
0069         pr_debug("thread_map__new\n");
0070         return -1;
0071     }
0072 
0073     evsel->core.attr.disabled = 1;
0074 
0075     err = evsel__open_per_thread(evsel, threads);
0076     if (err) {
0077         pr_debug("Failed to open event cpu-clock:u\n");
0078         return err;
0079     }
0080 
0081     perf_thread_map__put(threads);
0082     return evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;
0083 }
0084 
0085 static int attach__current_enabled(struct evlist *evlist)
0086 {
0087     struct evsel *evsel = evlist__last(evlist);
0088     struct perf_thread_map *threads;
0089     int err;
0090 
0091     pr_debug("attaching to current thread as enabled\n");
0092 
0093     threads = thread_map__new(-1, getpid(), UINT_MAX);
0094     if (threads == NULL) {
0095         pr_debug("failed to call thread_map__new\n");
0096         return -1;
0097     }
0098 
0099     err = evsel__open_per_thread(evsel, threads);
0100 
0101     perf_thread_map__put(threads);
0102     return err == 0 ? TEST_OK : TEST_FAIL;
0103 }
0104 
0105 static int detach__disable(struct evlist *evlist)
0106 {
0107     struct evsel *evsel = evlist__last(evlist);
0108 
0109     return evsel__enable(evsel);
0110 }
0111 
0112 static int attach__cpu_disabled(struct evlist *evlist)
0113 {
0114     struct evsel *evsel = evlist__last(evlist);
0115     struct perf_cpu_map *cpus;
0116     int err;
0117 
0118     pr_debug("attaching to CPU 0 as enabled\n");
0119 
0120     cpus = perf_cpu_map__new("0");
0121     if (cpus == NULL) {
0122         pr_debug("failed to call perf_cpu_map__new\n");
0123         return -1;
0124     }
0125 
0126     evsel->core.attr.disabled = 1;
0127 
0128     err = evsel__open_per_cpu(evsel, cpus, -1);
0129     if (err) {
0130         if (err == -EACCES)
0131             return TEST_SKIP;
0132 
0133         pr_debug("Failed to open event cpu-clock:u\n");
0134         return err;
0135     }
0136 
0137     perf_cpu_map__put(cpus);
0138     return evsel__enable(evsel);
0139 }
0140 
0141 static int attach__cpu_enabled(struct evlist *evlist)
0142 {
0143     struct evsel *evsel = evlist__last(evlist);
0144     struct perf_cpu_map *cpus;
0145     int err;
0146 
0147     pr_debug("attaching to CPU 0 as enabled\n");
0148 
0149     cpus = perf_cpu_map__new("0");
0150     if (cpus == NULL) {
0151         pr_debug("failed to call perf_cpu_map__new\n");
0152         return -1;
0153     }
0154 
0155     err = evsel__open_per_cpu(evsel, cpus, -1);
0156     if (err == -EACCES)
0157         return TEST_SKIP;
0158 
0159     perf_cpu_map__put(cpus);
0160     return err ? TEST_FAIL : TEST_OK;
0161 }
0162 
0163 static int test_times(int (attach)(struct evlist *),
0164               int (detach)(struct evlist *))
0165 {
0166     struct perf_counts_values count;
0167     struct evlist *evlist = NULL;
0168     struct evsel *evsel;
0169     int err = -1, i;
0170 
0171     evlist = evlist__new();
0172     if (!evlist) {
0173         pr_debug("failed to create event list\n");
0174         goto out_err;
0175     }
0176 
0177     err = parse_event(evlist, "cpu-clock:u");
0178     if (err) {
0179         pr_debug("failed to parse event cpu-clock:u\n");
0180         goto out_err;
0181     }
0182 
0183     evsel = evlist__last(evlist);
0184     evsel->core.attr.read_format |=
0185         PERF_FORMAT_TOTAL_TIME_ENABLED |
0186         PERF_FORMAT_TOTAL_TIME_RUNNING;
0187 
0188     err = attach(evlist);
0189     if (err == TEST_SKIP) {
0190         pr_debug("  SKIP  : not enough rights\n");
0191         return err;
0192     }
0193 
0194     TEST_ASSERT_VAL("failed to attach", !err);
0195 
0196     for (i = 0; i < 100000000; i++) { }
0197 
0198     TEST_ASSERT_VAL("failed to detach", !detach(evlist));
0199 
0200     perf_evsel__read(&evsel->core, 0, 0, &count);
0201 
0202     err = !(count.ena == count.run);
0203 
0204     pr_debug("  %s: ena %" PRIu64", run %" PRIu64"\n",
0205          !err ? "OK    " : "FAILED",
0206          count.ena, count.run);
0207 
0208 out_err:
0209     evlist__delete(evlist);
0210     return !err ? TEST_OK : TEST_FAIL;
0211 }
0212 
0213 /*
0214  * This test creates software event 'cpu-clock'
0215  * attaches it in several ways (explained below)
0216  * and checks that enabled and running times
0217  * match.
0218  */
0219 static int test__event_times(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
0220 {
0221     int err, ret = 0;
0222 
0223 #define _T(attach, detach)          \
0224     err = test_times(attach, detach);   \
0225     if (err && (ret == TEST_OK || ret == TEST_SKIP))    \
0226         ret = err;
0227 
0228     /* attach on newly spawned process after exec */
0229     _T(attach__enable_on_exec,   detach__enable_on_exec)
0230     /* attach on current process as enabled */
0231     _T(attach__current_enabled,  detach__disable)
0232     /* attach on current process as disabled */
0233     _T(attach__current_disabled, detach__disable)
0234     /* attach on cpu as disabled */
0235     _T(attach__cpu_disabled,     detach__disable)
0236     /* attach on cpu as enabled */
0237     _T(attach__cpu_enabled,      detach__disable)
0238 
0239 #undef _T
0240     return ret;
0241 }
0242 
0243 DEFINE_SUITE("Event times", event_times);