Merge tag 'for-linus-20191012' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / tools / perf / tests / backward-ring-buffer.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Test backward bit in event attribute, read ring buffer from end to
4  * beginning
5  */
6
7 #include <evlist.h>
8 #include <sys/prctl.h>
9 #include "record.h"
10 #include "tests.h"
11 #include "debug.h"
12 #include "parse-events.h"
13 #include "util/mmap.h"
14 #include <errno.h>
15 #include <linux/string.h>
16
17 #define NR_ITERS 111
18
19 static void testcase(void)
20 {
21         int i;
22
23         for (i = 0; i < NR_ITERS; i++) {
24                 char proc_name[15];
25
26                 snprintf(proc_name, sizeof(proc_name), "p:%d\n", i);
27                 prctl(PR_SET_NAME, proc_name);
28         }
29 }
30
31 static int count_samples(struct evlist *evlist, int *sample_count,
32                          int *comm_count)
33 {
34         int i;
35
36         for (i = 0; i < evlist->core.nr_mmaps; i++) {
37                 struct mmap *map = &evlist->overwrite_mmap[i];
38                 union perf_event *event;
39
40                 perf_mmap__read_init(map);
41                 while ((event = perf_mmap__read_event(map)) != NULL) {
42                         const u32 type = event->header.type;
43
44                         switch (type) {
45                         case PERF_RECORD_SAMPLE:
46                                 (*sample_count)++;
47                                 break;
48                         case PERF_RECORD_COMM:
49                                 (*comm_count)++;
50                                 break;
51                         default:
52                                 pr_err("Unexpected record of type %d\n", type);
53                                 return TEST_FAIL;
54                         }
55                 }
56                 perf_mmap__read_done(map);
57         }
58         return TEST_OK;
59 }
60
61 static int do_test(struct evlist *evlist, int mmap_pages,
62                    int *sample_count, int *comm_count)
63 {
64         int err;
65         char sbuf[STRERR_BUFSIZE];
66
67         err = evlist__mmap(evlist, mmap_pages);
68         if (err < 0) {
69                 pr_debug("evlist__mmap: %s\n",
70                          str_error_r(errno, sbuf, sizeof(sbuf)));
71                 return TEST_FAIL;
72         }
73
74         evlist__enable(evlist);
75         testcase();
76         evlist__disable(evlist);
77
78         err = count_samples(evlist, sample_count, comm_count);
79         evlist__munmap(evlist);
80         return err;
81 }
82
83
84 int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __maybe_unused)
85 {
86         int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0;
87         char pid[16], sbuf[STRERR_BUFSIZE];
88         struct evlist *evlist;
89         struct evsel *evsel __maybe_unused;
90         struct parse_events_error parse_error;
91         struct record_opts opts = {
92                 .target = {
93                         .uid = UINT_MAX,
94                         .uses_mmap = true,
95                 },
96                 .freq         = 0,
97                 .mmap_pages   = 256,
98                 .default_interval = 1,
99         };
100
101         snprintf(pid, sizeof(pid), "%d", getpid());
102         pid[sizeof(pid) - 1] = '\0';
103         opts.target.tid = opts.target.pid = pid;
104
105         evlist = evlist__new();
106         if (!evlist) {
107                 pr_debug("Not enough memory to create evlist\n");
108                 return TEST_FAIL;
109         }
110
111         err = perf_evlist__create_maps(evlist, &opts.target);
112         if (err < 0) {
113                 pr_debug("Not enough memory to create thread/cpu maps\n");
114                 goto out_delete_evlist;
115         }
116
117         bzero(&parse_error, sizeof(parse_error));
118         /*
119          * Set backward bit, ring buffer should be writing from end. Record
120          * it in aux evlist
121          */
122         err = parse_events(evlist, "syscalls:sys_enter_prctl/overwrite/", &parse_error);
123         if (err) {
124                 pr_debug("Failed to parse tracepoint event, try use root\n");
125                 ret = TEST_SKIP;
126                 goto out_delete_evlist;
127         }
128
129         perf_evlist__config(evlist, &opts, NULL);
130
131         err = evlist__open(evlist);
132         if (err < 0) {
133                 pr_debug("perf_evlist__open: %s\n",
134                          str_error_r(errno, sbuf, sizeof(sbuf)));
135                 goto out_delete_evlist;
136         }
137
138         ret = TEST_FAIL;
139         err = do_test(evlist, opts.mmap_pages, &sample_count,
140                       &comm_count);
141         if (err != TEST_OK)
142                 goto out_delete_evlist;
143
144         if ((sample_count != NR_ITERS) || (comm_count != NR_ITERS)) {
145                 pr_err("Unexpected counter: sample_count=%d, comm_count=%d\n",
146                        sample_count, comm_count);
147                 goto out_delete_evlist;
148         }
149
150         err = do_test(evlist, 1, &sample_count, &comm_count);
151         if (err != TEST_OK)
152                 goto out_delete_evlist;
153
154         ret = TEST_OK;
155 out_delete_evlist:
156         evlist__delete(evlist);
157         return ret;
158 }