From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>, Namhyung Kim <namhyung@kernel.org>,
Clark Williams <williams@redhat.com>,
linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
Song Liu <songliubraving@fb.com>,
Arnaldo Carvalho de Melo <acme@redhat.com>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Peter Zijlstra <peterz@infradead.org>,
Stanislav Fomichev <sdf@google.com>
Subject: [PATCH 41/44] perf evlist: Introduce side band thread
Date: Thu, 21 Mar 2019 15:51:39 -0300 [thread overview]
Message-ID: <20190321185142.11441-42-acme@kernel.org> (raw)
In-Reply-To: <20190321185142.11441-1-acme@kernel.org>
From: Song Liu <songliubraving@fb.com>
This patch introduces side band thread that captures extended
information for events like PERF_RECORD_BPF_EVENT.
This new thread uses its own evlist that uses ring buffer with very low
watermark for lower latency.
To use side band thread, we need to:
1. add side band event(s) by calling perf_evlist__add_sb_event();
2. calls perf_evlist__start_sb_thread();
3. at the end of perf run, perf_evlist__stop_sb_thread().
In the next patch, we use this thread to handle PERF_RECORD_BPF_EVENT.
Committer notes:
Add fix by Jiri Olsa for when te sb_tread can't get started and then at
the end the stop_sb_thread() segfaults when joining the (non-existing)
thread.
That can happen when running 'perf top' or 'perf record' as a normal
user, for instance.
Further checks need to be done on top of this to more graciously handle
these possible failure scenarios.
Signed-off-by: Song Liu <songliubraving@fb.com>
Reviewed-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stanislav Fomichev <sdf@google.com>
Link: http://lkml.kernel.org/r/20190312053051.2690567-15-songliubraving@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-record.c | 9 +++
tools/perf/builtin-top.c | 9 +++
tools/perf/util/evlist.c | 119 ++++++++++++++++++++++++++++++++++++
tools/perf/util/evlist.h | 12 ++++
tools/perf/util/evsel.h | 6 ++
5 files changed, 155 insertions(+)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e79faccd7842..6f645fd72fed 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1137,6 +1137,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
struct perf_data *data = &rec->data;
struct perf_session *session;
bool disabled = false, draining = false;
+ struct perf_evlist *sb_evlist = NULL;
int fd;
atexit(record__sig_exit);
@@ -1237,6 +1238,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
goto out_child;
}
+ if (perf_evlist__start_sb_thread(sb_evlist, &rec->opts.target)) {
+ pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
+ opts->no_bpf_event = true;
+ }
+
err = record__synthesize(rec, false);
if (err < 0)
goto out_child;
@@ -1487,6 +1493,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
out_delete_session:
perf_session__delete(session);
+
+ if (!opts->no_bpf_event)
+ perf_evlist__stop_sb_thread(sb_evlist);
return status;
}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c2ea22c4ea67..3ce8a8db6c1d 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1501,6 +1501,7 @@ int cmd_top(int argc, const char **argv)
"number of thread to run event synthesize"),
OPT_END()
};
+ struct perf_evlist *sb_evlist = NULL;
const char * const top_usage[] = {
"perf top [<options>]",
NULL
@@ -1636,8 +1637,16 @@ int cmd_top(int argc, const char **argv)
goto out_delete_evlist;
}
+ if (perf_evlist__start_sb_thread(sb_evlist, target)) {
+ pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
+ opts->no_bpf_event = true;
+ }
+
status = __cmd_top(&top);
+ if (!opts->no_bpf_event)
+ perf_evlist__stop_sb_thread(sb_evlist);
+
out_delete_evlist:
perf_evlist__delete(top.evlist);
perf_session__delete(top.session);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index ed20f4379956..ec78e93085de 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -19,6 +19,7 @@
#include "debug.h"
#include "units.h"
#include "asm/bug.h"
+#include "bpf-event.h"
#include <signal.h>
#include <unistd.h>
@@ -1856,3 +1857,121 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list,
}
return leader;
}
+
+int perf_evlist__add_sb_event(struct perf_evlist **evlist,
+ struct perf_event_attr *attr,
+ perf_evsel__sb_cb_t cb,
+ void *data)
+{
+ struct perf_evsel *evsel;
+ bool new_evlist = (*evlist) == NULL;
+
+ if (*evlist == NULL)
+ *evlist = perf_evlist__new();
+ if (*evlist == NULL)
+ return -1;
+
+ if (!attr->sample_id_all) {
+ pr_warning("enabling sample_id_all for all side band events\n");
+ attr->sample_id_all = 1;
+ }
+
+ evsel = perf_evsel__new_idx(attr, (*evlist)->nr_entries);
+ if (!evsel)
+ goto out_err;
+
+ evsel->side_band.cb = cb;
+ evsel->side_band.data = data;
+ perf_evlist__add(*evlist, evsel);
+ return 0;
+
+out_err:
+ if (new_evlist) {
+ perf_evlist__delete(*evlist);
+ *evlist = NULL;
+ }
+ return -1;
+}
+
+static void *perf_evlist__poll_thread(void *arg)
+{
+ struct perf_evlist *evlist = arg;
+ bool draining = false;
+ int i;
+
+ while (draining || !(evlist->thread.done)) {
+ if (draining)
+ draining = false;
+ else if (evlist->thread.done)
+ draining = true;
+
+ if (!draining)
+ perf_evlist__poll(evlist, 1000);
+
+ for (i = 0; i < evlist->nr_mmaps; i++) {
+ struct perf_mmap *map = &evlist->mmap[i];
+ union perf_event *event;
+
+ if (perf_mmap__read_init(map))
+ continue;
+ while ((event = perf_mmap__read_event(map)) != NULL) {
+ struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event);
+
+ if (evsel && evsel->side_band.cb)
+ evsel->side_band.cb(event, evsel->side_band.data);
+ else
+ pr_warning("cannot locate proper evsel for the side band event\n");
+
+ perf_mmap__consume(map);
+ }
+ perf_mmap__read_done(map);
+ }
+ }
+ return NULL;
+}
+
+int perf_evlist__start_sb_thread(struct perf_evlist *evlist,
+ struct target *target)
+{
+ struct perf_evsel *counter;
+
+ if (!evlist)
+ return 0;
+
+ if (perf_evlist__create_maps(evlist, target))
+ goto out_delete_evlist;
+
+ evlist__for_each_entry(evlist, counter) {
+ if (perf_evsel__open(counter, evlist->cpus,
+ evlist->threads) < 0)
+ goto out_delete_evlist;
+ }
+
+ if (perf_evlist__mmap(evlist, UINT_MAX))
+ goto out_delete_evlist;
+
+ evlist__for_each_entry(evlist, counter) {
+ if (perf_evsel__enable(counter))
+ goto out_delete_evlist;
+ }
+
+ evlist->thread.done = 0;
+ if (pthread_create(&evlist->thread.th, NULL, perf_evlist__poll_thread, evlist))
+ goto out_delete_evlist;
+
+ return 0;
+
+out_delete_evlist:
+ perf_evlist__delete(evlist);
+ evlist = NULL;
+ return -1;
+}
+
+void perf_evlist__stop_sb_thread(struct perf_evlist *evlist)
+{
+ if (!evlist)
+ return;
+ evlist->thread.done = 1;
+ pthread_join(evlist->thread.th, NULL);
+ perf_evlist__delete(evlist);
+}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 744906dd4887..dcb68f34d2cd 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -54,6 +54,10 @@ struct perf_evlist {
struct perf_sample *sample);
u64 first_sample_time;
u64 last_sample_time;
+ struct {
+ pthread_t th;
+ volatile int done;
+ } thread;
};
struct perf_evsel_str_handler {
@@ -87,6 +91,14 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
int perf_evlist__add_dummy(struct perf_evlist *evlist);
+int perf_evlist__add_sb_event(struct perf_evlist **evlist,
+ struct perf_event_attr *attr,
+ perf_evsel__sb_cb_t cb,
+ void *data);
+int perf_evlist__start_sb_thread(struct perf_evlist *evlist,
+ struct target *target);
+void perf_evlist__stop_sb_thread(struct perf_evlist *evlist);
+
int perf_evlist__add_newtp(struct perf_evlist *evlist,
const char *sys, const char *name, void *handler);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index cc578e02e08f..0f2c6c93d721 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -73,6 +73,8 @@ struct perf_evsel_config_term {
struct perf_stat_evsel;
+typedef int (perf_evsel__sb_cb_t)(union perf_event *event, void *data);
+
/** struct perf_evsel - event selector
*
* @evlist - evlist this evsel is in, if it is in one.
@@ -151,6 +153,10 @@ struct perf_evsel {
bool collect_stat;
bool weak_group;
const char *pmu_name;
+ struct {
+ perf_evsel__sb_cb_t *cb;
+ void *data;
+ } side_band;
};
union u64_swap {
--
2.20.1
next prev parent reply other threads:[~2019-03-21 18:51 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-03-21 18:50 [GIT PULL 00/44] perf/core fixes and improvements Arnaldo Carvalho de Melo
2019-03-21 18:50 ` [PATCH 01/44] perf list: Filter metrics too Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 02/44] perf record: Allow to limit number of reported perf.data files Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 03/44] perf record: Clarify help for --switch-output Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 04/44] perf report: Show all sort keys in help output Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 05/44] perf report: Indicate JITed code better in report Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 06/44] perf script: Support relative time Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 07/44] perf stat: Fix --no-scale Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 08/44] perf stat: Improve scaling Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 09/44] perf vendor events: Remove P8 HW events which are not supported Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 10/44] perf tools: Add doc about how to build perf with Asan and UBSan Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 11/44] perf list: Don't forget to drop the reference to the allocated thread_map Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 12/44] perf tools: Fix errors under optimization level '-Og' Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 13/44] perf config: Fix an error in the config template documentation Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 14/44] perf config: Fix a memory leak in collect_config() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 15/44] perf build-id: Fix memory leak in print_sdt_events() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 16/44] perf top: Delete the evlist before perf_session, fixing heap-use-after-free issue Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 17/44] perf top: Fix error handling in cmd_top() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 18/44] perf hist: Add missing map__put() in error case Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 19/44] perf map: Remove map from 'names' tree in __maps__remove() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 20/44] perf maps: Purge all maps from the 'names' tree Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 21/44] perf top: Fix global-buffer-overflow issue Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 22/44] perf evsel: Free evsel->counts in perf_evsel__exit() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 23/44] perf tests: Fix a memory leak of cpu_map object in the openat_syscall_event_on_all_cpus test Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 24/44] perf tests: Fix memory leak by expr__find_other() in test__expr() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 25/44] perf tests: Fix a memory leak in test__perf_evsel__tp_sched_test() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 26/44] perf record: Replace option --bpf-event with --no-bpf-event Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 27/44] tools lib bpf: Introduce bpf_program__get_prog_info_linear() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 28/44] bpftool: use bpf_program__get_prog_info_linear() in prog.c:do_dump() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 29/44] perf bpf: Synthesize bpf events with bpf_program__get_prog_info_linear() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 30/44] perf bpf: Make synthesize_bpf_events() receive perf_session pointer instead of perf_tool Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 31/44] perf bpf: Save bpf_prog_info in a rbtree in perf_env Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 32/44] perf bpf: Save bpf_prog_info information as headers to perf.data Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 33/44] perf bpf: Save BTF in a rbtree in perf_env Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 34/44] perf bpf: Save BTF information as headers to perf.data Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 35/44] perf top: Add option --no-bpf-event Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 36/44] perf feature detection: Add -lopcodes to feature-libbfd Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 37/44] perf symbols: Introduce DSO_BINARY_TYPE__BPF_PROG_INFO Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 38/44] perf bpf: Process PERF_BPF_EVENT_PROG_LOAD for annotation Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 39/44] perf build: Check what binutils's 'disassembler()' signature to use Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 40/44] perf annotate: Enable annotation of BPF programs Arnaldo Carvalho de Melo
2019-03-21 18:51 ` Arnaldo Carvalho de Melo [this message]
2019-03-21 18:51 ` [PATCH 42/44] perf tools: Save bpf_prog_info and BTF of new " Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 43/44] perf bpf: Extract logic to create program names from perf_event__synthesize_one_bpf_prog() Arnaldo Carvalho de Melo
2019-03-21 18:51 ` [PATCH 44/44] perf bpf: Show more BPF program info in print_bpf_prog_info() Arnaldo Carvalho de Melo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190321185142.11441-42-acme@kernel.org \
--to=acme@kernel.org \
--cc=acme@redhat.com \
--cc=ast@kernel.org \
--cc=daniel@iogearbox.net \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=sdf@google.com \
--cc=songliubraving@fb.com \
--cc=williams@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.