master
c 952 lines 27.6 KB
Raw
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.1 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
21 #include "qemu/osdep.h"
22 #include "qemu/aio-wait.h"
23 #include "io/channel.h"
24 #include "qapi/error.h"
25 #include "qemu/main-loop.h"
26 #include "qemu/module.h"
27 #include "qemu/iov.h"
28
29 bool qio_channel_has_feature(QIOChannel *ioc,
30 QIOChannelFeature feature)
31 {
32 return ioc->features & (1 << feature);
33 }
34
35
36 void qio_channel_set_feature(QIOChannel *ioc,
37 QIOChannelFeature feature)
38 {
39 ioc->features |= (1 << feature);
40 }
41
42
43 void qio_channel_set_name(QIOChannel *ioc,
44 const char *name)
45 {
46 g_free(ioc->name);
47 ioc->name = g_strdup(name);
48 }
49
50
51 ssize_t qio_channel_readv_full(QIOChannel *ioc,
52 const struct iovec *iov,
53 size_t niov,
54 int **fds,
55 size_t *nfds,
56 int flags,
57 Error **errp)
58 {
59 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
60
61 if ((fds || nfds) &&
62 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
63 error_setg_errno(errp, EINVAL,
64 "Channel does not support file descriptor passing");
65 return -1;
66 }
67
68 if ((flags & QIO_CHANNEL_READ_FLAG_MSG_PEEK) &&
69 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_READ_MSG_PEEK)) {
70 error_setg_errno(errp, EINVAL,
71 "Channel does not support peek read");
72 return -1;
73 }
74
75 return klass->io_readv(ioc, iov, niov, fds, nfds, flags, errp);
76 }
77
78
79 ssize_t qio_channel_writev_full(QIOChannel *ioc,
80 const struct iovec *iov,
81 size_t niov,
82 int *fds,
83 size_t nfds,
84 int flags,
85 Error **errp)
86 {
87 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
88
89 if (fds || nfds) {
90 if (!qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
91 error_setg_errno(errp, EINVAL,
92 "Channel does not support file descriptor passing");
93 return -1;
94 }
95 if (flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) {
96 error_setg_errno(errp, EINVAL,
97 "Zero Copy does not support file descriptor passing");
98 return -1;
99 }
100 }
101
102 if ((flags & QIO_CHANNEL_WRITE_FLAG_ZERO_COPY) &&
103 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
104 error_setg_errno(errp, EINVAL,
105 "Requested Zero Copy feature is not available");
106 return -1;
107 }
108
109 return klass->io_writev(ioc, iov, niov, fds, nfds, flags, errp);
110 }
111
112
113 int coroutine_mixed_fn qio_channel_readv_all_eof(QIOChannel *ioc,
114 const struct iovec *iov,
115 size_t niov,
116 Error **errp)
117 {
118 return qio_channel_readv_full_all_eof(ioc, iov, niov, NULL, NULL, 0,
119 errp);
120 }
121
122 int coroutine_mixed_fn qio_channel_readv_all(QIOChannel *ioc,
123 const struct iovec *iov,
124 size_t niov,
125 Error **errp)
126 {
127 return qio_channel_readv_full_all(ioc, iov, niov, NULL, NULL, errp);
128 }
129
130 int coroutine_mixed_fn qio_channel_readv_full_all_eof(QIOChannel *ioc,
131 const struct iovec *iov,
132 size_t niov,
133 int **fds, size_t *nfds,
134 int flags,
135 Error **errp)
136 {
137 int ret = -1;
138 struct iovec *local_iov = g_new(struct iovec, niov);
139 struct iovec *local_iov_head = local_iov;
140 unsigned int nlocal_iov = niov;
141 int **local_fds = fds;
142 size_t *local_nfds = nfds;
143 bool partial = false;
144
145 if (nfds) {
146 *nfds = 0;
147 }
148
149 if (fds) {
150 *fds = NULL;
151 }
152
153 nlocal_iov = iov_copy(local_iov, nlocal_iov,
154 iov, niov,
155 0, iov_size(iov, niov));
156
157 while ((nlocal_iov > 0) || local_fds) {
158 ssize_t len;
159 len = qio_channel_readv_full(ioc, local_iov, nlocal_iov, local_fds,
160 local_nfds, flags, errp);
161 if (len == QIO_CHANNEL_ERR_BLOCK) {
162 qio_channel_wait_cond(ioc, G_IO_IN);
163 continue;
164 }
165
166 if (len == 0) {
167 if (local_nfds && *local_nfds) {
168 /*
169 * Got some FDs, but no data yet. This isn't an EOF
170 * scenario (yet), so carry on to try to read data
171 * on next loop iteration
172 */
173 goto next_iter;
174 } else if (!partial) {
175 /* No fds and no data - EOF before any data read */
176 ret = 0;
177 goto cleanup;
178 } else {
179 len = -1;
180 error_setg(errp,
181 "Unexpected end-of-file before all data were read");
182 /* Fallthrough into len < 0 handling */
183 }
184 }
185
186 if (len < 0) {
187 /* Close any FDs we previously received */
188 if (nfds && fds) {
189 size_t i;
190 for (i = 0; i < (*nfds); i++) {
191 close((*fds)[i]);
192 }
193 g_free(*fds);
194 *fds = NULL;
195 *nfds = 0;
196 }
197 goto cleanup;
198 }
199
200 if (nlocal_iov) {
201 iov_discard_front(&local_iov, &nlocal_iov, len);
202 }
203
204 next_iter:
205 partial = true;
206 local_fds = NULL;
207 local_nfds = NULL;
208 }
209
210 ret = 1;
211
212 cleanup:
213 g_free(local_iov_head);
214 return ret;
215 }
216
217 int coroutine_mixed_fn qio_channel_readv_full_all(QIOChannel *ioc,
218 const struct iovec *iov,
219 size_t niov,
220 int **fds, size_t *nfds,
221 Error **errp)
222 {
223 int ret = qio_channel_readv_full_all_eof(ioc, iov, niov, fds, nfds, 0,
224 errp);
225
226 if (ret == 0) {
227 error_setg(errp, "Unexpected end-of-file before all data were read");
228 return -1;
229 }
230 if (ret == 1) {
231 return 0;
232 }
233
234 return ret;
235 }
236
237 int coroutine_mixed_fn qio_channel_writev_all(QIOChannel *ioc,
238 const struct iovec *iov,
239 size_t niov,
240 Error **errp)
241 {
242 return qio_channel_writev_full_all(ioc, iov, niov, NULL, 0, 0, errp);
243 }
244
245 int coroutine_mixed_fn qio_channel_writev_full_all(QIOChannel *ioc,
246 const struct iovec *iov,
247 size_t niov,
248 int *fds, size_t nfds,
249 int flags, Error **errp)
250 {
251 int ret = -1;
252 struct iovec *local_iov = g_new(struct iovec, niov);
253 struct iovec *local_iov_head = local_iov;
254 unsigned int nlocal_iov = niov;
255
256 nlocal_iov = iov_copy(local_iov, nlocal_iov,
257 iov, niov,
258 0, iov_size(iov, niov));
259
260 while (nlocal_iov > 0) {
261 ssize_t len;
262
263 len = qio_channel_writev_full(ioc, local_iov, nlocal_iov, fds,
264 nfds, flags, errp);
265
266 if (len == QIO_CHANNEL_ERR_BLOCK) {
267 qio_channel_wait_cond(ioc, G_IO_OUT);
268 continue;
269 }
270 if (len < 0) {
271 goto cleanup;
272 }
273
274 iov_discard_front(&local_iov, &nlocal_iov, len);
275
276 fds = NULL;
277 nfds = 0;
278 }
279
280 ret = 0;
281 cleanup:
282 g_free(local_iov_head);
283 return ret;
284 }
285
286 ssize_t qio_channel_readv(QIOChannel *ioc,
287 const struct iovec *iov,
288 size_t niov,
289 Error **errp)
290 {
291 return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, 0, errp);
292 }
293
294
295 ssize_t qio_channel_writev(QIOChannel *ioc,
296 const struct iovec *iov,
297 size_t niov,
298 Error **errp)
299 {
300 return qio_channel_writev_full(ioc, iov, niov, NULL, 0, 0, errp);
301 }
302
303
304 ssize_t qio_channel_read(QIOChannel *ioc,
305 void *buf,
306 size_t buflen,
307 Error **errp)
308 {
309 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
310 return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, 0, errp);
311 }
312
313
314 ssize_t qio_channel_write(QIOChannel *ioc,
315 const void *buf,
316 size_t buflen,
317 Error **errp)
318 {
319 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
320 return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, 0, errp);
321 }
322
323
324 int coroutine_mixed_fn qio_channel_read_all_eof(QIOChannel *ioc,
325 void *buf,
326 size_t buflen,
327 Error **errp)
328 {
329 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
330 return qio_channel_readv_all_eof(ioc, &iov, 1, errp);
331 }
332
333
334 int coroutine_mixed_fn qio_channel_read_all(QIOChannel *ioc,
335 void *buf,
336 size_t buflen,
337 Error **errp)
338 {
339 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
340 return qio_channel_readv_all(ioc, &iov, 1, errp);
341 }
342
343
344 int coroutine_mixed_fn qio_channel_write_all(QIOChannel *ioc,
345 const void *buf,
346 size_t buflen,
347 Error **errp)
348 {
349 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
350 return qio_channel_writev_all(ioc, &iov, 1, errp);
351 }
352
353
354 bool qio_channel_set_blocking(QIOChannel *ioc,
355 bool enabled,
356 Error **errp)
357 {
358 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
359 return klass->io_set_blocking(ioc, enabled, errp) == 0;
360 }
361
362
363 void qio_channel_set_follow_coroutine_ctx(QIOChannel *ioc, bool enabled)
364 {
365 ioc->follow_coroutine_ctx = enabled;
366 }
367
368
369 int qio_channel_close(QIOChannel *ioc,
370 Error **errp)
371 {
372 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
373 return klass->io_close(ioc, errp);
374 }
375
376
377 GSource *qio_channel_create_watch(QIOChannel *ioc,
378 GIOCondition condition)
379 {
380 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
381 GSource *ret = klass->io_create_watch(ioc, condition);
382
383 if (ioc->name) {
384 g_source_set_name(ret, ioc->name);
385 }
386
387 return ret;
388 }
389
390
391 void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
392 AioContext *read_ctx,
393 IOHandler *io_read,
394 AioContext *write_ctx,
395 IOHandler *io_write,
396 void *opaque)
397 {
398 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
399
400 klass->io_set_aio_fd_handler(ioc, read_ctx, io_read, write_ctx, io_write,
401 opaque);
402 }
403
404 guint qio_channel_add_watch_full(QIOChannel *ioc,
405 GIOCondition condition,
406 QIOChannelFunc func,
407 gpointer user_data,
408 GDestroyNotify notify,
409 GMainContext *context)
410 {
411 GSource *source;
412 guint id;
413
414 source = qio_channel_create_watch(ioc, condition);
415
416 g_source_set_callback(source, (GSourceFunc)func, user_data, notify);
417
418 id = g_source_attach(source, context);
419 g_source_unref(source);
420
421 return id;
422 }
423
424 guint qio_channel_add_watch(QIOChannel *ioc,
425 GIOCondition condition,
426 QIOChannelFunc func,
427 gpointer user_data,
428 GDestroyNotify notify)
429 {
430 return qio_channel_add_watch_full(ioc, condition, func,
431 user_data, notify, NULL);
432 }
433
434 GSource *qio_channel_add_watch_source(QIOChannel *ioc,
435 GIOCondition condition,
436 QIOChannelFunc func,
437 gpointer user_data,
438 GDestroyNotify notify,
439 GMainContext *context)
440 {
441 GSource *source;
442 guint id;
443
444 id = qio_channel_add_watch_full(ioc, condition, func,
445 user_data, notify, context);
446 source = g_main_context_find_source_by_id(context, id);
447 g_source_ref(source);
448 return source;
449 }
450
451
452 ssize_t qio_channel_pwritev(QIOChannel *ioc, const struct iovec *iov,
453 size_t niov, off_t offset, Error **errp)
454 {
455 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
456
457 if (!klass->io_pwritev) {
458 error_setg(errp, "Channel does not support pwritev");
459 return -1;
460 }
461
462 if (!qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_SEEKABLE)) {
463 error_setg_errno(errp, EINVAL, "Requested channel is not seekable");
464 return -1;
465 }
466
467 return klass->io_pwritev(ioc, iov, niov, offset, errp);
468 }
469
470 ssize_t qio_channel_pwrite(QIOChannel *ioc, void *buf, size_t buflen,
471 off_t offset, Error **errp)
472 {
473 struct iovec iov = {
474 .iov_base = buf,
475 .iov_len = buflen
476 };
477
478 return qio_channel_pwritev(ioc, &iov, 1, offset, errp);
479 }
480
481 int coroutine_mixed_fn qio_channel_pwritev_all(QIOChannel *ioc,
482 const struct iovec *iov,
483 size_t niov,
484 off_t offset,
485 Error **errp)
486 {
487 int ret = -1;
488 struct iovec *local_iov = g_new(struct iovec, niov);
489 struct iovec *local_iov_head = local_iov;
490 unsigned int nlocal_iov = niov;
491
492 nlocal_iov = iov_copy(local_iov, nlocal_iov,
493 iov, niov,
494 0, iov_size(iov, niov));
495
496 while (nlocal_iov > 0) {
497 ssize_t len;
498
499 len = qio_channel_pwritev(ioc, local_iov, nlocal_iov, offset, errp);
500
501 if (len == QIO_CHANNEL_ERR_BLOCK) {
502 qio_channel_wait_cond(ioc, G_IO_OUT);
503 continue;
504 }
505 if (len < 0) {
506 goto cleanup;
507 }
508
509 offset += len;
510 iov_discard_front(&local_iov, &nlocal_iov, len);
511 }
512
513 ret = 0;
514 cleanup:
515 g_free(local_iov_head);
516 return ret;
517 }
518
519 int coroutine_mixed_fn qio_channel_pwrite_all(QIOChannel *ioc,
520 const void *buf,
521 size_t buflen,
522 off_t offset,
523 Error **errp)
524 {
525 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
526 return qio_channel_pwritev_all(ioc, &iov, 1, offset, errp);
527 }
528
529 ssize_t qio_channel_preadv(QIOChannel *ioc, const struct iovec *iov,
530 size_t niov, off_t offset, Error **errp)
531 {
532 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
533
534 if (!klass->io_preadv) {
535 error_setg(errp, "Channel does not support preadv");
536 return -1;
537 }
538
539 if (!qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_SEEKABLE)) {
540 error_setg_errno(errp, EINVAL, "Requested channel is not seekable");
541 return -1;
542 }
543
544 return klass->io_preadv(ioc, iov, niov, offset, errp);
545 }
546
547 ssize_t qio_channel_pread(QIOChannel *ioc, void *buf, size_t buflen,
548 off_t offset, Error **errp)
549 {
550 struct iovec iov = {
551 .iov_base = buf,
552 .iov_len = buflen
553 };
554
555 return qio_channel_preadv(ioc, &iov, 1, offset, errp);
556 }
557
558 int coroutine_mixed_fn qio_channel_preadv_all_eof(QIOChannel *ioc,
559 const struct iovec *iov,
560 size_t niov,
561 off_t offset,
562 Error **errp)
563 {
564 int ret = -1;
565 struct iovec *local_iov = g_new(struct iovec, niov);
566 struct iovec *local_iov_head = local_iov;
567 unsigned int nlocal_iov = niov;
568 bool partial = false;
569
570 nlocal_iov = iov_copy(local_iov, nlocal_iov,
571 iov, niov,
572 0, iov_size(iov, niov));
573
574 while (nlocal_iov > 0) {
575 ssize_t len;
576 len = qio_channel_preadv(ioc, local_iov, nlocal_iov, offset, errp);
577
578 if (len == QIO_CHANNEL_ERR_BLOCK) {
579 qio_channel_wait_cond(ioc, G_IO_IN);
580 continue;
581 }
582
583 if (len == 0) {
584 if (!partial) {
585 ret = 0;
586 goto cleanup;
587 }
588 error_setg(errp,
589 "Unexpected end-of-file before all data were read");
590 goto cleanup;
591 }
592
593 if (len < 0) {
594 goto cleanup;
595 }
596
597 partial = true;
598 offset += len;
599 iov_discard_front(&local_iov, &nlocal_iov, len);
600 }
601
602 ret = 1;
603
604 cleanup:
605 g_free(local_iov_head);
606 return ret;
607 }
608
609 int coroutine_mixed_fn qio_channel_preadv_all(QIOChannel *ioc,
610 const struct iovec *iov,
611 size_t niov,
612 off_t offset,
613 Error **errp)
614 {
615 int ret = qio_channel_preadv_all_eof(ioc, iov, niov, offset, errp);
616
617 if (ret == 0) {
618 error_setg(errp,
619 "Unexpected end-of-file before all data were read");
620 return -1;
621 }
622 if (ret == 1) {
623 return 0;
624 }
625
626 return ret;
627 }
628
629 int coroutine_mixed_fn qio_channel_pread_all_eof(QIOChannel *ioc,
630 void *buf,
631 size_t buflen,
632 off_t offset,
633 Error **errp)
634 {
635 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
636 return qio_channel_preadv_all_eof(ioc, &iov, 1, offset, errp);
637 }
638
639 int coroutine_mixed_fn qio_channel_pread_all(QIOChannel *ioc,
640 void *buf,
641 size_t buflen,
642 off_t offset,
643 Error **errp)
644 {
645 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
646 return qio_channel_preadv_all(ioc, &iov, 1, offset, errp);
647 }
648
649 int qio_channel_shutdown(QIOChannel *ioc,
650 QIOChannelShutdown how,
651 Error **errp)
652 {
653 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
654
655 if (!klass->io_shutdown) {
656 error_setg(errp, "Data path shutdown not supported");
657 return -1;
658 }
659
660 return klass->io_shutdown(ioc, how, errp);
661 }
662
663
664 void qio_channel_set_delay(QIOChannel *ioc,
665 bool enabled)
666 {
667 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
668
669 if (klass->io_set_delay) {
670 klass->io_set_delay(ioc, enabled);
671 }
672 }
673
674
675 void qio_channel_set_cork(QIOChannel *ioc,
676 bool enabled)
677 {
678 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
679
680 if (klass->io_set_cork) {
681 klass->io_set_cork(ioc, enabled);
682 }
683 }
684
685 int qio_channel_get_peerpid(QIOChannel *ioc,
686 unsigned int *pid,
687 Error **errp)
688 {
689 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
690
691 if (!klass->io_peerpid) {
692 error_setg(errp, "Channel does not support peer pid");
693 return -1;
694 }
695 klass->io_peerpid(ioc, pid, errp);
696 return 0;
697 }
698
699 off_t qio_channel_io_seek(QIOChannel *ioc,
700 off_t offset,
701 int whence,
702 Error **errp)
703 {
704 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
705
706 if (!klass->io_seek) {
707 error_setg(errp, "Channel does not support random access");
708 return -1;
709 }
710
711 return klass->io_seek(ioc, offset, whence, errp);
712 }
713
714 int qio_channel_flush(QIOChannel *ioc,
715 Error **errp)
716 {
717 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
718
719 if (!klass->io_flush ||
720 !qio_channel_has_feature(ioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
721 return 0;
722 }
723
724 return klass->io_flush(ioc, errp);
725 }
726
727
728 static void qio_channel_restart_read(void *opaque)
729 {
730 QIOChannel *ioc = opaque;
731 Coroutine *co = qatomic_xchg(&ioc->read_coroutine, NULL);
732
733 if (!co) {
734 return;
735 }
736
737 /* Assert that aio_co_wake() reenters the coroutine directly */
738 assert(qemu_get_current_aio_context() ==
739 qemu_coroutine_get_aio_context(co));
740 aio_co_wake(co);
741 }
742
743 static void qio_channel_restart_write(void *opaque)
744 {
745 QIOChannel *ioc = opaque;
746 Coroutine *co = qatomic_xchg(&ioc->write_coroutine, NULL);
747
748 if (!co) {
749 return;
750 }
751
752 /* Assert that aio_co_wake() reenters the coroutine directly */
753 assert(qemu_get_current_aio_context() ==
754 qemu_coroutine_get_aio_context(co));
755 aio_co_wake(co);
756 }
757
758 static void coroutine_fn
759 qio_channel_set_fd_handlers(QIOChannel *ioc, GIOCondition condition)
760 {
761 AioContext *ctx = ioc->follow_coroutine_ctx ?
762 qemu_coroutine_get_aio_context(qemu_coroutine_self()) :
763 iohandler_get_aio_context();
764 AioContext *read_ctx = NULL;
765 IOHandler *io_read = NULL;
766 AioContext *write_ctx = NULL;
767 IOHandler *io_write = NULL;
768
769 if (condition == G_IO_IN) {
770 ioc->read_coroutine = qemu_coroutine_self();
771 ioc->read_ctx = ctx;
772 read_ctx = ctx;
773 io_read = qio_channel_restart_read;
774
775 /*
776 * Thread safety: if the other coroutine is set and its AioContext
777 * matches ours, then there is mutual exclusion between read and write
778 * because they share a single thread and it's safe to set both read
779 * and write fd handlers here. If the AioContext does not match ours,
780 * then both threads may run in parallel but there is no shared state
781 * to worry about.
782 */
783 if (ioc->write_coroutine && ioc->write_ctx == ctx) {
784 write_ctx = ctx;
785 io_write = qio_channel_restart_write;
786 }
787 } else if (condition == G_IO_OUT) {
788 ioc->write_coroutine = qemu_coroutine_self();
789 ioc->write_ctx = ctx;
790 write_ctx = ctx;
791 io_write = qio_channel_restart_write;
792 if (ioc->read_coroutine && ioc->read_ctx == ctx) {
793 read_ctx = ctx;
794 io_read = qio_channel_restart_read;
795 }
796 } else {
797 abort();
798 }
799
800 qio_channel_set_aio_fd_handler(ioc, read_ctx, io_read,
801 write_ctx, io_write, ioc);
802 }
803
804 static void coroutine_fn
805 qio_channel_clear_fd_handlers(QIOChannel *ioc, GIOCondition condition)
806 {
807 AioContext *read_ctx = NULL;
808 IOHandler *io_read = NULL;
809 AioContext *write_ctx = NULL;
810 IOHandler *io_write = NULL;
811 AioContext *ctx;
812
813 if (condition == G_IO_IN) {
814 ctx = ioc->read_ctx;
815 read_ctx = ctx;
816 io_read = NULL;
817 if (ioc->write_coroutine && ioc->write_ctx == ctx) {
818 write_ctx = ctx;
819 io_write = qio_channel_restart_write;
820 }
821 } else if (condition == G_IO_OUT) {
822 ctx = ioc->write_ctx;
823 write_ctx = ctx;
824 io_write = NULL;
825 if (ioc->read_coroutine && ioc->read_ctx == ctx) {
826 read_ctx = ctx;
827 io_read = qio_channel_restart_read;
828 }
829 } else {
830 abort();
831 }
832
833 qio_channel_set_aio_fd_handler(ioc, read_ctx, io_read,
834 write_ctx, io_write, ioc);
835 }
836
837 void coroutine_fn qio_channel_yield(QIOChannel *ioc,
838 GIOCondition condition)
839 {
840 AioContext *ioc_ctx;
841
842 assert(qemu_in_coroutine());
843 ioc_ctx = qemu_coroutine_get_aio_context(qemu_coroutine_self());
844
845 if (condition == G_IO_IN) {
846 assert(!ioc->read_coroutine);
847 } else if (condition == G_IO_OUT) {
848 assert(!ioc->write_coroutine);
849 } else {
850 abort();
851 }
852 qio_channel_set_fd_handlers(ioc, condition);
853 qemu_coroutine_yield();
854 assert(in_aio_context_home_thread(ioc_ctx));
855
856 /* Allow interrupting the operation by reentering the coroutine other than
857 * through the aio_fd_handlers. */
858 if (condition == G_IO_IN) {
859 assert(ioc->read_coroutine == NULL);
860 } else if (condition == G_IO_OUT) {
861 assert(ioc->write_coroutine == NULL);
862 }
863 qio_channel_clear_fd_handlers(ioc, condition);
864 }
865
866 void qio_channel_wake_read(QIOChannel *ioc)
867 {
868 Coroutine *co = qatomic_xchg(&ioc->read_coroutine, NULL);
869 if (co) {
870 aio_co_wake(co);
871 }
872 }
873
874 static gboolean qio_channel_wait_complete(QIOChannel *ioc,
875 GIOCondition condition,
876 gpointer opaque)
877 {
878 GMainLoop *loop = opaque;
879
880 g_main_loop_quit(loop);
881 return FALSE;
882 }
883
884
885 void qio_channel_wait(QIOChannel *ioc,
886 GIOCondition condition)
887 {
888 GMainContext *ctxt = g_main_context_new();
889 GMainLoop *loop = g_main_loop_new(ctxt, TRUE);
890 GSource *source;
891
892 source = qio_channel_create_watch(ioc, condition);
893
894 g_source_set_callback(source,
895 (GSourceFunc)qio_channel_wait_complete,
896 loop,
897 NULL);
898
899 g_source_attach(source, ctxt);
900
901 g_main_loop_run(loop);
902
903 g_source_unref(source);
904 g_main_loop_unref(loop);
905 g_main_context_unref(ctxt);
906 }
907
908 void coroutine_mixed_fn
909 qio_channel_wait_cond(QIOChannel *ioc,
910 GIOCondition condition)
911 {
912 if (qemu_in_coroutine()) {
913 qio_channel_yield(ioc, condition);
914 } else {
915 qio_channel_wait(ioc, condition);
916 }
917 }
918
919 static void qio_channel_finalize(Object *obj)
920 {
921 QIOChannel *ioc = QIO_CHANNEL(obj);
922
923 /* Must not have coroutines in qio_channel_yield() */
924 assert(!ioc->read_coroutine);
925 assert(!ioc->write_coroutine);
926
927 g_free(ioc->name);
928
929 #ifdef _WIN32
930 if (ioc->event) {
931 CloseHandle(ioc->event);
932 }
933 #endif
934 }
935
936 static const TypeInfo qio_channel_info = {
937 .parent = TYPE_OBJECT,
938 .name = TYPE_QIO_CHANNEL,
939 .instance_size = sizeof(QIOChannel),
940 .instance_finalize = qio_channel_finalize,
941 .abstract = true,
942 .class_size = sizeof(QIOChannelClass),
943 };
944
945
946 static void qio_channel_register_types(void)
947 {
948 type_register_static(&qio_channel_info);
949 }
950
951
952 type_init(qio_channel_register_types);