2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00
linux/tools/perf/tests/openat-syscall-tp-fields.c
Ian Rogers dc6d2bc2d8 perf sample: Make user_regs and intr_regs optional
The struct dump_regs contains 512 bytes of cache_regs, meaning the two
values in perf_sample contribute 1088 bytes of its total 1384 bytes
size. Initializing this much memory has a cost reported by Tavian
Barnes <tavianator@tavianator.com> as about 2.5% when running `perf
script --itrace=i0`:
https://lore.kernel.org/lkml/d841b97b3ad2ca8bcab07e4293375fb7c32dfce7.1736618095.git.tavianator@tavianator.com/

Adrian Hunter <adrian.hunter@intel.com> replied that the zero
initialization was necessary and couldn't simply be removed.

This patch aims to strike a middle ground of still zeroing the
perf_sample, but removing 79% of its size by make user_regs and
intr_regs optional pointers to zalloc-ed memory. To support the
allocation accessors are created for user_regs and intr_regs. To
support correct cleanup perf_sample__init and perf_sample__exit
functions are created and added throughout the code base.

Signed-off-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250113194345.1537821-1-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2025-02-12 20:06:11 -08:00

162 lines
3.6 KiB
C

// SPDX-License-Identifier: GPL-2.0
#include <stdbool.h>
#include <linux/err.h>
#include <linux/string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "evlist.h"
#include "evsel.h"
#include "thread_map.h"
#include "record.h"
#include "tests.h"
#include "debug.h"
#include "util/mmap.h"
#include <errno.h>
#include <perf/mmap.h>
#include "util/sample.h"
#ifndef O_DIRECTORY
#define O_DIRECTORY 00200000
#endif
#ifndef AT_FDCWD
#define AT_FDCWD -100
#endif
static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
struct record_opts opts = {
.target = {
.uid = UINT_MAX,
.uses_mmap = true,
},
.no_buffering = true,
.freq = 1,
.mmap_pages = 256,
.raw_samples = true,
};
const char *filename = "/etc/passwd";
int flags = O_RDONLY | O_DIRECTORY;
struct evlist *evlist = evlist__new();
struct evsel *evsel;
int ret = TEST_FAIL, err, i, nr_events = 0, nr_polls = 0;
char sbuf[STRERR_BUFSIZE];
if (evlist == NULL) {
pr_debug("%s: evlist__new\n", __func__);
goto out;
}
evsel = evsel__newtp("syscalls", "sys_enter_openat");
if (IS_ERR(evsel)) {
pr_debug("%s: evsel__newtp\n", __func__);
ret = PTR_ERR(evsel) == -EACCES ? TEST_SKIP : TEST_FAIL;
goto out_delete_evlist;
}
evlist__add(evlist, evsel);
err = evlist__create_maps(evlist, &opts.target);
if (err < 0) {
pr_debug("%s: evlist__create_maps\n", __func__);
goto out_delete_evlist;
}
evsel__config(evsel, &opts, NULL);
perf_thread_map__set_pid(evlist->core.threads, 0, getpid());
err = evlist__open(evlist);
if (err < 0) {
pr_debug("perf_evlist__open: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
}
err = evlist__mmap(evlist, UINT_MAX);
if (err < 0) {
pr_debug("evlist__mmap: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
}
evlist__enable(evlist);
/*
* Generate the event:
*/
openat(AT_FDCWD, filename, flags);
while (1) {
int before = nr_events;
for (i = 0; i < evlist->core.nr_mmaps; i++) {
union perf_event *event;
struct mmap *md;
md = &evlist->mmap[i];
if (perf_mmap__read_init(&md->core) < 0)
continue;
while ((event = perf_mmap__read_event(&md->core)) != NULL) {
const u32 type = event->header.type;
int tp_flags;
struct perf_sample sample;
++nr_events;
if (type != PERF_RECORD_SAMPLE) {
perf_mmap__consume(&md->core);
continue;
}
perf_sample__init(&sample, /*all=*/false);
err = evsel__parse_sample(evsel, event, &sample);
if (err) {
pr_debug("Can't parse sample, err = %d\n", err);
perf_sample__exit(&sample);
goto out_delete_evlist;
}
tp_flags = evsel__intval(evsel, &sample, "flags");
perf_sample__exit(&sample);
if (flags != tp_flags) {
pr_debug("%s: Expected flags=%#x, got %#x\n",
__func__, flags, tp_flags);
goto out_delete_evlist;
}
goto out_ok;
}
perf_mmap__read_done(&md->core);
}
if (nr_events == before)
evlist__poll(evlist, 10);
if (++nr_polls > 5) {
pr_debug("%s: no events!\n", __func__);
goto out_delete_evlist;
}
}
out_ok:
ret = TEST_OK;
out_delete_evlist:
evlist__delete(evlist);
out:
return ret;
}
static struct test_case tests__syscall_openat_tp_fields[] = {
TEST_CASE_REASON("syscalls:sys_enter_openat event fields",
syscall_openat_tp_fields,
"permissions"),
{ .name = NULL, }
};
struct test_suite suite__syscall_openat_tp_fields = {
.desc = "syscalls:sys_enter_openat event fields",
.test_cases = tests__syscall_openat_tp_fields,
};