2 * Read/write thread of a guest agent for virtio-trace
4 * Copyright (C) 2012 Hitachi, Ltd.
5 * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
6 * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
8 * Licensed under GPL version 2 only.
17 #include <sys/syscall.h>
18 #include "trace-agent.h"
20 #define READ_WAIT_USEC 100000
22 void *rw_thread_info_new(void)
24 struct rw_thread_info
*rw_ti
;
26 rw_ti
= zalloc(sizeof(struct rw_thread_info
));
28 pr_err("rw_thread_info zalloc error\n");
35 rw_ti
->read_pipe
= -1;
36 rw_ti
->write_pipe
= -1;
37 rw_ti
->pipe_size
= PIPE_INIT
;
42 void *rw_thread_init(int cpu
, const char *in_path
, const char *out_path
,
43 bool stdout_flag
, unsigned long pipe_size
,
44 struct rw_thread_info
*rw_ti
)
50 /* set read(input) fd */
51 rw_ti
->in_fd
= open(in_path
, O_RDONLY
);
52 if (rw_ti
->in_fd
== -1) {
53 pr_err("Could not open in_fd (CPU:%d)\n", cpu
);
57 /* set write(output) fd */
59 /* virtio-serial output mode */
60 rw_ti
->out_fd
= open(out_path
, O_WRONLY
);
61 if (rw_ti
->out_fd
== -1) {
62 pr_err("Could not open out_fd (CPU:%d)\n", cpu
);
67 rw_ti
->out_fd
= STDOUT_FILENO
;
69 if (pipe2(data_pipe
, O_NONBLOCK
) < 0) {
70 pr_err("Could not create pipe in rw-thread(%d)\n", cpu
);
75 * Size of pipe is 64kB in default based on fs/pipe.c.
76 * To read/write trace data speedy, pipe size is changed.
78 if (fcntl(*data_pipe
, F_SETPIPE_SZ
, pipe_size
) < 0) {
79 pr_err("Could not change pipe size in rw-thread(%d)\n", cpu
);
83 rw_ti
->read_pipe
= data_pipe
[1];
84 rw_ti
->write_pipe
= data_pipe
[0];
85 rw_ti
->pipe_size
= pipe_size
;
93 /* Bind a thread to a cpu */
94 static void bind_cpu(int cpu_num
)
99 CPU_SET(cpu_num
, &mask
);
101 /* bind my thread to cpu_num by assigning zero to the first argument */
102 if (sched_setaffinity(0, sizeof(mask
), &mask
) == -1)
103 pr_err("Could not set CPU#%d affinity\n", (int)cpu_num
);
106 static void *rw_thread_main(void *thread_info
)
110 struct rw_thread_info
*ts
= (struct rw_thread_info
*)thread_info
;
112 bind_cpu(ts
->cpu_num
);
115 /* Wait for a read order of trace data by Host OS */
116 if (!global_run_operation
) {
117 pthread_mutex_lock(&mutex_notify
);
118 pthread_cond_wait(&cond_wakeup
, &mutex_notify
);
119 pthread_mutex_unlock(&mutex_notify
);
122 if (global_sig_receive
)
126 * Each thread read trace_pipe_raw of each cpu bounding the
127 * thread, so contention of multi-threads does not occur.
129 rlen
= splice(ts
->in_fd
, NULL
, ts
->read_pipe
, NULL
,
130 ts
->pipe_size
, SPLICE_F_MOVE
| SPLICE_F_MORE
);
133 pr_err("Splice_read in rw-thread(%d)\n", ts
->cpu_num
);
135 } else if (rlen
== 0) {
137 * If trace data do not exist or are unreadable not
138 * for exceeding the page size, splice_read returns
139 * NULL. Then, this waits for being filled the data in a
142 usleep(READ_WAIT_USEC
);
143 pr_debug("Read retry(cpu:%d)\n", ts
->cpu_num
);
150 ret
= splice(ts
->write_pipe
, NULL
, ts
->out_fd
, NULL
,
152 SPLICE_F_MOVE
| SPLICE_F_MORE
);
155 pr_err("Splice_write in rw-thread(%d)\n",
160 * When host reader is not in time for reading
161 * trace data, guest will be stopped. This is
162 * because char dev in QEMU is not supported
163 * non-blocking mode. Then, writer might be
164 * sleep in that case.
165 * This sleep will be removed by supporting
170 } while (wlen
< rlen
);
180 pthread_t
rw_thread_run(struct rw_thread_info
*rw_ti
)
183 pthread_t rw_thread_per_cpu
;
185 ret
= pthread_create(&rw_thread_per_cpu
, NULL
, rw_thread_main
, rw_ti
);
187 pr_err("Could not create a rw thread(%d)\n", rw_ti
->cpu_num
);
191 return rw_thread_per_cpu
;