Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/virtio/virtio-trace/trace-agent-ctl.c
26282 views
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 <[email protected]>
7
* Masami Hiramatsu <[email protected]>
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
}
136
137