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 <[email protected]> > --- > 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

