Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Controller of read/write threads for virtio-trace
0004  *
0005  * Copyright (C) 2012 Hitachi, Ltd.
0006  * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
0007  *            Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
0008  */
0009 
0010 #define _GNU_SOURCE
0011 #include <fcntl.h>
0012 #include <poll.h>
0013 #include <signal.h>
0014 #include <stdio.h>
0015 #include <stdlib.h>
0016 #include <unistd.h>
0017 #include "trace-agent.h"
0018 
0019 #define HOST_MSG_SIZE       256
0020 #define EVENT_WAIT_MSEC     100
0021 
0022 static volatile sig_atomic_t global_signal_val;
0023 bool global_sig_receive;    /* default false */
0024 bool global_run_operation;  /* default false*/
0025 
0026 /* Handle SIGTERM/SIGINT/SIGQUIT to exit */
0027 static void signal_handler(int sig)
0028 {
0029     global_signal_val = sig;
0030 }
0031 
0032 int rw_ctl_init(const char *ctl_path)
0033 {
0034     int ctl_fd;
0035 
0036     ctl_fd = open(ctl_path, O_RDONLY);
0037     if (ctl_fd == -1) {
0038         pr_err("Cannot open ctl_fd\n");
0039         goto error;
0040     }
0041 
0042     return ctl_fd;
0043 
0044 error:
0045     exit(EXIT_FAILURE);
0046 }
0047 
0048 static int wait_order(int ctl_fd)
0049 {
0050     struct pollfd poll_fd;
0051     int ret = 0;
0052 
0053     while (!global_sig_receive) {
0054         poll_fd.fd = ctl_fd;
0055         poll_fd.events = POLLIN;
0056 
0057         ret = poll(&poll_fd, 1, EVENT_WAIT_MSEC);
0058 
0059         if (global_signal_val) {
0060             global_sig_receive = true;
0061             pr_info("Receive interrupt %d\n", global_signal_val);
0062 
0063             /* Wakes rw-threads when they are sleeping */
0064             if (!global_run_operation)
0065                 pthread_cond_broadcast(&cond_wakeup);
0066 
0067             ret = -1;
0068             break;
0069         }
0070 
0071         if (ret < 0) {
0072             pr_err("Polling error\n");
0073             goto error;
0074         }
0075 
0076         if (ret)
0077             break;
0078     };
0079 
0080     return ret;
0081 
0082 error:
0083     exit(EXIT_FAILURE);
0084 }
0085 
0086 /*
0087  * contol read/write threads by handling global_run_operation
0088  */
0089 void *rw_ctl_loop(int ctl_fd)
0090 {
0091     ssize_t rlen;
0092     char buf[HOST_MSG_SIZE];
0093     int ret;
0094 
0095     /* Setup signal handlers */
0096     signal(SIGTERM, signal_handler);
0097     signal(SIGINT, signal_handler);
0098     signal(SIGQUIT, signal_handler);
0099 
0100     while (!global_sig_receive) {
0101 
0102         ret = wait_order(ctl_fd);
0103         if (ret < 0)
0104             break;
0105 
0106         rlen = read(ctl_fd, buf, sizeof(buf));
0107         if (rlen < 0) {
0108             pr_err("read data error in ctl thread\n");
0109             goto error;
0110         }
0111 
0112         if (rlen == 2 && buf[0] == '1') {
0113             /*
0114              * If host writes '1' to a control path,
0115              * this controller wakes all read/write threads.
0116              */
0117             global_run_operation = true;
0118             pthread_cond_broadcast(&cond_wakeup);
0119             pr_debug("Wake up all read/write threads\n");
0120         } else if (rlen == 2 && buf[0] == '0') {
0121             /*
0122              * If host writes '0' to a control path, read/write
0123              * threads will wait for notification from Host.
0124              */
0125             global_run_operation = false;
0126             pr_debug("Stop all read/write threads\n");
0127         } else
0128             pr_info("Invalid host notification: %s\n", buf);
0129     }
0130 
0131     return NULL;
0132 
0133 error:
0134     exit(EXIT_FAILURE);
0135 }