Implement functions of initialization, finalization and processing
of control commands coming from control file descriptors.

Signed-off-by: Alexey Budankov <alexey.budan...@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'
+};
+
+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


Reply via email to