xref: /linux/tools/virtio/virtio-trace/trace-agent-ctl.c (revision ea68a3e9d14e9e0bf017d178fb4bd53b6deb1482)
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