root/tools/virtio/virtio-trace/trace-agent-ctl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. signal_handler
  2. rw_ctl_init
  3. wait_order
  4. rw_ctl_loop

   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 
  22 static volatile sig_atomic_t global_signal_val;
  23 bool global_sig_receive;        /* default false */
  24 bool global_run_operation;      /* default false*/
  25 
  26 /* Handle SIGTERM/SIGINT/SIGQUIT to exit */
  27 static void signal_handler(int sig)
  28 {
  29         global_signal_val = sig;
  30 }
  31 
  32 int 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 
  44 error:
  45         exit(EXIT_FAILURE);
  46 }
  47 
  48 static 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 
  82 error:
  83         exit(EXIT_FAILURE);
  84 }
  85 
  86 /*
  87  * contol read/write threads by handling global_run_operation
  88  */
  89 void *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 
 133 error:
 134         exit(EXIT_FAILURE);
 135 }

/* [<][>][^][v][top][bottom][index][help] */