]> git.proxmox.com Git - mirror_qemu.git/blame - io/channel.c
tcg: Add a new line after incompatibility warning
[mirror_qemu.git] / io / channel.c
CommitLineData
666a3af9
DB
1/*
2 * QEMU I/O channels
3 *
4 * Copyright (c) 2015 Red Hat, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
cae9fc56 21#include "qemu/osdep.h"
666a3af9 22#include "io/channel.h"
da34e65c 23#include "qapi/error.h"
c4c497d2 24#include "qemu/main-loop.h"
666a3af9
DB
25
26bool qio_channel_has_feature(QIOChannel *ioc,
27 QIOChannelFeature feature)
28{
29 return ioc->features & (1 << feature);
30}
31
32
d8d3c7cc
FF
33void qio_channel_set_feature(QIOChannel *ioc,
34 QIOChannelFeature feature)
35{
36 ioc->features |= (1 << feature);
37}
38
39
20f4aa26
DB
40void qio_channel_set_name(QIOChannel *ioc,
41 const char *name)
42{
43 g_free(ioc->name);
44 ioc->name = g_strdup(name);
45}
46
47
666a3af9
DB
48ssize_t qio_channel_readv_full(QIOChannel *ioc,
49 const struct iovec *iov,
50 size_t niov,
51 int **fds,
52 size_t *nfds,
53 Error **errp)
54{
55 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
56
57 if ((fds || nfds) &&
e413ae0c 58 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
666a3af9
DB
59 error_setg_errno(errp, EINVAL,
60 "Channel does not support file descriptor passing");
61 return -1;
62 }
63
64 return klass->io_readv(ioc, iov, niov, fds, nfds, errp);
65}
66
67
68ssize_t qio_channel_writev_full(QIOChannel *ioc,
69 const struct iovec *iov,
70 size_t niov,
71 int *fds,
72 size_t nfds,
73 Error **errp)
74{
75 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
76
77 if ((fds || nfds) &&
e413ae0c 78 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
666a3af9
DB
79 error_setg_errno(errp, EINVAL,
80 "Channel does not support file descriptor passing");
81 return -1;
82 }
83
84 return klass->io_writev(ioc, iov, niov, fds, nfds, errp);
85}
86
87
88ssize_t qio_channel_readv(QIOChannel *ioc,
89 const struct iovec *iov,
90 size_t niov,
91 Error **errp)
92{
93 return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, errp);
94}
95
96
97ssize_t qio_channel_writev(QIOChannel *ioc,
98 const struct iovec *iov,
99 size_t niov,
100 Error **errp)
101{
102 return qio_channel_writev_full(ioc, iov, niov, NULL, 0, errp);
103}
104
105
106ssize_t qio_channel_read(QIOChannel *ioc,
107 char *buf,
108 size_t buflen,
109 Error **errp)
110{
111 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
112 return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, errp);
113}
114
115
116ssize_t qio_channel_write(QIOChannel *ioc,
117 const char *buf,
118 size_t buflen,
119 Error **errp)
120{
121 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
122 return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, errp);
123}
124
125
126int qio_channel_set_blocking(QIOChannel *ioc,
127 bool enabled,
128 Error **errp)
129{
130 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
131 return klass->io_set_blocking(ioc, enabled, errp);
132}
133
134
135int qio_channel_close(QIOChannel *ioc,
136 Error **errp)
137{
138 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
139 return klass->io_close(ioc, errp);
140}
141
142
143GSource *qio_channel_create_watch(QIOChannel *ioc,
144 GIOCondition condition)
145{
146 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
20f4aa26
DB
147 GSource *ret = klass->io_create_watch(ioc, condition);
148
149 if (ioc->name) {
150 g_source_set_name(ret, ioc->name);
151 }
152
153 return ret;
666a3af9
DB
154}
155
156
bf88c124
PB
157void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
158 AioContext *ctx,
159 IOHandler *io_read,
160 IOHandler *io_write,
161 void *opaque)
162{
163 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
164
165 klass->io_set_aio_fd_handler(ioc, ctx, io_read, io_write, opaque);
166}
167
666a3af9
DB
168guint qio_channel_add_watch(QIOChannel *ioc,
169 GIOCondition condition,
170 QIOChannelFunc func,
171 gpointer user_data,
172 GDestroyNotify notify)
173{
174 GSource *source;
175 guint id;
176
177 source = qio_channel_create_watch(ioc, condition);
178
179 g_source_set_callback(source, (GSourceFunc)func, user_data, notify);
180
181 id = g_source_attach(source, NULL);
182 g_source_unref(source);
183
184 return id;
185}
186
187
188int qio_channel_shutdown(QIOChannel *ioc,
189 QIOChannelShutdown how,
190 Error **errp)
191{
192 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
193
194 if (!klass->io_shutdown) {
195 error_setg(errp, "Data path shutdown not supported");
196 return -1;
197 }
198
199 return klass->io_shutdown(ioc, how, errp);
200}
201
202
203void qio_channel_set_delay(QIOChannel *ioc,
204 bool enabled)
205{
206 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
207
208 if (klass->io_set_delay) {
209 klass->io_set_delay(ioc, enabled);
210 }
211}
212
213
214void qio_channel_set_cork(QIOChannel *ioc,
215 bool enabled)
216{
217 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
218
219 if (klass->io_set_cork) {
220 klass->io_set_cork(ioc, enabled);
221 }
222}
223
224
225off_t qio_channel_io_seek(QIOChannel *ioc,
226 off_t offset,
227 int whence,
228 Error **errp)
229{
230 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
231
232 if (!klass->io_seek) {
233 error_setg(errp, "Channel does not support random access");
234 return -1;
235 }
236
237 return klass->io_seek(ioc, offset, whence, errp);
238}
239
240
c4c497d2 241static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc);
666a3af9 242
c4c497d2
PB
243static void qio_channel_restart_read(void *opaque)
244{
245 QIOChannel *ioc = opaque;
246 Coroutine *co = ioc->read_coroutine;
247
248 ioc->read_coroutine = NULL;
249 qio_channel_set_aio_fd_handlers(ioc);
250 aio_co_wake(co);
251}
666a3af9 252
c4c497d2 253static void qio_channel_restart_write(void *opaque)
666a3af9 254{
c4c497d2
PB
255 QIOChannel *ioc = opaque;
256 Coroutine *co = ioc->write_coroutine;
257
258 ioc->write_coroutine = NULL;
259 qio_channel_set_aio_fd_handlers(ioc);
260 aio_co_wake(co);
666a3af9
DB
261}
262
c4c497d2
PB
263static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc)
264{
265 IOHandler *rd_handler = NULL, *wr_handler = NULL;
266 AioContext *ctx;
267
268 if (ioc->read_coroutine) {
269 rd_handler = qio_channel_restart_read;
270 }
271 if (ioc->write_coroutine) {
272 wr_handler = qio_channel_restart_write;
273 }
274
275 ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
276 qio_channel_set_aio_fd_handler(ioc, ctx, rd_handler, wr_handler, ioc);
277}
278
279void qio_channel_attach_aio_context(QIOChannel *ioc,
280 AioContext *ctx)
281{
282 AioContext *old_ctx;
283 if (ioc->ctx == ctx) {
284 return;
285 }
286
287 old_ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
288 qio_channel_set_aio_fd_handler(ioc, old_ctx, NULL, NULL, NULL);
289 ioc->ctx = ctx;
290 qio_channel_set_aio_fd_handlers(ioc);
291}
292
293void qio_channel_detach_aio_context(QIOChannel *ioc)
294{
295 ioc->read_coroutine = NULL;
296 ioc->write_coroutine = NULL;
297 qio_channel_set_aio_fd_handlers(ioc);
298 ioc->ctx = NULL;
299}
666a3af9
DB
300
301void coroutine_fn qio_channel_yield(QIOChannel *ioc,
302 GIOCondition condition)
303{
666a3af9 304 assert(qemu_in_coroutine());
c4c497d2
PB
305 if (condition == G_IO_IN) {
306 assert(!ioc->read_coroutine);
307 ioc->read_coroutine = qemu_coroutine_self();
308 } else if (condition == G_IO_OUT) {
309 assert(!ioc->write_coroutine);
310 ioc->write_coroutine = qemu_coroutine_self();
311 } else {
312 abort();
313 }
314 qio_channel_set_aio_fd_handlers(ioc);
666a3af9
DB
315 qemu_coroutine_yield();
316}
317
318
319static gboolean qio_channel_wait_complete(QIOChannel *ioc,
320 GIOCondition condition,
321 gpointer opaque)
322{
323 GMainLoop *loop = opaque;
324
325 g_main_loop_quit(loop);
326 return FALSE;
327}
328
329
330void qio_channel_wait(QIOChannel *ioc,
331 GIOCondition condition)
332{
333 GMainContext *ctxt = g_main_context_new();
334 GMainLoop *loop = g_main_loop_new(ctxt, TRUE);
335 GSource *source;
336
337 source = qio_channel_create_watch(ioc, condition);
338
339 g_source_set_callback(source,
340 (GSourceFunc)qio_channel_wait_complete,
341 loop,
342 NULL);
343
344 g_source_attach(source, ctxt);
345
346 g_main_loop_run(loop);
347
348 g_source_unref(source);
349 g_main_loop_unref(loop);
350 g_main_context_unref(ctxt);
351}
352
353
a5897205
PB
354static void qio_channel_finalize(Object *obj)
355{
356 QIOChannel *ioc = QIO_CHANNEL(obj);
357
20f4aa26
DB
358 g_free(ioc->name);
359
360#ifdef _WIN32
a5897205
PB
361 if (ioc->event) {
362 CloseHandle(ioc->event);
363 }
a5897205 364#endif
20f4aa26 365}
a5897205 366
666a3af9
DB
367static const TypeInfo qio_channel_info = {
368 .parent = TYPE_OBJECT,
369 .name = TYPE_QIO_CHANNEL,
370 .instance_size = sizeof(QIOChannel),
a5897205 371 .instance_finalize = qio_channel_finalize,
666a3af9
DB
372 .abstract = true,
373 .class_size = sizeof(QIOChannelClass),
374};
375
376
377static void qio_channel_register_types(void)
378{
379 type_register_static(&qio_channel_info);
380}
381
382
383type_init(qio_channel_register_types);