172 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Test backward bit in event attribute, read ring buffer from end to4 * beginning5 */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 11119 20static 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 32static 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 62static 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 85static int test__backward_ring_buffer(struct test_suite *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 parse_events_error__init(&parse_error);119 /*120 * Set backward bit, ring buffer should be writing from end. Record121 * it in aux evlist122 */123 err = parse_events(evlist, "syscalls:sys_enter_prctl/overwrite/", &parse_error);124 parse_events_error__exit(&parse_error);125 if (err) {126 pr_debug("Failed to parse tracepoint event, try use root\n");127 ret = TEST_SKIP;128 goto out_delete_evlist;129 }130 131 evlist__config(evlist, &opts, NULL);132 133 err = evlist__open(evlist);134 if (err < 0) {135 pr_debug("perf_evlist__open: %s\n",136 str_error_r(errno, sbuf, sizeof(sbuf)));137 goto out_delete_evlist;138 }139 140 ret = TEST_FAIL;141 err = do_test(evlist, opts.mmap_pages, &sample_count,142 &comm_count);143 if (err != TEST_OK)144 goto out_delete_evlist;145 146 if ((sample_count != NR_ITERS) || (comm_count != NR_ITERS)) {147 pr_err("Unexpected counter: sample_count=%d, comm_count=%d\n",148 sample_count, comm_count);149 goto out_delete_evlist;150 }151 152 evlist__close(evlist);153 154 err = evlist__open(evlist);155 if (err < 0) {156 pr_debug("perf_evlist__open: %s\n",157 str_error_r(errno, sbuf, sizeof(sbuf)));158 goto out_delete_evlist;159 }160 161 err = do_test(evlist, 1, &sample_count, &comm_count);162 if (err != TEST_OK)163 goto out_delete_evlist;164 165 ret = TEST_OK;166out_delete_evlist:167 evlist__delete(evlist);168 return ret;169}170 171DEFINE_SUITE("Read backward ring buffer", backward_ring_buffer);172