Message ID | 20190226002019.3748539-15-songliubraving@fb.com |
---|---|
State | Changes Requested |
Delegated to: | BPF Maintainers |
Headers | show |
Series | perf annotation of BPF programs | expand |
On Mon, Feb 25, 2019 at 04:20:18PM -0800, Song Liu wrote: SNIP > diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c > index 8c902276d4b4..61b87c8111e6 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> > > @@ -1841,3 +1842,102 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, > } > return leader; > } > + > +static struct perf_evlist *sb_evlist; > +pthread_t poll_thread; so some of the things are static and some like poll_args you alloced on the stack.. I dont like this interface, could we come up with something generic? perhaps encapsulated in perf_evlist, like: struct perf_evlist { ... struct { pthread_t th; int state; } thread; }; typedef int (perf_evlist__thread_cb_t)(perf_evlist, union perf_event *event,....) perf_evlist__start_thread(perf_evlist, perf_evlist__thread_cb_t cb); perf_evlist__stop_thread(perf_evlist); jirka
> On Feb 27, 2019, at 5:21 AM, Jiri Olsa <jolsa@redhat.com> wrote: > > On Mon, Feb 25, 2019 at 04:20:18PM -0800, Song Liu wrote: > > SNIP > >> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c >> index 8c902276d4b4..61b87c8111e6 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> >> >> @@ -1841,3 +1842,102 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, >> } >> return leader; >> } >> + >> +static struct perf_evlist *sb_evlist; >> +pthread_t poll_thread; > > so some of the things are static and some like poll_args > you alloced on the stack.. I dont like this interface, > could we come up with something generic? perhaps > encapsulated in perf_evlist, like: I picked global sb_evlist and poll_thread because there should be only one sb_evlist and one thread polling it. There might be multiple evsel on the sb_evlist. I am not sure I understand your suggestion.. > struct perf_evlist { > ... > struct { > pthread_t th; > int state; > } thread; This will not be used by the main perf_evlist, right? > }; > > typedef int (perf_evlist__thread_cb_t)(perf_evlist, union perf_event *event,....) How do we use this callback? We need a way to specify which events to poll (mmap, bpf_event, ksymbol, etc). How do we do that with the callback function? Thanks, Song > perf_evlist__start_thread(perf_evlist, perf_evlist__thread_cb_t cb); > perf_evlist__stop_thread(perf_evlist); > > > jirka
On Wed, Feb 27, 2019 at 05:52:52PM +0000, Song Liu wrote: > > > > On Feb 27, 2019, at 5:21 AM, Jiri Olsa <jolsa@redhat.com> wrote: > > > > On Mon, Feb 25, 2019 at 04:20:18PM -0800, Song Liu wrote: > > > > SNIP > > > >> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c > >> index 8c902276d4b4..61b87c8111e6 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> > >> > >> @@ -1841,3 +1842,102 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, > >> } > >> return leader; > >> } > >> + > >> +static struct perf_evlist *sb_evlist; > >> +pthread_t poll_thread; > > > > so some of the things are static and some like poll_args > > you alloced on the stack.. I dont like this interface, > > could we come up with something generic? perhaps > > encapsulated in perf_evlist, like: > > I picked global sb_evlist and poll_thread because there > should be only one sb_evlist and one thread polling it. > There might be multiple evsel on the sb_evlist. > > I am not sure I understand your suggestion.. > > > struct perf_evlist { > > ... > > struct { > > pthread_t th; > > int state; > > } thread; > > This will not be used by the main perf_evlist, right? no, just by the thread interface > > > }; > > > > typedef int (perf_evlist__thread_cb_t)(perf_evlist, union perf_event *event,....) > > How do we use this callback? We need a way to specify which > events to poll (mmap, bpf_event, ksymbol, etc). How do we do > that with the callback function? you provide your own callback jirka
> On Mar 4, 2019, at 5:52 AM, Jiri Olsa <jolsa@redhat.com> wrote: > > On Wed, Feb 27, 2019 at 05:52:52PM +0000, Song Liu wrote: >> >> >>> On Feb 27, 2019, at 5:21 AM, Jiri Olsa <jolsa@redhat.com> wrote: >>> >>> On Mon, Feb 25, 2019 at 04:20:18PM -0800, Song Liu wrote: >>> >>> SNIP >>> >>>> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c >>>> index 8c902276d4b4..61b87c8111e6 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> >>>> >>>> @@ -1841,3 +1842,102 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, >>>> } >>>> return leader; >>>> } >>>> + >>>> +static struct perf_evlist *sb_evlist; >>>> +pthread_t poll_thread; >>> >>> so some of the things are static and some like poll_args >>> you alloced on the stack.. I dont like this interface, >>> could we come up with something generic? perhaps >>> encapsulated in perf_evlist, like: >> >> I picked global sb_evlist and poll_thread because there >> should be only one sb_evlist and one thread polling it. >> There might be multiple evsel on the sb_evlist. >> >> I am not sure I understand your suggestion.. >> >>> struct perf_evlist { >>> ... >>> struct { >>> pthread_t th; >>> int state; >>> } thread; >> >> This will not be used by the main perf_evlist, right? > > no, just by the thread interface What is "state" here? > >> >>> }; >>> >>> typedef int (perf_evlist__thread_cb_t)(perf_evlist, union perf_event *event,....) >> >> How do we use this callback? We need a way to specify which >> events to poll (mmap, bpf_event, ksymbol, etc). How do we do >> that with the callback function? > > you provide your own callback I guess I get your point now. I can try that. Thanks, Song > jirka
On Mon, Mar 04, 2019 at 07:49:06PM +0000, Song Liu wrote: > > > > On Mar 4, 2019, at 5:52 AM, Jiri Olsa <jolsa@redhat.com> wrote: > > > > On Wed, Feb 27, 2019 at 05:52:52PM +0000, Song Liu wrote: > >> > >> > >>> On Feb 27, 2019, at 5:21 AM, Jiri Olsa <jolsa@redhat.com> wrote: > >>> > >>> On Mon, Feb 25, 2019 at 04:20:18PM -0800, Song Liu wrote: > >>> > >>> SNIP > >>> > >>>> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c > >>>> index 8c902276d4b4..61b87c8111e6 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> > >>>> > >>>> @@ -1841,3 +1842,102 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, > >>>> } > >>>> return leader; > >>>> } > >>>> + > >>>> +static struct perf_evlist *sb_evlist; > >>>> +pthread_t poll_thread; > >>> > >>> so some of the things are static and some like poll_args > >>> you alloced on the stack.. I dont like this interface, > >>> could we come up with something generic? perhaps > >>> encapsulated in perf_evlist, like: > >> > >> I picked global sb_evlist and poll_thread because there > >> should be only one sb_evlist and one thread polling it. > >> There might be multiple evsel on the sb_evlist. > >> > >> I am not sure I understand your suggestion.. > >> > >>> struct perf_evlist { > >>> ... > >>> struct { > >>> pthread_t th; > >>> int state; > >>> } thread; > >> > >> This will not be used by the main perf_evlist, right? > > > > no, just by the thread interface > > What is "state" here? it's replacement for the 'done' pointer u had, which I did not like.. leting each thread having its own state is better IMO jirka
> On Mar 4, 2019, at 12:41 PM, Jiri Olsa <jolsa@redhat.com> wrote: > > On Mon, Mar 04, 2019 at 07:49:06PM +0000, Song Liu wrote: >> >> >>> On Mar 4, 2019, at 5:52 AM, Jiri Olsa <jolsa@redhat.com> wrote: >>> >>> On Wed, Feb 27, 2019 at 05:52:52PM +0000, Song Liu wrote: >>>> >>>> >>>>> On Feb 27, 2019, at 5:21 AM, Jiri Olsa <jolsa@redhat.com> wrote: >>>>> >>>>> On Mon, Feb 25, 2019 at 04:20:18PM -0800, Song Liu wrote: >>>>> >>>>> SNIP >>>>> >>>>>> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c >>>>>> index 8c902276d4b4..61b87c8111e6 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> >>>>>> >>>>>> @@ -1841,3 +1842,102 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, >>>>>> } >>>>>> return leader; >>>>>> } >>>>>> + >>>>>> +static struct perf_evlist *sb_evlist; >>>>>> +pthread_t poll_thread; >>>>> >>>>> so some of the things are static and some like poll_args >>>>> you alloced on the stack.. I dont like this interface, >>>>> could we come up with something generic? perhaps >>>>> encapsulated in perf_evlist, like: >>>> >>>> I picked global sb_evlist and poll_thread because there >>>> should be only one sb_evlist and one thread polling it. >>>> There might be multiple evsel on the sb_evlist. >>>> >>>> I am not sure I understand your suggestion.. >>>> >>>>> struct perf_evlist { >>>>> ... >>>>> struct { >>>>> pthread_t th; >>>>> int state; >>>>> } thread; >>>> >>>> This will not be used by the main perf_evlist, right? >>> >>> no, just by the thread interface >> >> What is "state" here? > > it's replacement for the 'done' pointer u had, > which I did not like.. leting each thread having > its own state is better IMO > > jirka I see. Let me try that. Song
> On Feb 27, 2019, at 5:21 AM, Jiri Olsa <jolsa@redhat.com> wrote: > > On Mon, Feb 25, 2019 at 04:20:18PM -0800, Song Liu wrote: > > SNIP > >> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c >> index 8c902276d4b4..61b87c8111e6 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> >> >> @@ -1841,3 +1842,102 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, >> } >> return leader; >> } >> + >> +static struct perf_evlist *sb_evlist; >> +pthread_t poll_thread; > > so some of the things are static and some like poll_args > you alloced on the stack.. I dont like this interface, > could we come up with something generic? perhaps > encapsulated in perf_evlist, like: > > struct perf_evlist { > ... > struct { > pthread_t th; > int state; > } thread; > }; > > typedef int (perf_evlist__thread_cb_t)(perf_evlist, union perf_event *event,....) > > perf_evlist__start_thread(perf_evlist, perf_evlist__thread_cb_t cb); > perf_evlist__stop_thread(perf_evlist); > > > jirka More questions on this proposal: IIUC, this approach creates one perf_evlist and one thread for each side band event (only bpf for now, more afterwards). Each of these perf_evlists will create its own ring buffer. On the other hand, current patch allows different events to share the thread, the perf_evlist, and the ring buffer. If my understanding is correct, current patch would be more efficient down the road? Did I miss some downsides of current patch? Thanks, Song
On Mon, Mar 04, 2019 at 09:40:07PM +0000, Song Liu wrote: > > > > On Feb 27, 2019, at 5:21 AM, Jiri Olsa <jolsa@redhat.com> wrote: > > > > On Mon, Feb 25, 2019 at 04:20:18PM -0800, Song Liu wrote: > > > > SNIP > > > >> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c > >> index 8c902276d4b4..61b87c8111e6 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> > >> > >> @@ -1841,3 +1842,102 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, > >> } > >> return leader; > >> } > >> + > >> +static struct perf_evlist *sb_evlist; > >> +pthread_t poll_thread; > > > > so some of the things are static and some like poll_args > > you alloced on the stack.. I dont like this interface, > > could we come up with something generic? perhaps > > encapsulated in perf_evlist, like: > > > > struct perf_evlist { > > ... > > struct { > > pthread_t th; > > int state; > > } thread; > > }; > > > > typedef int (perf_evlist__thread_cb_t)(perf_evlist, union perf_event *event,....) > > > > perf_evlist__start_thread(perf_evlist, perf_evlist__thread_cb_t cb); > > perf_evlist__stop_thread(perf_evlist); > > > > > > jirka > > More questions on this proposal: > > IIUC, this approach creates one perf_evlist and one thread for each side band > event (only bpf for now, more afterwards). Each of these perf_evlists will > create its own ring buffer. > > On the other hand, current patch allows different events to share the thread, > the perf_evlist, and the ring buffer. you can have those events in single evlist no? > > If my understanding is correct, current patch would be more efficient down the > road? Did I miss some downsides of current patch? I'd just like something configurable and with single handle not scattered around the code, so it's easy to add new callback jirka
> On Mar 5, 2019, at 3:03 AM, Jiri Olsa <jolsa@redhat.com> wrote: > > On Mon, Mar 04, 2019 at 09:40:07PM +0000, Song Liu wrote: >> >> >>> On Feb 27, 2019, at 5:21 AM, Jiri Olsa <jolsa@redhat.com> wrote: >>> >>> On Mon, Feb 25, 2019 at 04:20:18PM -0800, Song Liu wrote: >>> >>> SNIP >>> >>>> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c >>>> index 8c902276d4b4..61b87c8111e6 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> >>>> >>>> @@ -1841,3 +1842,102 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, >>>> } >>>> return leader; >>>> } >>>> + >>>> +static struct perf_evlist *sb_evlist; >>>> +pthread_t poll_thread; >>> >>> so some of the things are static and some like poll_args >>> you alloced on the stack.. I dont like this interface, >>> could we come up with something generic? perhaps >>> encapsulated in perf_evlist, like: >>> >>> struct perf_evlist { >>> ... >>> struct { >>> pthread_t th; >>> int state; >>> } thread; >>> }; >>> >>> typedef int (perf_evlist__thread_cb_t)(perf_evlist, union perf_event *event,....) >>> >>> perf_evlist__start_thread(perf_evlist, perf_evlist__thread_cb_t cb); >>> perf_evlist__stop_thread(perf_evlist); >>> >>> >>> jirka >> >> More questions on this proposal: >> >> IIUC, this approach creates one perf_evlist and one thread for each side band >> event (only bpf for now, more afterwards). Each of these perf_evlists will >> create its own ring buffer. >> >> On the other hand, current patch allows different events to share the thread, >> the perf_evlist, and the ring buffer. > > you can have those events in single evlist no? > >> >> If my understanding is correct, current patch would be more efficient down the >> road? Did I miss some downsides of current patch? > > I'd just like something configurable and with single handle > not scattered around the code, so it's easy to add new callback > > jirka To make adding callbacks easy, we need to register callback per perf_evsel, so multiple side band events could share the perf_evlist. It will be something like: typedef int (perf_evsel__sb_cb_t)(union perf_event *event, void *data); struct perf_evsel { ... struct { perf_evsel__sb_cb_t *cb; void *data; } side_band; }; perf_evlist__add_sb_event(struct perf_evlist *evlist, struct perf_event_attr *attr, perf_evsel__sb_cb_t cb, void *data); perf_evlist__start_sb_evlist(struct perf_evlist *evlist); perf_evlist__stop_sb_evlist(struct perf_evlist *evlist); Does this look like a good approach? Thanks, Song
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 2355e0a9eda0..d10c1d5a9e89 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1106,6 +1106,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_poll_args poll_args; int fd; atexit(record__sig_exit); @@ -1206,6 +1207,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) goto out_child; } + poll_args.env = &session->header.env; + poll_args.done = &done; + perf_evlist__start_polling_thread(&rec->opts.target, &poll_args); + err = record__synthesize(rec, false); if (err < 0) goto out_child; @@ -1456,6 +1461,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) out_delete_session: perf_session__delete(session); + + perf_evlist__stop_polling_thread(); return status; } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index ccdf5689452f..f41545445917 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1524,6 +1524,7 @@ int cmd_top(int argc, const char **argv) "number of thread to run event synthesize"), OPT_END() }; + struct perf_evlist_sb_poll_args poll_args; const char * const top_usage[] = { "perf top [<options>]", NULL @@ -1654,8 +1655,14 @@ int cmd_top(int argc, const char **argv) top.record_opts.bpf_event = !top.no_bpf_event; + poll_args.env = &perf_env; + poll_args.done = &done; + perf_evlist__start_polling_thread(target, &poll_args); + status = __cmd_top(&top); + perf_evlist__stop_polling_thread(); + out_delete_evlist: perf_evlist__delete(top.evlist); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 8c902276d4b4..61b87c8111e6 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> @@ -1841,3 +1842,102 @@ struct perf_evsel *perf_evlist__reset_weak_group(struct perf_evlist *evsel_list, } return leader; } + +static struct perf_evlist *sb_evlist; +pthread_t poll_thread; + +int perf_evlist__new_side_band_event(struct perf_event_attr *attr) +{ + struct perf_evsel *evsel; + + if (!sb_evlist) + sb_evlist = perf_evlist__new(); + + if (!sb_evlist) + return -1; + + evsel = perf_evsel__new_idx(attr, sb_evlist->nr_entries); + if (!evsel) + goto out_err; + + perf_evlist__add(sb_evlist, evsel); + return 0; + +out_err: + perf_evlist__delete(sb_evlist); + return -1; +} + +static void *perf_evlist__poll_thread(void *arg) +{ + struct perf_evlist_sb_poll_args *args = arg; + int i; + + while (!*(args->done)) { + perf_evlist__poll(sb_evlist, 1000); + + for (i = 0; i < sb_evlist->nr_mmaps; i++) { + struct perf_mmap *map = &sb_evlist->mmap[i]; + union perf_event *event; + + if (perf_mmap__read_init(map)) + continue; + while ((event = perf_mmap__read_event(map)) != NULL) { + pr_debug("processing vip event of type %d\n", + event->header.type); + switch (event->header.type) { + default: + break; + } + perf_mmap__consume(map); + } + perf_mmap__read_done(map); + } + } + return NULL; +} + +int perf_evlist__start_polling_thread(struct target *target, + struct perf_evlist_sb_poll_args *args) +{ + struct perf_evsel *counter; + + if (sb_evlist == NULL) + return 0; + + if (perf_evlist__create_maps(sb_evlist, target)) + goto out_delete_evlist; + + evlist__for_each_entry(sb_evlist, counter) { + if (perf_evsel__open(counter, sb_evlist->cpus, + sb_evlist->threads) < 0) + goto out_delete_evlist; + } + + if (perf_evlist__mmap(sb_evlist, UINT_MAX)) + goto out_delete_evlist; + + evlist__for_each_entry(sb_evlist, counter) { + if (perf_evsel__enable(counter)) + goto out_delete_evlist; + } + + if (pthread_create(&poll_thread, NULL, perf_evlist__poll_thread, args)) + goto out_delete_evlist; + + return 0; + +out_delete_evlist: + perf_evlist__delete(sb_evlist); + sb_evlist = NULL; + return -1; +} + +void perf_evlist__stop_polling_thread(void) +{ + if (!sb_evlist) + return; + pthread_join(poll_thread, NULL); + perf_evlist__exit(sb_evlist); + sb_evlist = NULL; +} diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 868294491194..4182e50659e0 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -58,6 +58,12 @@ struct perf_evsel_str_handler { void *handler; }; +struct perf_evlist_sb_poll_args { + struct perf_env *env; + + volatile int *done; +}; + struct perf_evlist *perf_evlist__new(void); struct perf_evlist *perf_evlist__new_default(void); struct perf_evlist *perf_evlist__new_dummy(void); @@ -84,6 +90,13 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, int perf_evlist__add_dummy(struct perf_evlist *evlist); +int perf_evlist__new_side_band_event(struct perf_event_attr *attr); + +int perf_evlist__start_polling_thread(struct target *target, + struct perf_evlist_sb_poll_args *args); + +void perf_evlist__stop_polling_thread(void); + int perf_evlist__add_newtp(struct perf_evlist *evlist, const char *sys, const char *name, void *handler);
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. In the next patch, we uses this thread to handle PERF_RECORD_BPF_EVENT. Signed-off-by: Song Liu <songliubraving@fb.com> --- tools/perf/builtin-record.c | 7 +++ tools/perf/builtin-top.c | 7 +++ tools/perf/util/evlist.c | 100 ++++++++++++++++++++++++++++++++++++ tools/perf/util/evlist.h | 13 +++++ 4 files changed, 127 insertions(+)