Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d787d37 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

 into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

 * Improve listing of accessible enum perf probe variables, from Hyeoncheol Lee.

 * Don't stop the build if the audit libraries are not installed, fix from Namhyung Kim.

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents ac2ba2b3 aec1930b
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
perf-trace(1)
=============

NAME
----
perf-trace - strace inspired tool

SYNOPSIS
--------
[verse]
'perf trace'

DESCRIPTION
-----------
This command will show the events associated with the target, initially
syscalls, but other system events like pagefaults, task lifetime events,
scheduling events, etc.

Initially this is a live mode only tool, but eventually will work with
perf.data files like the other tools, allowing a detached 'record' from
analysis phases.

OPTIONS
-------

--all-cpus::
        System-wide collection from all CPUs.

-p::
--pid=::
	Record events on existing process ID (comma separated list).

--tid=::
        Record events on existing thread ID (comma separated list).

--uid=::
        Record events in threads owned by uid. Name or number.

--no-inherit::
	Child tasks do not inherit counters.

--mmap-pages=::
	Number of mmap data pages. Must be a power of two.

--cpu::
Collect samples only on the list of CPUs provided. Multiple CPUs can be provided as a
comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
In per-thread mode with inheritance mode on (default), Events are captured only when
the thread executes on the designated CPUs. Default is to monitor all CPUs.

SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-script[1]
+13 −0
Original line number Diff line number Diff line
@@ -559,6 +559,19 @@ else
	LIB_OBJS += $(OUTPUT)util/unwind.o
endif

ifdef NO_LIBAUDIT
	BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
else
	FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
	ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y)
		msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
		BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
	else
		BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
		EXTLIBS += -laudit
	endif
endif

ifdef NO_NEWT
	BASIC_CFLAGS += -DNO_NEWT_SUPPORT
else
+1 −1
Original line number Diff line number Diff line
@@ -320,7 +320,7 @@ static int perf_record__open(struct perf_record *rec)
		}
	}

	if (perf_evlist__set_filters(evlist)) {
	if (perf_evlist__apply_filters(evlist)) {
		error("failed to set filter with %d (%s)\n", errno,
			strerror(errno));
		rc = -1;
+1 −1
Original line number Diff line number Diff line
@@ -478,7 +478,7 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv)
		counter->supported = true;
	}

	if (perf_evlist__set_filters(evsel_list)) {
	if (perf_evlist__apply_filters(evsel_list)) {
		error("failed to set filter with %d (%s)\n", errno,
			strerror(errno));
		return -1;
+118 −2
Original line number Diff line number Diff line
@@ -564,7 +564,7 @@ static int test__basic_mmap(void)
			goto out_munmap;
		}

		err = perf_evlist__parse_sample(evlist, event, &sample, false);
		err = perf_evlist__parse_sample(evlist, event, &sample);
		if (err) {
			pr_err("Can't parse sample, err = %d\n", err);
			goto out_munmap;
@@ -781,7 +781,7 @@ static int test__PERF_RECORD(void)
				if (type < PERF_RECORD_MAX)
					nr_events[type]++;

				err = perf_evlist__parse_sample(evlist, event, &sample, false);
				err = perf_evlist__parse_sample(evlist, event, &sample);
				if (err < 0) {
					if (verbose)
						perf_event__fprintf(event, stderr);
@@ -1289,6 +1289,118 @@ static int perf_evsel__tp_sched_test(void)
	return ret;
}

static int test__syscall_open_tp_fields(void)
{
	struct perf_record_opts opts = {
		.target = {
			.uid = UINT_MAX,
			.uses_mmap = true,
		},
		.no_delay   = true,
		.freq	    = 1,
		.mmap_pages = 256,
		.raw_samples = true,
	};
	const char *filename = "/etc/passwd";
	int flags = O_RDONLY | O_DIRECTORY;
	struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
	struct perf_evsel *evsel;
	int err = -1, i, nr_events = 0, nr_polls = 0;

	if (evlist == NULL) {
		pr_debug("%s: perf_evlist__new\n", __func__);
		goto out;
	}

	evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
	if (evsel == NULL) {
		pr_debug("%s: perf_evsel__newtp\n", __func__);
		goto out_delete_evlist;
	}

	perf_evlist__add(evlist, evsel);

	err = perf_evlist__create_maps(evlist, &opts.target);
	if (err < 0) {
		pr_debug("%s: perf_evlist__create_maps\n", __func__);
		goto out_delete_evlist;
	}

	perf_evsel__config(evsel, &opts, evsel);

	evlist->threads->map[0] = getpid();

	err = perf_evlist__open(evlist);
	if (err < 0) {
		pr_debug("perf_evlist__open: %s\n", strerror(errno));
		goto out_delete_evlist;
	}

	err = perf_evlist__mmap(evlist, UINT_MAX, false);
	if (err < 0) {
		pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
		goto out_delete_evlist;
	}

	perf_evlist__enable(evlist);

	/*
 	 * Generate the event:
 	 */
	open(filename, flags);

	while (1) {
		int before = nr_events;

		for (i = 0; i < evlist->nr_mmaps; i++) {
			union perf_event *event;

			while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
				const u32 type = event->header.type;
				int tp_flags;
				struct perf_sample sample;

				++nr_events;

				if (type != PERF_RECORD_SAMPLE)
					continue;

				err = perf_evsel__parse_sample(evsel, event, &sample);
				if (err) {
					pr_err("Can't parse sample, err = %d\n", err);
					goto out_munmap;
				}

				tp_flags = perf_evsel__intval(evsel, &sample, "flags");

				if (flags != tp_flags) {
					pr_debug("%s: Expected flags=%#x, got %#x\n",
						 __func__, flags, tp_flags);
					goto out_munmap;
				}

				goto out_ok;
			}
		}

		if (nr_events == before)
			poll(evlist->pollfd, evlist->nr_fds, 10);

		if (++nr_polls > 5) {
			pr_debug("%s: no events!\n", __func__);
			goto out_munmap;
		}
	}
out_ok:
	err = 0;
out_munmap:
	perf_evlist__munmap(evlist);
out_delete_evlist:
	perf_evlist__delete(evlist);
out:
	return err;
}

static struct test {
	const char *desc;
	int (*func)(void);
@@ -1339,6 +1451,10 @@ static struct test {
		.desc = "Check parsing of sched tracepoints fields",
		.func = perf_evsel__tp_sched_test,
	},
	{
		.desc = "Generate and check syscalls:sys_enter_open event fields",
		.func = test__syscall_open_tp_fields,
	},
	{
		.func = NULL,
	},
Loading