1 // SPDX-License-Identifier: GPL-2.0-only
3 * Read/write thread of a guest agent for virtio-trace
5 * Copyright (C) 2012 Hitachi, Ltd.
6 * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
7 * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
15 #include <sys/syscall.h>
16 #include "trace-agent.h"
18 #define READ_WAIT_USEC 100000
20 void *rw_thread_info_new(void)
22 struct rw_thread_info
*rw_ti
;
24 rw_ti
= zalloc(sizeof(struct rw_thread_info
));
26 pr_err("rw_thread_info zalloc error\n");
33 rw_ti
->read_pipe
= -1;
34 rw_ti
->write_pipe
= -1;
35 rw_ti
->pipe_size
= PIPE_INIT
;
40 void *rw_thread_init(int cpu
, const char *in_path
, const char *out_path
,
41 bool stdout_flag
, unsigned long pipe_size
,
42 struct rw_thread_info
*rw_ti
)
48 /* set read(input) fd */
49 rw_ti
->in_fd
= open(in_path
, O_RDONLY
);
50 if (rw_ti
->in_fd
== -1) {
51 pr_err("Could not open in_fd (CPU:%d)\n", cpu
);
55 /* set write(output) fd */
57 /* virtio-serial output mode */
58 rw_ti
->out_fd
= open(out_path
, O_WRONLY
);
59 if (rw_ti
->out_fd
== -1) {
60 pr_err("Could not open out_fd (CPU:%d)\n", cpu
);
65 rw_ti
->out_fd
= STDOUT_FILENO
;
67 if (pipe2(data_pipe
, O_NONBLOCK
) < 0) {
68 pr_err("Could not create pipe in rw-thread(%d)\n", cpu
);
73 * Size of pipe is 64kB in default based on fs/pipe.c.
74 * To read/write trace data speedy, pipe size is changed.
76 if (fcntl(*data_pipe
, F_SETPIPE_SZ
, pipe_size
) < 0) {
77 pr_err("Could not change pipe size in rw-thread(%d)\n", cpu
);
81 rw_ti
->read_pipe
= data_pipe
[1];
82 rw_ti
->write_pipe
= data_pipe
[0];
83 rw_ti
->pipe_size
= pipe_size
;
91 /* Bind a thread to a cpu */
92 static void bind_cpu(int cpu_num
)
97 CPU_SET(cpu_num
, &mask
);
99 /* bind my thread to cpu_num by assigning zero to the first argument */
100 if (sched_setaffinity(0, sizeof(mask
), &mask
) == -1)
101 pr_err("Could not set CPU#%d affinity\n", (int)cpu_num
);
104 static void *rw_thread_main(void *thread_info
)
108 struct rw_thread_info
*ts
= (struct rw_thread_info
*)thread_info
;
110 bind_cpu(ts
->cpu_num
);
113 /* Wait for a read order of trace data by Host OS */
114 if (!global_run_operation
) {
115 pthread_mutex_lock(&mutex_notify
);
116 pthread_cond_wait(&cond_wakeup
, &mutex_notify
);
117 pthread_mutex_unlock(&mutex_notify
);
120 if (global_sig_receive
)
124 * Each thread read trace_pipe_raw of each cpu bounding the
125 * thread, so contention of multi-threads does not occur.
127 rlen
= splice(ts
->in_fd
, NULL
, ts
->read_pipe
, NULL
,
128 ts
->pipe_size
, SPLICE_F_MOVE
| SPLICE_F_MORE
);
131 pr_err("Splice_read in rw-thread(%d)\n", ts
->cpu_num
);
133 } else if (rlen
== 0) {
135 * If trace data do not exist or are unreadable not
136 * for exceeding the page size, splice_read returns
137 * NULL. Then, this waits for being filled the data in a
140 usleep(READ_WAIT_USEC
);
141 pr_debug("Read retry(cpu:%d)\n", ts
->cpu_num
);
148 ret
= splice(ts
->write_pipe
, NULL
, ts
->out_fd
, NULL
,
150 SPLICE_F_MOVE
| SPLICE_F_MORE
);
153 pr_err("Splice_write in rw-thread(%d)\n",
158 * When host reader is not in time for reading
159 * trace data, guest will be stopped. This is
160 * because char dev in QEMU is not supported
161 * non-blocking mode. Then, writer might be
162 * sleep in that case.
163 * This sleep will be removed by supporting
168 } while (wlen
< rlen
);
178 pthread_t
rw_thread_run(struct rw_thread_info
*rw_ti
)
181 pthread_t rw_thread_per_cpu
;
183 ret
= pthread_create(&rw_thread_per_cpu
, NULL
, rw_thread_main
, rw_ti
);
185 pr_err("Could not create a rw thread(%d)\n", rw_ti
->cpu_num
);
189 return rw_thread_per_cpu
;