4 * Copyright (c) 2015 Red Hat, Inc.
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.
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.
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/>.
21 #include "qemu/osdep.h"
22 #include "io/channel.h"
23 #include "qapi/error.h"
24 #include "qemu/main-loop.h"
26 bool qio_channel_has_feature(QIOChannel
*ioc
,
27 QIOChannelFeature feature
)
29 return ioc
->features
& (1 << feature
);
33 void qio_channel_set_feature(QIOChannel
*ioc
,
34 QIOChannelFeature feature
)
36 ioc
->features
|= (1 << feature
);
40 void qio_channel_set_name(QIOChannel
*ioc
,
44 ioc
->name
= g_strdup(name
);
48 ssize_t
qio_channel_readv_full(QIOChannel
*ioc
,
49 const struct iovec
*iov
,
55 QIOChannelClass
*klass
= QIO_CHANNEL_GET_CLASS(ioc
);
58 !qio_channel_has_feature(ioc
, QIO_CHANNEL_FEATURE_FD_PASS
)) {
59 error_setg_errno(errp
, EINVAL
,
60 "Channel does not support file descriptor passing");
64 return klass
->io_readv(ioc
, iov
, niov
, fds
, nfds
, errp
);
68 ssize_t
qio_channel_writev_full(QIOChannel
*ioc
,
69 const struct iovec
*iov
,
75 QIOChannelClass
*klass
= QIO_CHANNEL_GET_CLASS(ioc
);
78 !qio_channel_has_feature(ioc
, QIO_CHANNEL_FEATURE_FD_PASS
)) {
79 error_setg_errno(errp
, EINVAL
,
80 "Channel does not support file descriptor passing");
84 return klass
->io_writev(ioc
, iov
, niov
, fds
, nfds
, errp
);
88 ssize_t
qio_channel_readv(QIOChannel
*ioc
,
89 const struct iovec
*iov
,
93 return qio_channel_readv_full(ioc
, iov
, niov
, NULL
, NULL
, errp
);
97 ssize_t
qio_channel_writev(QIOChannel
*ioc
,
98 const struct iovec
*iov
,
102 return qio_channel_writev_full(ioc
, iov
, niov
, NULL
, 0, errp
);
106 ssize_t
qio_channel_read(QIOChannel
*ioc
,
111 struct iovec iov
= { .iov_base
= buf
, .iov_len
= buflen
};
112 return qio_channel_readv_full(ioc
, &iov
, 1, NULL
, NULL
, errp
);
116 ssize_t
qio_channel_write(QIOChannel
*ioc
,
121 struct iovec iov
= { .iov_base
= (char *)buf
, .iov_len
= buflen
};
122 return qio_channel_writev_full(ioc
, &iov
, 1, NULL
, 0, errp
);
126 int qio_channel_set_blocking(QIOChannel
*ioc
,
130 QIOChannelClass
*klass
= QIO_CHANNEL_GET_CLASS(ioc
);
131 return klass
->io_set_blocking(ioc
, enabled
, errp
);
135 int qio_channel_close(QIOChannel
*ioc
,
138 QIOChannelClass
*klass
= QIO_CHANNEL_GET_CLASS(ioc
);
139 return klass
->io_close(ioc
, errp
);
143 GSource
*qio_channel_create_watch(QIOChannel
*ioc
,
144 GIOCondition condition
)
146 QIOChannelClass
*klass
= QIO_CHANNEL_GET_CLASS(ioc
);
147 GSource
*ret
= klass
->io_create_watch(ioc
, condition
);
150 g_source_set_name(ret
, ioc
->name
);
157 void qio_channel_set_aio_fd_handler(QIOChannel
*ioc
,
163 QIOChannelClass
*klass
= QIO_CHANNEL_GET_CLASS(ioc
);
165 klass
->io_set_aio_fd_handler(ioc
, ctx
, io_read
, io_write
, opaque
);
168 guint
qio_channel_add_watch(QIOChannel
*ioc
,
169 GIOCondition condition
,
172 GDestroyNotify notify
)
177 source
= qio_channel_create_watch(ioc
, condition
);
179 g_source_set_callback(source
, (GSourceFunc
)func
, user_data
, notify
);
181 id
= g_source_attach(source
, NULL
);
182 g_source_unref(source
);
188 int qio_channel_shutdown(QIOChannel
*ioc
,
189 QIOChannelShutdown how
,
192 QIOChannelClass
*klass
= QIO_CHANNEL_GET_CLASS(ioc
);
194 if (!klass
->io_shutdown
) {
195 error_setg(errp
, "Data path shutdown not supported");
199 return klass
->io_shutdown(ioc
, how
, errp
);
203 void qio_channel_set_delay(QIOChannel
*ioc
,
206 QIOChannelClass
*klass
= QIO_CHANNEL_GET_CLASS(ioc
);
208 if (klass
->io_set_delay
) {
209 klass
->io_set_delay(ioc
, enabled
);
214 void qio_channel_set_cork(QIOChannel
*ioc
,
217 QIOChannelClass
*klass
= QIO_CHANNEL_GET_CLASS(ioc
);
219 if (klass
->io_set_cork
) {
220 klass
->io_set_cork(ioc
, enabled
);
225 off_t
qio_channel_io_seek(QIOChannel
*ioc
,
230 QIOChannelClass
*klass
= QIO_CHANNEL_GET_CLASS(ioc
);
232 if (!klass
->io_seek
) {
233 error_setg(errp
, "Channel does not support random access");
237 return klass
->io_seek(ioc
, offset
, whence
, errp
);
241 static void qio_channel_set_aio_fd_handlers(QIOChannel
*ioc
);
243 static void qio_channel_restart_read(void *opaque
)
245 QIOChannel
*ioc
= opaque
;
246 Coroutine
*co
= ioc
->read_coroutine
;
248 ioc
->read_coroutine
= NULL
;
249 qio_channel_set_aio_fd_handlers(ioc
);
253 static void qio_channel_restart_write(void *opaque
)
255 QIOChannel
*ioc
= opaque
;
256 Coroutine
*co
= ioc
->write_coroutine
;
258 ioc
->write_coroutine
= NULL
;
259 qio_channel_set_aio_fd_handlers(ioc
);
263 static void qio_channel_set_aio_fd_handlers(QIOChannel
*ioc
)
265 IOHandler
*rd_handler
= NULL
, *wr_handler
= NULL
;
268 if (ioc
->read_coroutine
) {
269 rd_handler
= qio_channel_restart_read
;
271 if (ioc
->write_coroutine
) {
272 wr_handler
= qio_channel_restart_write
;
275 ctx
= ioc
->ctx
? ioc
->ctx
: iohandler_get_aio_context();
276 qio_channel_set_aio_fd_handler(ioc
, ctx
, rd_handler
, wr_handler
, ioc
);
279 void qio_channel_attach_aio_context(QIOChannel
*ioc
,
282 assert(!ioc
->read_coroutine
);
283 assert(!ioc
->write_coroutine
);
287 void qio_channel_detach_aio_context(QIOChannel
*ioc
)
289 ioc
->read_coroutine
= NULL
;
290 ioc
->write_coroutine
= NULL
;
291 qio_channel_set_aio_fd_handlers(ioc
);
295 void coroutine_fn
qio_channel_yield(QIOChannel
*ioc
,
296 GIOCondition condition
)
298 assert(qemu_in_coroutine());
299 if (condition
== G_IO_IN
) {
300 assert(!ioc
->read_coroutine
);
301 ioc
->read_coroutine
= qemu_coroutine_self();
302 } else if (condition
== G_IO_OUT
) {
303 assert(!ioc
->write_coroutine
);
304 ioc
->write_coroutine
= qemu_coroutine_self();
308 qio_channel_set_aio_fd_handlers(ioc
);
309 qemu_coroutine_yield();
313 static gboolean
qio_channel_wait_complete(QIOChannel
*ioc
,
314 GIOCondition condition
,
317 GMainLoop
*loop
= opaque
;
319 g_main_loop_quit(loop
);
324 void qio_channel_wait(QIOChannel
*ioc
,
325 GIOCondition condition
)
327 GMainContext
*ctxt
= g_main_context_new();
328 GMainLoop
*loop
= g_main_loop_new(ctxt
, TRUE
);
331 source
= qio_channel_create_watch(ioc
, condition
);
333 g_source_set_callback(source
,
334 (GSourceFunc
)qio_channel_wait_complete
,
338 g_source_attach(source
, ctxt
);
340 g_main_loop_run(loop
);
342 g_source_unref(source
);
343 g_main_loop_unref(loop
);
344 g_main_context_unref(ctxt
);
348 static void qio_channel_finalize(Object
*obj
)
350 QIOChannel
*ioc
= QIO_CHANNEL(obj
);
356 CloseHandle(ioc
->event
);
361 static const TypeInfo qio_channel_info
= {
362 .parent
= TYPE_OBJECT
,
363 .name
= TYPE_QIO_CHANNEL
,
364 .instance_size
= sizeof(QIOChannel
),
365 .instance_finalize
= qio_channel_finalize
,
367 .class_size
= sizeof(QIOChannelClass
),
371 static void qio_channel_register_types(void)
373 type_register_static(&qio_channel_info
);
377 type_init(qio_channel_register_types
);