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