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