On Mon, Nov 16, 2020 at 03:16:19PM +0300, Alexey Budankov wrote:
> 
> Introduce thread local variable and use it for threaded trace streaming.
> Use thread affinity mask instead or record affinity mask in affinity modes.
> Introduce and use evlist__ctlfd_update() function to propogate external
> control commands to global evlist object.
> 
> Signed-off-by: Alexey Budankov <[email protected]>
> ---
>  tools/perf/builtin-record.c | 137 ++++++++++++++++++++++++------------
>  tools/perf/util/evlist.c    |  16 +++++
>  tools/perf/util/evlist.h    |   1 +
>  3 files changed, 109 insertions(+), 45 deletions(-)
> 
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 765a90e38f69..e41e1cd90168 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
[SNIP]
> @@ -2114,20 +2165,26 @@ static int __cmd_record(struct record *rec, int argc, 
> const char **argv)
>                               alarm(rec->switch_output.time);
>               }
>  
> -             if (hits == rec->samples) {
> +             if (hits == thread->samples) {
>                       if (done || draining)
>                               break;
> -                     err = evlist__poll(rec->evlist, -1);
> +                     err = fdarray__poll(&thread->pollfd, -1);
>                       /*
>                        * Propagate error, only if there's any. Ignore positive
>                        * number of returned events and interrupt error.
>                        */
>                       if (err > 0 || (err < 0 && errno == EINTR))
>                               err = 0;
> -                     waking++;
> +                     thread->waking++;
>  
> -                     if (evlist__filter_pollfd(rec->evlist, POLLERR | 
> POLLHUP) == 0)
> +                     if (fdarray__filter(&thread->pollfd, POLLERR | POLLHUP,
> +                                         record__thread_munmap_filtered, 
> NULL) == 0)
>                               draining = true;
> +
> +                     if (thread->ctlfd_pos != -1) {

Isn't it only for the first thread?  I guess all thread should have
non-negative ctlfd_pos so this check seems meaningless, no?

Thanks,
Namhyung


> +                             evlist__ctlfd_update(rec->evlist,
> +                                     
> &thread->pollfd.entries[thread->ctlfd_pos]);
> +                     }
>               }
>  
>               if (evlist__ctlfd_process(rec->evlist, &cmd) > 0) {
> @@ -2175,18 +2232,20 @@ static int __cmd_record(struct record *rec, int argc, 
> const char **argv)
>               goto out_child;
>       }
>  
> -     if (!quiet)
> -             fprintf(stderr, "[ perf record: Woken up %ld times to write 
> data ]\n", waking);
> -
>       if (target__none(&rec->opts.target))
>               record__synthesize_workload(rec, true);
>  
>  out_child:
> +     record__stop_threads(rec, &waking);
> +out_free_threads:
>       record__free_thread_data(rec);
>       evlist__finalize_ctlfd(rec->evlist);
>       record__mmap_read_all(rec, true);
>       record__aio_mmap_read_sync(rec);
>  
> +     if (!quiet)
> +             fprintf(stderr, "[ perf record: Woken up %ld times to write 
> data ]\n", waking);
> +
>       if (rec->session->bytes_transferred && rec->session->bytes_compressed) {
>               ratio = 
> (float)rec->session->bytes_transferred/(float)rec->session->bytes_compressed;
>               session->header.env.comp_ratio = ratio + 0.5;
> @@ -2995,17 +3054,6 @@ int cmd_record(int argc, const char **argv)
>  
>       symbol__init(NULL);
>  
> -     if (rec->opts.affinity != PERF_AFFINITY_SYS) {
> -             rec->affinity_mask.nbits = cpu__max_cpu();
> -             rec->affinity_mask.bits = 
> bitmap_alloc(rec->affinity_mask.nbits);
> -             if (!rec->affinity_mask.bits) {
> -                     pr_err("Failed to allocate thread mask for %zd cpus\n", 
> rec->affinity_mask.nbits);
> -                     err = -ENOMEM;
> -                     goto out_opts;
> -             }
> -             pr_debug2("thread mask[%zd]: empty\n", 
> rec->affinity_mask.nbits);
> -     }
> -
>       err = record__auxtrace_init(rec);
>       if (err)
>               goto out;
> @@ -3134,7 +3182,6 @@ int cmd_record(int argc, const char **argv)
>  
>       err = __cmd_record(&record, argc, argv);
>  out:
> -     bitmap_free(rec->affinity_mask.bits);
>       evlist__delete(rec->evlist);
>       symbol__exit();
>       auxtrace_record__free(rec->itr);
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index 8bdf3d2c907c..758a4896fedd 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -1970,6 +1970,22 @@ int evlist__ctlfd_process(struct evlist *evlist, enum 
> evlist_ctl_cmd *cmd)
>       return err;
>  }
>  
> +int evlist__ctlfd_update(struct evlist *evlist, struct pollfd *update)
> +{
> +     int ctlfd_pos = evlist->ctl_fd.pos;
> +     struct pollfd *entries = evlist->core.pollfd.entries;
> +
> +     if (!evlist__ctlfd_initialized(evlist))
> +             return 0;
> +
> +     if (entries[ctlfd_pos].fd != update->fd ||
> +         entries[ctlfd_pos].events != update->events)
> +             return -1;
> +
> +     entries[ctlfd_pos].revents = update->revents;
> +     return 0;
> +}
> +
>  struct evsel *evlist__find_evsel(struct evlist *evlist, int idx)
>  {
>       struct evsel *evsel;
> diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
> index e1a450322bc5..9b73d6ccf066 100644
> --- a/tools/perf/util/evlist.h
> +++ b/tools/perf/util/evlist.h
> @@ -380,6 +380,7 @@ void evlist__close_control(int ctl_fd, int ctl_fd_ack, 
> bool *ctl_fd_close);
>  int evlist__initialize_ctlfd(struct evlist *evlist, int ctl_fd, int 
> ctl_fd_ack);
>  int evlist__finalize_ctlfd(struct evlist *evlist);
>  bool evlist__ctlfd_initialized(struct evlist *evlist);
> +int evlist__ctlfd_update(struct evlist *evlist, struct pollfd *update);
>  int evlist__ctlfd_process(struct evlist *evlist, enum evlist_ctl_cmd *cmd);
>  int evlist__ctlfd_ack(struct evlist *evlist);
>  
> -- 
> 2.24.1
> 
> 

Reply via email to