14a27fd15SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2108fc825SYoshihiro YUNOMAE /*
3108fc825SYoshihiro YUNOMAE * Controller of read/write threads for virtio-trace
4108fc825SYoshihiro YUNOMAE *
5108fc825SYoshihiro YUNOMAE * Copyright (C) 2012 Hitachi, Ltd.
6108fc825SYoshihiro YUNOMAE * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
7108fc825SYoshihiro YUNOMAE * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
8108fc825SYoshihiro YUNOMAE */
9108fc825SYoshihiro YUNOMAE
10108fc825SYoshihiro YUNOMAE #define _GNU_SOURCE
11108fc825SYoshihiro YUNOMAE #include <fcntl.h>
12108fc825SYoshihiro YUNOMAE #include <poll.h>
13108fc825SYoshihiro YUNOMAE #include <signal.h>
14108fc825SYoshihiro YUNOMAE #include <stdio.h>
15108fc825SYoshihiro YUNOMAE #include <stdlib.h>
16108fc825SYoshihiro YUNOMAE #include <unistd.h>
17108fc825SYoshihiro YUNOMAE #include "trace-agent.h"
18108fc825SYoshihiro YUNOMAE
19108fc825SYoshihiro YUNOMAE #define HOST_MSG_SIZE 256
20108fc825SYoshihiro YUNOMAE #define EVENT_WAIT_MSEC 100
21108fc825SYoshihiro YUNOMAE
22108fc825SYoshihiro YUNOMAE static volatile sig_atomic_t global_signal_val;
23108fc825SYoshihiro YUNOMAE bool global_sig_receive; /* default false */
24108fc825SYoshihiro YUNOMAE bool global_run_operation; /* default false*/
25108fc825SYoshihiro YUNOMAE
26108fc825SYoshihiro YUNOMAE /* Handle SIGTERM/SIGINT/SIGQUIT to exit */
signal_handler(int sig)27108fc825SYoshihiro YUNOMAE static void signal_handler(int sig)
28108fc825SYoshihiro YUNOMAE {
29108fc825SYoshihiro YUNOMAE global_signal_val = sig;
30108fc825SYoshihiro YUNOMAE }
31108fc825SYoshihiro YUNOMAE
rw_ctl_init(const char * ctl_path)32108fc825SYoshihiro YUNOMAE int rw_ctl_init(const char *ctl_path)
33108fc825SYoshihiro YUNOMAE {
34108fc825SYoshihiro YUNOMAE int ctl_fd;
35108fc825SYoshihiro YUNOMAE
36108fc825SYoshihiro YUNOMAE ctl_fd = open(ctl_path, O_RDONLY);
37108fc825SYoshihiro YUNOMAE if (ctl_fd == -1) {
38108fc825SYoshihiro YUNOMAE pr_err("Cannot open ctl_fd\n");
39108fc825SYoshihiro YUNOMAE goto error;
40108fc825SYoshihiro YUNOMAE }
41108fc825SYoshihiro YUNOMAE
42108fc825SYoshihiro YUNOMAE return ctl_fd;
43108fc825SYoshihiro YUNOMAE
44108fc825SYoshihiro YUNOMAE error:
45108fc825SYoshihiro YUNOMAE exit(EXIT_FAILURE);
46108fc825SYoshihiro YUNOMAE }
47108fc825SYoshihiro YUNOMAE
wait_order(int ctl_fd)48108fc825SYoshihiro YUNOMAE static int wait_order(int ctl_fd)
49108fc825SYoshihiro YUNOMAE {
50108fc825SYoshihiro YUNOMAE struct pollfd poll_fd;
51108fc825SYoshihiro YUNOMAE int ret = 0;
52108fc825SYoshihiro YUNOMAE
53108fc825SYoshihiro YUNOMAE while (!global_sig_receive) {
54108fc825SYoshihiro YUNOMAE poll_fd.fd = ctl_fd;
55108fc825SYoshihiro YUNOMAE poll_fd.events = POLLIN;
56108fc825SYoshihiro YUNOMAE
57108fc825SYoshihiro YUNOMAE ret = poll(&poll_fd, 1, EVENT_WAIT_MSEC);
58108fc825SYoshihiro YUNOMAE
59108fc825SYoshihiro YUNOMAE if (global_signal_val) {
60108fc825SYoshihiro YUNOMAE global_sig_receive = true;
61108fc825SYoshihiro YUNOMAE pr_info("Receive interrupt %d\n", global_signal_val);
62108fc825SYoshihiro YUNOMAE
63108fc825SYoshihiro YUNOMAE /* Wakes rw-threads when they are sleeping */
64108fc825SYoshihiro YUNOMAE if (!global_run_operation)
65108fc825SYoshihiro YUNOMAE pthread_cond_broadcast(&cond_wakeup);
66108fc825SYoshihiro YUNOMAE
67108fc825SYoshihiro YUNOMAE ret = -1;
68108fc825SYoshihiro YUNOMAE break;
69108fc825SYoshihiro YUNOMAE }
70108fc825SYoshihiro YUNOMAE
71108fc825SYoshihiro YUNOMAE if (ret < 0) {
72108fc825SYoshihiro YUNOMAE pr_err("Polling error\n");
73108fc825SYoshihiro YUNOMAE goto error;
74108fc825SYoshihiro YUNOMAE }
75108fc825SYoshihiro YUNOMAE
76108fc825SYoshihiro YUNOMAE if (ret)
77108fc825SYoshihiro YUNOMAE break;
78*75e4ab97SShaomin Deng }
79108fc825SYoshihiro YUNOMAE
80108fc825SYoshihiro YUNOMAE return ret;
81108fc825SYoshihiro YUNOMAE
82108fc825SYoshihiro YUNOMAE error:
83108fc825SYoshihiro YUNOMAE exit(EXIT_FAILURE);
84108fc825SYoshihiro YUNOMAE }
85108fc825SYoshihiro YUNOMAE
86108fc825SYoshihiro YUNOMAE /*
87108fc825SYoshihiro YUNOMAE * contol read/write threads by handling global_run_operation
88108fc825SYoshihiro YUNOMAE */
rw_ctl_loop(int ctl_fd)89108fc825SYoshihiro YUNOMAE void *rw_ctl_loop(int ctl_fd)
90108fc825SYoshihiro YUNOMAE {
91108fc825SYoshihiro YUNOMAE ssize_t rlen;
92108fc825SYoshihiro YUNOMAE char buf[HOST_MSG_SIZE];
93108fc825SYoshihiro YUNOMAE int ret;
94108fc825SYoshihiro YUNOMAE
95108fc825SYoshihiro YUNOMAE /* Setup signal handlers */
96108fc825SYoshihiro YUNOMAE signal(SIGTERM, signal_handler);
97108fc825SYoshihiro YUNOMAE signal(SIGINT, signal_handler);
98108fc825SYoshihiro YUNOMAE signal(SIGQUIT, signal_handler);
99108fc825SYoshihiro YUNOMAE
100108fc825SYoshihiro YUNOMAE while (!global_sig_receive) {
101108fc825SYoshihiro YUNOMAE
102108fc825SYoshihiro YUNOMAE ret = wait_order(ctl_fd);
103108fc825SYoshihiro YUNOMAE if (ret < 0)
104108fc825SYoshihiro YUNOMAE break;
105108fc825SYoshihiro YUNOMAE
106108fc825SYoshihiro YUNOMAE rlen = read(ctl_fd, buf, sizeof(buf));
107108fc825SYoshihiro YUNOMAE if (rlen < 0) {
108108fc825SYoshihiro YUNOMAE pr_err("read data error in ctl thread\n");
109108fc825SYoshihiro YUNOMAE goto error;
110108fc825SYoshihiro YUNOMAE }
111108fc825SYoshihiro YUNOMAE
112108fc825SYoshihiro YUNOMAE if (rlen == 2 && buf[0] == '1') {
113108fc825SYoshihiro YUNOMAE /*
114108fc825SYoshihiro YUNOMAE * If host writes '1' to a control path,
115108fc825SYoshihiro YUNOMAE * this controller wakes all read/write threads.
116108fc825SYoshihiro YUNOMAE */
117108fc825SYoshihiro YUNOMAE global_run_operation = true;
118108fc825SYoshihiro YUNOMAE pthread_cond_broadcast(&cond_wakeup);
119108fc825SYoshihiro YUNOMAE pr_debug("Wake up all read/write threads\n");
120108fc825SYoshihiro YUNOMAE } else if (rlen == 2 && buf[0] == '0') {
121108fc825SYoshihiro YUNOMAE /*
122108fc825SYoshihiro YUNOMAE * If host writes '0' to a control path, read/write
123108fc825SYoshihiro YUNOMAE * threads will wait for notification from Host.
124108fc825SYoshihiro YUNOMAE */
125108fc825SYoshihiro YUNOMAE global_run_operation = false;
126108fc825SYoshihiro YUNOMAE pr_debug("Stop all read/write threads\n");
127108fc825SYoshihiro YUNOMAE } else
128108fc825SYoshihiro YUNOMAE pr_info("Invalid host notification: %s\n", buf);
129108fc825SYoshihiro YUNOMAE }
130108fc825SYoshihiro YUNOMAE
131108fc825SYoshihiro YUNOMAE return NULL;
132108fc825SYoshihiro YUNOMAE
133108fc825SYoshihiro YUNOMAE error:
134108fc825SYoshihiro YUNOMAE exit(EXIT_FAILURE);
135108fc825SYoshihiro YUNOMAE }
136