lkml.org 
[lkml]   [2020]   [Jun]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v7 03/13] perf evlist: implement control command handling functions
    Date

    Implement functions of initialization, finalization and processing
    of control command messages coming from control file descriptors.
    Allocate control file descriptor as a static descriptor at struct
    pollfd object of evsel_list using perf_evlist__add_pollfd_stat().

    Signed-off-by: Alexey Budankov <alexey.budankov@linux.intel.com>
    ---
    tools/perf/util/evlist.c | 128 +++++++++++++++++++++++++++++++++++++++
    tools/perf/util/evlist.h | 17 ++++++
    2 files changed, 145 insertions(+)

    diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
    index 47541b5cab46..fbd98f741af9 100644
    --- a/tools/perf/util/evlist.c
    +++ b/tools/perf/util/evlist.c
    @@ -1718,3 +1718,131 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
    }
    return leader;
    }
    +
    +int evlist__initialize_ctlfd(struct evlist *evlist, int fd, int ack)
    +{
    + if (fd == -1) {
    + pr_debug("Control descriptor is not initialized\n");
    + return 0;
    + }
    +
    + evlist->ctl_fd.pos = perf_evlist__add_pollfd_stat(&evlist->core, fd, 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.fd = fd;
    + evlist->ctl_fd.ack = ack;
    +
    + return 0;
    +}
    +
    +int evlist__finalize_ctlfd(struct evlist *evlist)
    +{
    + if (evlist->ctl_fd.pos == -1)
    + return 0;
    +
    + evlist->core.pollfd.stat_entries[evlist->ctl_fd.pos].fd = -1;
    + evlist->ctl_fd.pos = -1;
    + evlist->ctl_fd.ack = -1;
    + evlist->ctl_fd.fd = -1;
    +
    + return 0;
    +}
    +
    +static int evlist__ctlfd_recv(struct evlist *evlist, enum evlist_ctl_cmd *cmd,
    + char *cmd_data, size_t data_size)
    +{
    + int err;
    + char c;
    + size_t bytes_read = 0;
    +
    + memset(cmd_data, 0, data_size--);
    +
    + do {
    + err = read(evlist->ctl_fd.fd, &c, 1);
    + if (err > 0) {
    + if (c == '\n' || c == '\0')
    + break;
    + cmd_data[bytes_read++] = c;
    + if (bytes_read == data_size)
    + break;
    + } else {
    + if (err == -1)
    + pr_err("Failed to read from ctlfd %d: %m\n", evlist->ctl_fd.fd);
    + break;
    + }
    + } while (1);
    +
    + pr_debug("Message from ctl_fd: \"%s%s\"\n", cmd_data,
    + bytes_read == data_size ? "" : c == '\n' ? "\\n" : "\\0");
    +
    + if (err > 0) {
    + if (!strncmp(cmd_data, EVLIST_CTL_CMD_ENABLE_TAG,
    + strlen(EVLIST_CTL_CMD_ENABLE_TAG))) {
    + *cmd = EVLIST_CTL_CMD_ENABLE;
    + } else if (!strncmp(cmd_data, EVLIST_CTL_CMD_DISABLE_TAG,
    + strlen(EVLIST_CTL_CMD_DISABLE_TAG))) {
    + *cmd = EVLIST_CTL_CMD_DISABLE;
    + }
    + }
    +
    + return err;
    +}
    +
    +static int evlist__ctlfd_ack(struct evlist *evlist)
    +{
    + int err;
    +
    + if (evlist->ctl_fd.ack == -1)
    + return 0;
    +
    + err = write(evlist->ctl_fd.ack, EVLIST_CTL_CMD_ACK_TAG,
    + sizeof(EVLIST_CTL_CMD_ACK_TAG));
    + if (err == -1)
    + pr_err("failed to write to ctl_ack_fd %d: %m\n", evlist->ctl_fd.ack);
    +
    + return err;
    +}
    +
    +int evlist__ctlfd_process(struct evlist *evlist, enum evlist_ctl_cmd *cmd)
    +{
    + int err = 0;
    + char cmd_data[EVLIST_CTL_CMD_MAX_LEN];
    + int ctlfd_pos = evlist->ctl_fd.pos;
    + struct pollfd *stat_entries = evlist->core.pollfd.stat_entries;
    +
    + if (ctlfd_pos == -1 || !stat_entries[ctlfd_pos].revents)
    + return 0;
    +
    + if (stat_entries[ctlfd_pos].revents & POLLIN) {
    + err = evlist__ctlfd_recv(evlist, cmd, cmd_data,
    + EVLIST_CTL_CMD_MAX_LEN);
    + if (err > 0) {
    + switch (*cmd) {
    + case EVLIST_CTL_CMD_ENABLE:
    + evlist__enable(evlist);
    + break;
    + case EVLIST_CTL_CMD_DISABLE:
    + evlist__disable(evlist);
    + break;
    + case EVLIST_CTL_CMD_ACK:
    + case EVLIST_CTL_CMD_UNSUPPORTED:
    + default:
    + pr_debug("ctlfd: unsupported %d\n", *cmd);
    + break;
    + }
    + if (!(*cmd == EVLIST_CTL_CMD_ACK || *cmd == EVLIST_CTL_CMD_UNSUPPORTED))
    + evlist__ctlfd_ack(evlist);
    + }
    + }
    +
    + if (stat_entries[ctlfd_pos].revents & (POLLHUP | POLLERR))
    + evlist__finalize_ctlfd(evlist);
    + else
    + stat_entries[ctlfd_pos].revents = 0;
    +
    + return err;
    +}
    diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
    index 0d8b361f1c8e..bccf0a970371 100644
    --- a/tools/perf/util/evlist.h
    +++ b/tools/perf/util/evlist.h
    @@ -360,4 +360,21 @@ void perf_evlist__force_leader(struct evlist *evlist);
    struct evsel *perf_evlist__reset_weak_group(struct evlist *evlist,
    struct evsel *evsel,
    bool close);
    +#define EVLIST_CTL_CMD_ENABLE_TAG "enable"
    +#define EVLIST_CTL_CMD_DISABLE_TAG "disable"
    +#define EVLIST_CTL_CMD_ACK_TAG "ack\n"
    +
    +#define EVLIST_CTL_CMD_MAX_LEN 64
    +
    +enum evlist_ctl_cmd {
    + EVLIST_CTL_CMD_UNSUPPORTED = 0,
    + EVLIST_CTL_CMD_ENABLE,
    + EVLIST_CTL_CMD_DISABLE,
    + EVLIST_CTL_CMD_ACK
    +};
    +
    +int evlist__initialize_ctlfd(struct evlist *evlist, int ctl_fd, int ctl_fd_ack);
    +int evlist__finalize_ctlfd(struct evlist *evlist);
    +int evlist__ctlfd_process(struct evlist *evlist, enum evlist_ctl_cmd *cmd);
    +
    #endif /* __PERF_EVLIST_H */
    --
    2.24.1
    \
     
     \ /
      Last update: 2020-06-03 17:55    [W:3.199 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site