Messages in this thread | | | From | Arnaldo Carvalho de Melo <> | Date | Wed, 6 May 2020 17:21:38 -0300 | Subject | Re: [PATCH v2 02/11] perf evlist: implement control command handling functions |
| |
Em Wed, May 06, 2020 at 09:19:22PM +0300, Alexey Budankov escreveu: > > Implement functions of initialization, finalization and processing > of control commands coming from control file descriptors. > > Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com> > --- > tools/perf/util/evlist.c | 100 +++++++++++++++++++++++++++++++++++++++ > tools/perf/util/evlist.h | 12 +++++ > 2 files changed, 112 insertions(+) > > diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c > index 2db4bedc4f81..e086c846ef3a 100644 > --- a/tools/perf/util/evlist.c > +++ b/tools/perf/util/evlist.c > @@ -1707,3 +1707,103 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list, > } > return leader; > } > + > +int perf_evlist__initialize_ctlfd(struct evlist *evlist, int ctl_fd, int ctl_fd_ack) > +{ > + if (ctl_fd == -1) { > + pr_debug("Control descriptor is not initialized\n"); > + return 0; > + } > + > + evlist->ctl_fd_pos = perf_evlist__add_pollfd(&evlist->core, ctl_fd, NULL, POLLIN); > + if (evlist->ctl_fd_pos < 0) { > + evlist->ctl_fd_pos = -1; > + pr_err("Failed to add ctl fd entry: %m\n"); > + return -1; > + } > + > + evlist->ctl_fd = ctl_fd; > + evlist->ctl_fd_ack = ctl_fd_ack; > + > + return 0; > +} > + > +int perf_evlist__finalize_ctlfd(struct evlist *evlist) > +{ > + if (evlist->ctl_fd_pos == -1) > + return 0; > + > + evlist->core.pollfd.entries[evlist->ctl_fd_pos].fd = -1; > + evlist->ctl_fd_pos = -1; > + evlist->ctl_fd_ack = -1; > + evlist->ctl_fd = -1; > + > + return 0; > +} > + > +static int perf_evlist__ctlfd_recv(struct evlist *evlist, enum evlist_ctl_cmd *cmd) > +{ > + int err; > + char buf[2]; > + > + err = read(evlist->ctl_fd, &buf, sizeof(buf)); > + if (err > 0) > + *cmd = buf[0]; > + else if (err == -1) > + pr_err("Failed to read from ctlfd %d: %m\n", evlist->ctl_fd); > + > + return err; > +} > + > +static int perf_evlist__ctlfd_ack(struct evlist *evlist) > +{ > + int err; > + char buf[2] = {CTL_CMD_ACK, '\n'}; > + > + if (evlist->ctl_fd_ack == -1) > + return 0; > + > + err = write(evlist->ctl_fd_ack, buf, sizeof(buf)); > + if (err == -1) > + pr_err("failed to write to ctl_ack_fd %d: %m\n", evlist->ctl_fd_ack); > + > + return err; > +} > + > +int perf_evlist__ctlfd_process(struct evlist *evlist, enum evlist_ctl_cmd *cmd) > +{ > + int err = 0; > + int ctlfd_pos = evlist->ctl_fd_pos; > + struct pollfd *entries = evlist->core.pollfd.entries; > + > + if (!entries[ctlfd_pos].revents) > + return 0; > + > + if (entries[ctlfd_pos].revents & POLLIN) { > + err = perf_evlist__ctlfd_recv(evlist, cmd); > + if (err > 0) { > + switch (*cmd) { > + case CTL_CMD_ENABLE: > + evlist__enable(evlist); > + break; > + case CTL_CMD_DISABLE: > + evlist__disable(evlist); > + break; > + case CTL_CMD_ACK: > + case CTL_CMD_UNSUPPORTED: > + default: > + pr_debug("ctlfd: unsupported %d\n", *cmd); > + break; > + } > + if (!(*cmd == CTL_CMD_ACK || *cmd == CTL_CMD_UNSUPPORTED)) > + perf_evlist__ctlfd_ack(evlist); > + } > + } > + > + if (entries[ctlfd_pos].revents & (POLLHUP | POLLERR)) > + perf_evlist__finalize_ctlfd(evlist); > + else > + entries[ctlfd_pos].revents = 0; > + > + return err; > +} > diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h > index 62f259d89b41..84386850c290 100644 > --- a/tools/perf/util/evlist.h > +++ b/tools/perf/util/evlist.h > @@ -358,4 +358,16 @@ void perf_evlist__force_leader(struct evlist *evlist); > struct evsel *perf_evlist__reset_weak_group(struct evlist *evlist, > struct evsel *evsel, > bool close); > + > +enum evlist_ctl_cmd { > + CTL_CMD_UNSUPPORTED = 0, > + CTL_CMD_ENABLE = 'e', > + CTL_CMD_DISABLE = 'd', > + CTL_CMD_ACK = 'a' > +};
Can we make this a string, I think we'll eventually ask for lots more stuff, like asking for a --switch-output snapshot with --overwrite, reconfiguring events to increase/decrease frequency, etc, interfacing with PERF_EVENT_IOC_MODIFY_ATTRIBUTES, PERF_EVENT_IOC_SET_FILTER, etc.
This will also allow us to have parameters, etc, wdyt?
Also please since these are events that deal with 'struct evlist', name them with the evlist__ prefix, not the perf_evlist__ one, as those should be used with 'struct perf_evlist', i.e. the one in libperf (tools/lib/perf/).
Right now this is inconsistent, we did it that way to minimize disruption of the codebase when moving things from tools/perf/ to tools/lib/perf/, but this confuses things and I just did a s/perf_evsel__/evsel__) for things dealing with 'struct evsel', so lets not add new ones with the wrong prefix, eventually we'll have perf_ only for things in libperf.
> + > +int perf_evlist__initialize_ctlfd(struct evlist *evlist, int ctl_fd, int ctl_fd_ack); > +int perf_evlist__finalize_ctlfd(struct evlist *evlist); > +int perf_evlist__ctlfd_process(struct evlist *evlist, enum evlist_ctl_cmd *cmd); > + > #endif /* __PERF_EVLIST_H */ > -- > 2.24.1 > >
--
- Arnaldo
| |