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

Commit a074865e authored by Wang Nan's avatar Wang Nan Committed by Arnaldo Carvalho de Melo
Browse files

perf tools: Introduce perf hooks



Perf hooks allow hooking user code at perf events. They can be used for
manipulation of BPF maps, taking snapshot and reporting results. In this
patch two perf hook points are introduced: record_start and record_end.

To avoid buggy user actions, a SIGSEGV signal handler is introduced into
'perf record'. It turns off perf hook if it causes a segfault and report
an error to help debugging.

A test case for perf hook is introduced.

Test result:
  $ ./buildperf/perf test -v hook
  50: Test perf hooks                                          :
  --- start ---
  test child forked, pid 10311
  SIGSEGV is observed as expected, try to recover.
  Fatal error (SEGFAULT) in perf hook 'test'
  test child finished with 0
  ---- end ----
  Test perf hooks: Ok

Signed-off-by: default avatarWang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Joe Stringer <joe@ovn.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/20161126070354.141764-5-wangnan0@huawei.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 5a6acad1
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "util/llvm-utils.h"
#include "util/bpf-loader.h"
#include "util/trigger.h"
#include "util/perf-hooks.h"
#include "asm/bug.h"

#include <unistd.h>
@@ -206,6 +207,12 @@ static void sig_handler(int sig)
	done = 1;
}

static void sigsegv_handler(int sig)
{
	perf_hooks__recover();
	sighandler_dump_stack(sig);
}

static void record__sig_exit(void)
{
	if (signr == -1)
@@ -833,6 +840,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
	signal(SIGCHLD, sig_handler);
	signal(SIGINT, sig_handler);
	signal(SIGTERM, sig_handler);
	signal(SIGSEGV, sigsegv_handler);

	if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
		signal(SIGUSR2, snapshot_sig_handler);
@@ -970,6 +978,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)

	trigger_ready(&auxtrace_snapshot_trigger);
	trigger_ready(&switch_output_trigger);
	perf_hooks__invoke_record_start();
	for (;;) {
		unsigned long long hits = rec->samples;

@@ -1114,6 +1123,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
		}
	}

	perf_hooks__invoke_record_end();

	if (!err && !quiet) {
		char samples[128];
		const char *postfix = rec->timestamp_filename ?
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ perf-y += backward-ring-buffer.o
perf-y += sdt.o
perf-y += is_printable_array.o
perf-y += bitmap.o
perf-y += perf-hooks.o

$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
	$(call rule_mkdir)
+4 −0
Original line number Diff line number Diff line
@@ -229,6 +229,10 @@ static struct test generic_tests[] = {
		.desc = "Test bitmap print",
		.func = test__bitmap_print,
	},
	{
		.desc = "Test perf hooks",
		.func = test__perf_hooks,
	},
	{
		.func = NULL,
	},
+44 −0
Original line number Diff line number Diff line
#include <signal.h>
#include <stdlib.h>

#include "tests.h"
#include "debug.h"
#include "util.h"
#include "perf-hooks.h"

static void sigsegv_handler(int sig __maybe_unused)
{
	pr_debug("SIGSEGV is observed as expected, try to recover.\n");
	perf_hooks__recover();
	signal(SIGSEGV, SIG_DFL);
	raise(SIGSEGV);
	exit(-1);
}

static int hook_flags;

static void the_hook(void)
{
	int *p = NULL;

	hook_flags = 1234;

	/* Generate a segfault, test perf_hooks__recover */
	*p = 0;
}

int test__perf_hooks(int subtest __maybe_unused)
{
	signal(SIGSEGV, sigsegv_handler);
	perf_hooks__set_hook("test", the_hook);
	perf_hooks__invoke_test();

	/* hook is triggered? */
	if (hook_flags != 1234)
		return TEST_FAIL;

	/* the buggy hook is removed? */
	if (perf_hooks__get_hook("test"))
		return TEST_FAIL;
	return TEST_OK;
}
+1 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ int test__cpu_map_print(int subtest);
int test__sdt_event(int subtest);
int test__is_printable_array(int subtest);
int test__bitmap_print(int subtest);
int test__perf_hooks(int subtest);

#if defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT
Loading