linux/tools/virtio/virtio-trace/trace-agent-ctl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Controller of read/write threads for virtio-trace
   4 *
   5 * Copyright (C) 2012 Hitachi, Ltd.
   6 * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
   7 *            Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
   8 */
   9
  10#define _GNU_SOURCE
  11#include <fcntl.h>
  12#include <poll.h>
  13#include <signal.h>
  14#include <stdio.h>
  15#include <stdlib.h>
  16#include <unistd.h>
  17#include "trace-agent.h"
  18
  19#define HOST_MSG_SIZE           256
  20#define EVENT_WAIT_MSEC         100
  21
  22static volatile sig_atomic_t global_signal_val;
  23bool global_sig_receive;        /* default false */
  24bool global_run_operation;      /* default false*/
  25
  26/* Handle SIGTERM/SIGINT/SIGQUIT to exit */
  27static void signal_handler(int sig)
  28{
  29        global_signal_val = sig;
  30}
  31
  32int rw_ctl_init(const char *ctl_path)
  33{
  34        int ctl_fd;
  35
  36        ctl_fd = open(ctl_path, O_RDONLY);
  37        if (ctl_fd == -1) {
  38                pr_err("Cannot open ctl_fd\n");
  39                goto error;
  40        }
  41
  42        return ctl_fd;
  43
  44error:
  45        exit(EXIT_FAILURE);
  46}
  47
  48static int wait_order(int ctl_fd)
  49{
  50        struct pollfd poll_fd;
  51        int ret = 0;
  52
  53        while (!global_sig_receive) {
  54                poll_fd.fd = ctl_fd;
  55                poll_fd.events = POLLIN;
  56
  57                ret = poll(&poll_fd, 1, EVENT_WAIT_MSEC);
  58
  59                if (global_signal_val) {
  60                        global_sig_receive = true;
  61                        pr_info("Receive interrupt %d\n", global_signal_val);
  62
  63                        /* Wakes rw-threads when they are sleeping */
  64                        if (!global_run_operation)
  65                                pthread_cond_broadcast(&cond_wakeup);
  66
  67                        ret = -1;
  68                        break;
  69                }
  70
  71                if (ret < 0) {
  72                        pr_err("Polling error\n");
  73                        goto error;
  74                }
  75
  76                if (ret)
  77                        break;
  78        };
  79
  80        return ret;
  81
  82error:
  83        exit(EXIT_FAILURE);
  84}
  85
  86/*
  87 * contol read/write threads by handling global_run_operation
  88 */
  89void *rw_ctl_loop(int ctl_fd)
  90{
  91        ssize_t rlen;
  92        char buf[HOST_MSG_SIZE];
  93        int ret;
  94
  95        /* Setup signal handlers */
  96        signal(SIGTERM, signal_handler);
  97        signal(SIGINT, signal_handler);
  98        signal(SIGQUIT, signal_handler);
  99
 100        while (!global_sig_receive) {
 101
 102                ret = wait_order(ctl_fd);
 103                if (ret < 0)
 104                        break;
 105
 106                rlen = read(ctl_fd, buf, sizeof(buf));
 107                if (rlen < 0) {
 108                        pr_err("read data error in ctl thread\n");
 109                        goto error;
 110                }
 111
 112                if (rlen == 2 && buf[0] == '1') {
 113                        /*
 114                         * If host writes '1' to a control path,
 115                         * this controller wakes all read/write threads.
 116                         */
 117                        global_run_operation = true;
 118                        pthread_cond_broadcast(&cond_wakeup);
 119                        pr_debug("Wake up all read/write threads\n");
 120                } else if (rlen == 2 && buf[0] == '0') {
 121                        /*
 122                         * If host writes '0' to a control path, read/write
 123                         * threads will wait for notification from Host.
 124                         */
 125                        global_run_operation = false;
 126                        pr_debug("Stop all read/write threads\n");
 127                } else
 128                        pr_info("Invalid host notification: %s\n", buf);
 129        }
 130
 131        return NULL;
 132
 133error:
 134        exit(EXIT_FAILURE);
 135}
 136