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