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