blob: 0640941ac573b558fdc5a737f117f940b542915e [file] [log] [blame]
Daniel P. Berrange666a3af2015-02-27 16:19:33 +00001/*
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
Chetan Pantc8198bd2020-10-14 13:40:33 +00009 * version 2.1 of the License, or (at your option) any later version.
Daniel P. Berrange666a3af2015-02-27 16:19:33 +000010 *
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
Peter Maydellcae9fc52016-01-29 17:50:03 +000021#include "qemu/osdep.h"
Daniel P. Berrange666a3af2015-02-27 16:19:33 +000022#include "io/channel.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010023#include "qapi/error.h"
Paolo Bonzinic4c497d2017-02-13 14:52:23 +010024#include "qemu/main-loop.h"
Markus Armbruster0b8fa322019-05-23 16:35:07 +020025#include "qemu/module.h"
Daniel P. Berranged4622e52017-08-30 14:53:59 +010026#include "qemu/iov.h"
Daniel P. Berrange666a3af2015-02-27 16:19:33 +000027
28bool qio_channel_has_feature(QIOChannel *ioc,
29 QIOChannelFeature feature)
30{
31 return ioc->features & (1 << feature);
32}
33
34
Felipe Franciosid8d3c7c2016-09-29 08:52:37 -070035void qio_channel_set_feature(QIOChannel *ioc,
36 QIOChannelFeature feature)
37{
38 ioc->features |= (1 << feature);
39}
40
41
Daniel P. Berrange20f4aa22016-09-30 11:50:18 +010042void qio_channel_set_name(QIOChannel *ioc,
43 const char *name)
44{
45 g_free(ioc->name);
46 ioc->name = g_strdup(name);
47}
48
49
Daniel P. Berrange666a3af2015-02-27 16:19:33 +000050ssize_t qio_channel_readv_full(QIOChannel *ioc,
51 const struct iovec *iov,
52 size_t niov,
53 int **fds,
54 size_t *nfds,
55 Error **errp)
56{
57 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
58
59 if ((fds || nfds) &&
Felipe Franciosie413ae02016-09-29 08:52:36 -070060 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
Daniel P. Berrange666a3af2015-02-27 16:19:33 +000061 error_setg_errno(errp, EINVAL,
62 "Channel does not support file descriptor passing");
63 return -1;
64 }
65
66 return klass->io_readv(ioc, iov, niov, fds, nfds, errp);
67}
68
69
70ssize_t qio_channel_writev_full(QIOChannel *ioc,
71 const struct iovec *iov,
72 size_t niov,
73 int *fds,
74 size_t nfds,
Leonardo Brasb88651c2022-05-13 03:28:31 -030075 int flags,
Daniel P. Berrange666a3af2015-02-27 16:19:33 +000076 Error **errp)
77{
78 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
79
Leonardo Brasb88651c2022-05-13 03:28:31 -030080 if (fds || nfds) {
81 if (!qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
82 error_setg_errno(errp, EINVAL,
83 "Channel does not support file descriptor passing");
84 return -1;
85 }
86 if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) {
87 error_setg_errno(errp, EINVAL,
88 "Zero Copy does not support file descriptor passing");
89 return -1;
90 }
91 }
92
93 if ((flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) &&
94 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
Daniel P. Berrange666a3af2015-02-27 16:19:33 +000095 error_setg_errno(errp, EINVAL,
Leonardo Brasb88651c2022-05-13 03:28:31 -030096 "Requested Zero Copy feature is not available");
Daniel P. Berrange666a3af2015-02-27 16:19:33 +000097 return -1;
98 }
99
Leonardo Brasb88651c2022-05-13 03:28:31 -0300100 return klass->io_writev(ioc, iov, niov, fds, nfds, flags, errp);
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000101}
102
103
Eric Blakee8ffaa32017-09-05 14:11:13 -0500104int qio_channel_readv_all_eof(QIOChannel *ioc,
105 const struct iovec *iov,
106 size_t niov,
107 Error **errp)
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100108{
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500109 return qio_channel_readv_full_all_eof(ioc, iov, niov, NULL, NULL, errp);
110}
111
112int qio_channel_readv_all(QIOChannel *ioc,
113 const struct iovec *iov,
114 size_t niov,
115 Error **errp)
116{
117 return qio_channel_readv_full_all(ioc, iov, niov, NULL, NULL, errp);
118}
119
120int qio_channel_readv_full_all_eof(QIOChannel *ioc,
121 const struct iovec *iov,
122 size_t niov,
123 int **fds, size_t *nfds,
124 Error **errp)
125{
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100126 int ret = -1;
127 struct iovec *local_iov = g_new(struct iovec, niov);
128 struct iovec *local_iov_head = local_iov;
129 unsigned int nlocal_iov = niov;
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500130 int **local_fds = fds;
131 size_t *local_nfds = nfds;
Eric Blakee8ffaa32017-09-05 14:11:13 -0500132 bool partial = false;
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100133
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500134 if (nfds) {
135 *nfds = 0;
136 }
137
138 if (fds) {
139 *fds = NULL;
140 }
141
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100142 nlocal_iov = iov_copy(local_iov, nlocal_iov,
143 iov, niov,
144 0, iov_size(iov, niov));
145
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500146 while ((nlocal_iov > 0) || local_fds) {
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100147 ssize_t len;
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500148 len = qio_channel_readv_full(ioc, local_iov, nlocal_iov, local_fds,
149 local_nfds, errp);
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100150 if (len == QIO_CHANNEL_ERR_BLOCK) {
Eric Blake9ffb8272017-09-05 14:11:12 -0500151 if (qemu_in_coroutine()) {
152 qio_channel_yield(ioc, G_IO_IN);
153 } else {
154 qio_channel_wait(ioc, G_IO_IN);
155 }
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100156 continue;
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500157 }
158
159 if (len == 0) {
160 if (local_nfds && *local_nfds) {
161 /*
162 * Got some FDs, but no data yet. This isn't an EOF
163 * scenario (yet), so carry on to try to read data
164 * on next loop iteration
165 */
166 goto next_iter;
167 } else if (!partial) {
168 /* No fds and no data - EOF before any data read */
Eric Blakee8ffaa32017-09-05 14:11:13 -0500169 ret = 0;
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500170 goto cleanup;
171 } else {
172 len = -1;
173 error_setg(errp,
174 "Unexpected end-of-file before all data were read");
175 /* Fallthrough into len < 0 handling */
176 }
177 }
178
179 if (len < 0) {
180 /* Close any FDs we previously received */
181 if (nfds && fds) {
182 size_t i;
183 for (i = 0; i < (*nfds); i++) {
184 close((*fds)[i]);
185 }
186 g_free(*fds);
187 *fds = NULL;
188 *nfds = 0;
Eric Blakee8ffaa32017-09-05 14:11:13 -0500189 }
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100190 goto cleanup;
191 }
192
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500193 if (nlocal_iov) {
194 iov_discard_front(&local_iov, &nlocal_iov, len);
195 }
196
197next_iter:
Eric Blakee8ffaa32017-09-05 14:11:13 -0500198 partial = true;
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500199 local_fds = NULL;
200 local_nfds = NULL;
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100201 }
202
Eric Blakee8ffaa32017-09-05 14:11:13 -0500203 ret = 1;
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100204
205 cleanup:
206 g_free(local_iov_head);
207 return ret;
208}
209
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500210int qio_channel_readv_full_all(QIOChannel *ioc,
211 const struct iovec *iov,
212 size_t niov,
213 int **fds, size_t *nfds,
214 Error **errp)
Eric Blakee8ffaa32017-09-05 14:11:13 -0500215{
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500216 int ret = qio_channel_readv_full_all_eof(ioc, iov, niov, fds, nfds, errp);
Eric Blakee8ffaa32017-09-05 14:11:13 -0500217
218 if (ret == 0) {
Jagannathan Ramanc90e3512021-02-12 06:16:07 -0500219 error_setg(errp, "Unexpected end-of-file before all data were read");
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500220 return -1;
Eric Blakee8ffaa32017-09-05 14:11:13 -0500221 }
Elena Ufimtsevabebab912021-01-29 11:46:09 -0500222 if (ret == 1) {
223 return 0;
224 }
225
Eric Blakee8ffaa32017-09-05 14:11:13 -0500226 return ret;
227}
228
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100229int qio_channel_writev_all(QIOChannel *ioc,
230 const struct iovec *iov,
231 size_t niov,
232 Error **errp)
233{
Leonardo Brasb88651c2022-05-13 03:28:31 -0300234 return qio_channel_writev_full_all(ioc, iov, niov, NULL, 0, 0, errp);
Elena Ufimtsevabfa42382021-01-29 11:46:08 -0500235}
236
237int qio_channel_writev_full_all(QIOChannel *ioc,
238 const struct iovec *iov,
239 size_t niov,
240 int *fds, size_t nfds,
Leonardo Brasb88651c2022-05-13 03:28:31 -0300241 int flags, Error **errp)
Elena Ufimtsevabfa42382021-01-29 11:46:08 -0500242{
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100243 int ret = -1;
244 struct iovec *local_iov = g_new(struct iovec, niov);
245 struct iovec *local_iov_head = local_iov;
246 unsigned int nlocal_iov = niov;
247
248 nlocal_iov = iov_copy(local_iov, nlocal_iov,
249 iov, niov,
250 0, iov_size(iov, niov));
251
252 while (nlocal_iov > 0) {
253 ssize_t len;
Leonardo Brasb88651c2022-05-13 03:28:31 -0300254
255 len = qio_channel_writev_full(ioc, local_iov, nlocal_iov, fds,
256 nfds, flags, errp);
257
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100258 if (len == QIO_CHANNEL_ERR_BLOCK) {
Eric Blake9ffb8272017-09-05 14:11:12 -0500259 if (qemu_in_coroutine()) {
260 qio_channel_yield(ioc, G_IO_OUT);
261 } else {
262 qio_channel_wait(ioc, G_IO_OUT);
263 }
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100264 continue;
265 }
266 if (len < 0) {
267 goto cleanup;
268 }
269
270 iov_discard_front(&local_iov, &nlocal_iov, len);
Elena Ufimtsevabfa42382021-01-29 11:46:08 -0500271
272 fds = NULL;
273 nfds = 0;
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100274 }
275
276 ret = 0;
277 cleanup:
278 g_free(local_iov_head);
279 return ret;
280}
281
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000282ssize_t qio_channel_readv(QIOChannel *ioc,
283 const struct iovec *iov,
284 size_t niov,
285 Error **errp)
286{
287 return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, errp);
288}
289
290
291ssize_t qio_channel_writev(QIOChannel *ioc,
292 const struct iovec *iov,
293 size_t niov,
294 Error **errp)
295{
Leonardo Brasb88651c2022-05-13 03:28:31 -0300296 return qio_channel_writev_full(ioc, iov, niov, NULL, 0, 0, errp);
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000297}
298
299
300ssize_t qio_channel_read(QIOChannel *ioc,
301 char *buf,
302 size_t buflen,
303 Error **errp)
304{
305 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
306 return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, errp);
307}
308
309
310ssize_t qio_channel_write(QIOChannel *ioc,
311 const char *buf,
312 size_t buflen,
313 Error **errp)
314{
315 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
Leonardo Brasb88651c2022-05-13 03:28:31 -0300316 return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, 0, errp);
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000317}
318
319
Eric Blakee8ffaa32017-09-05 14:11:13 -0500320int qio_channel_read_all_eof(QIOChannel *ioc,
321 char *buf,
322 size_t buflen,
323 Error **errp)
324{
325 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
326 return qio_channel_readv_all_eof(ioc, &iov, 1, errp);
327}
328
329
Daniel P. Berranged4622e52017-08-30 14:53:59 +0100330int qio_channel_read_all(QIOChannel *ioc,
331 char *buf,
332 size_t buflen,
333 Error **errp)
334{
335 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
336 return qio_channel_readv_all(ioc, &iov, 1, errp);
337}
338
339
340int qio_channel_write_all(QIOChannel *ioc,
341 const char *buf,
342 size_t buflen,
343 Error **errp)
344{
345 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
346 return qio_channel_writev_all(ioc, &iov, 1, errp);
347}
348
349
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000350int qio_channel_set_blocking(QIOChannel *ioc,
351 bool enabled,
352 Error **errp)
353{
354 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
355 return klass->io_set_blocking(ioc, enabled, errp);
356}
357
358
359int qio_channel_close(QIOChannel *ioc,
360 Error **errp)
361{
362 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
363 return klass->io_close(ioc, errp);
364}
365
366
367GSource *qio_channel_create_watch(QIOChannel *ioc,
368 GIOCondition condition)
369{
370 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
Daniel P. Berrange20f4aa22016-09-30 11:50:18 +0100371 GSource *ret = klass->io_create_watch(ioc, condition);
372
373 if (ioc->name) {
374 g_source_set_name(ret, ioc->name);
375 }
376
377 return ret;
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000378}
379
380
Paolo Bonzinibf88c122017-02-13 14:52:22 +0100381void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
382 AioContext *ctx,
383 IOHandler *io_read,
384 IOHandler *io_write,
385 void *opaque)
386{
387 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
388
389 klass->io_set_aio_fd_handler(ioc, ctx, io_read, io_write, opaque);
390}
391
Peter Xu315409c2018-03-05 14:43:20 +0800392guint qio_channel_add_watch_full(QIOChannel *ioc,
393 GIOCondition condition,
394 QIOChannelFunc func,
395 gpointer user_data,
396 GDestroyNotify notify,
397 GMainContext *context)
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000398{
399 GSource *source;
400 guint id;
401
402 source = qio_channel_create_watch(ioc, condition);
403
404 g_source_set_callback(source, (GSourceFunc)func, user_data, notify);
405
Peter Xu315409c2018-03-05 14:43:20 +0800406 id = g_source_attach(source, context);
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000407 g_source_unref(source);
408
409 return id;
410}
411
Peter Xu315409c2018-03-05 14:43:20 +0800412guint qio_channel_add_watch(QIOChannel *ioc,
413 GIOCondition condition,
414 QIOChannelFunc func,
415 gpointer user_data,
416 GDestroyNotify notify)
417{
418 return qio_channel_add_watch_full(ioc, condition, func,
419 user_data, notify, NULL);
420}
421
422GSource *qio_channel_add_watch_source(QIOChannel *ioc,
423 GIOCondition condition,
424 QIOChannelFunc func,
425 gpointer user_data,
426 GDestroyNotify notify,
427 GMainContext *context)
428{
429 GSource *source;
430 guint id;
431
432 id = qio_channel_add_watch_full(ioc, condition, func,
433 user_data, notify, context);
434 source = g_main_context_find_source_by_id(context, id);
435 g_source_ref(source);
436 return source;
437}
438
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000439
440int qio_channel_shutdown(QIOChannel *ioc,
441 QIOChannelShutdown how,
442 Error **errp)
443{
444 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
445
446 if (!klass->io_shutdown) {
447 error_setg(errp, "Data path shutdown not supported");
448 return -1;
449 }
450
451 return klass->io_shutdown(ioc, how, errp);
452}
453
454
455void qio_channel_set_delay(QIOChannel *ioc,
456 bool enabled)
457{
458 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
459
460 if (klass->io_set_delay) {
461 klass->io_set_delay(ioc, enabled);
462 }
463}
464
465
466void qio_channel_set_cork(QIOChannel *ioc,
467 bool enabled)
468{
469 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
470
471 if (klass->io_set_cork) {
472 klass->io_set_cork(ioc, enabled);
473 }
474}
475
476
477off_t qio_channel_io_seek(QIOChannel *ioc,
478 off_t offset,
479 int whence,
480 Error **errp)
481{
482 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
483
484 if (!klass->io_seek) {
485 error_setg(errp, "Channel does not support random access");
486 return -1;
487 }
488
489 return klass->io_seek(ioc, offset, whence, errp);
490}
491
Leonardo Brasb88651c2022-05-13 03:28:31 -0300492int qio_channel_flush(QIOChannel *ioc,
493 Error **errp)
494{
495 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
496
497 if (!klass->io_flush ||
498 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
499 return 0;
500 }
501
502 return klass->io_flush(ioc, errp);
503}
504
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000505
Paolo Bonzinic4c497d2017-02-13 14:52:23 +0100506static void qio_channel_restart_read(void *opaque)
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000507{
Paolo Bonzinic4c497d2017-02-13 14:52:23 +0100508 QIOChannel *ioc = opaque;
509 Coroutine *co = ioc->read_coroutine;
510
Kevin Wolf2a239e62019-02-20 18:00:07 +0100511 /* Assert that aio_co_wake() reenters the coroutine directly */
512 assert(qemu_get_current_aio_context() ==
513 qemu_coroutine_get_aio_context(co));
Paolo Bonzinic4c497d2017-02-13 14:52:23 +0100514 aio_co_wake(co);
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000515}
516
Paolo Bonzinic4c497d2017-02-13 14:52:23 +0100517static void qio_channel_restart_write(void *opaque)
518{
519 QIOChannel *ioc = opaque;
520 Coroutine *co = ioc->write_coroutine;
521
Kevin Wolf2a239e62019-02-20 18:00:07 +0100522 /* Assert that aio_co_wake() reenters the coroutine directly */
523 assert(qemu_get_current_aio_context() ==
524 qemu_coroutine_get_aio_context(co));
Paolo Bonzinic4c497d2017-02-13 14:52:23 +0100525 aio_co_wake(co);
526}
527
528static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc)
529{
530 IOHandler *rd_handler = NULL, *wr_handler = NULL;
531 AioContext *ctx;
532
533 if (ioc->read_coroutine) {
534 rd_handler = qio_channel_restart_read;
535 }
536 if (ioc->write_coroutine) {
537 wr_handler = qio_channel_restart_write;
538 }
539
540 ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
541 qio_channel_set_aio_fd_handler(ioc, ctx, rd_handler, wr_handler, ioc);
542}
543
544void qio_channel_attach_aio_context(QIOChannel *ioc,
545 AioContext *ctx)
546{
Paolo Bonzini8f7168b2017-05-26 11:36:41 +0200547 assert(!ioc->read_coroutine);
548 assert(!ioc->write_coroutine);
Paolo Bonzinic4c497d2017-02-13 14:52:23 +0100549 ioc->ctx = ctx;
Paolo Bonzinic4c497d2017-02-13 14:52:23 +0100550}
551
552void qio_channel_detach_aio_context(QIOChannel *ioc)
553{
554 ioc->read_coroutine = NULL;
555 ioc->write_coroutine = NULL;
556 qio_channel_set_aio_fd_handlers(ioc);
557 ioc->ctx = NULL;
558}
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000559
560void coroutine_fn qio_channel_yield(QIOChannel *ioc,
561 GIOCondition condition)
562{
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000563 assert(qemu_in_coroutine());
Paolo Bonzinic4c497d2017-02-13 14:52:23 +0100564 if (condition == G_IO_IN) {
565 assert(!ioc->read_coroutine);
566 ioc->read_coroutine = qemu_coroutine_self();
567 } else if (condition == G_IO_OUT) {
568 assert(!ioc->write_coroutine);
569 ioc->write_coroutine = qemu_coroutine_self();
570 } else {
571 abort();
572 }
573 qio_channel_set_aio_fd_handlers(ioc);
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000574 qemu_coroutine_yield();
Kevin Wolf6886cea2019-02-18 14:09:32 +0100575
576 /* Allow interrupting the operation by reentering the coroutine other than
577 * through the aio_fd_handlers. */
578 if (condition == G_IO_IN && ioc->read_coroutine) {
579 ioc->read_coroutine = NULL;
580 qio_channel_set_aio_fd_handlers(ioc);
581 } else if (condition == G_IO_OUT && ioc->write_coroutine) {
582 ioc->write_coroutine = NULL;
583 qio_channel_set_aio_fd_handlers(ioc);
584 }
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000585}
586
587
588static gboolean qio_channel_wait_complete(QIOChannel *ioc,
589 GIOCondition condition,
590 gpointer opaque)
591{
592 GMainLoop *loop = opaque;
593
594 g_main_loop_quit(loop);
595 return FALSE;
596}
597
598
599void qio_channel_wait(QIOChannel *ioc,
600 GIOCondition condition)
601{
602 GMainContext *ctxt = g_main_context_new();
603 GMainLoop *loop = g_main_loop_new(ctxt, TRUE);
604 GSource *source;
605
606 source = qio_channel_create_watch(ioc, condition);
607
608 g_source_set_callback(source,
609 (GSourceFunc)qio_channel_wait_complete,
610 loop,
611 NULL);
612
613 g_source_attach(source, ctxt);
614
615 g_main_loop_run(loop);
616
617 g_source_unref(source);
618 g_main_loop_unref(loop);
619 g_main_context_unref(ctxt);
620}
621
622
Paolo Bonzinia5897202016-03-07 12:12:36 +0100623static void qio_channel_finalize(Object *obj)
624{
625 QIOChannel *ioc = QIO_CHANNEL(obj);
626
Daniel P. Berrange20f4aa22016-09-30 11:50:18 +0100627 g_free(ioc->name);
628
629#ifdef _WIN32
Paolo Bonzinia5897202016-03-07 12:12:36 +0100630 if (ioc->event) {
631 CloseHandle(ioc->event);
632 }
Paolo Bonzinia5897202016-03-07 12:12:36 +0100633#endif
Daniel P. Berrange20f4aa22016-09-30 11:50:18 +0100634}
Paolo Bonzinia5897202016-03-07 12:12:36 +0100635
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000636static const TypeInfo qio_channel_info = {
637 .parent = TYPE_OBJECT,
638 .name = TYPE_QIO_CHANNEL,
639 .instance_size = sizeof(QIOChannel),
Paolo Bonzinia5897202016-03-07 12:12:36 +0100640 .instance_finalize = qio_channel_finalize,
Daniel P. Berrange666a3af2015-02-27 16:19:33 +0000641 .abstract = true,
642 .class_size = sizeof(QIOChannelClass),
643};
644
645
646static void qio_channel_register_types(void)
647{
648 type_register_static(&qio_channel_info);
649}
650
651
652type_init(qio_channel_register_types);