Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160203' into...
[qemu/ar7.git] / io / channel.c
blob5e94469de26753cf7e92a91a1ea845423a076cd9
1 /*
2 * QEMU I/O channels
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 "io/channel.h"
22 #include "qemu/coroutine.h"
24 bool qio_channel_has_feature(QIOChannel *ioc,
25 QIOChannelFeature feature)
27 return ioc->features & (1 << feature);
31 ssize_t qio_channel_readv_full(QIOChannel *ioc,
32 const struct iovec *iov,
33 size_t niov,
34 int **fds,
35 size_t *nfds,
36 Error **errp)
38 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
40 if ((fds || nfds) &&
41 !(ioc->features & (1 << QIO_CHANNEL_FEATURE_FD_PASS))) {
42 error_setg_errno(errp, EINVAL,
43 "Channel does not support file descriptor passing");
44 return -1;
47 return klass->io_readv(ioc, iov, niov, fds, nfds, errp);
51 ssize_t qio_channel_writev_full(QIOChannel *ioc,
52 const struct iovec *iov,
53 size_t niov,
54 int *fds,
55 size_t nfds,
56 Error **errp)
58 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
60 if ((fds || nfds) &&
61 !(ioc->features & (1 << QIO_CHANNEL_FEATURE_FD_PASS))) {
62 error_setg_errno(errp, EINVAL,
63 "Channel does not support file descriptor passing");
64 return -1;
67 return klass->io_writev(ioc, iov, niov, fds, nfds, errp);
71 ssize_t qio_channel_readv(QIOChannel *ioc,
72 const struct iovec *iov,
73 size_t niov,
74 Error **errp)
76 return qio_channel_readv_full(ioc, iov, niov, NULL, NULL, errp);
80 ssize_t qio_channel_writev(QIOChannel *ioc,
81 const struct iovec *iov,
82 size_t niov,
83 Error **errp)
85 return qio_channel_writev_full(ioc, iov, niov, NULL, 0, errp);
89 ssize_t qio_channel_read(QIOChannel *ioc,
90 char *buf,
91 size_t buflen,
92 Error **errp)
94 struct iovec iov = { .iov_base = buf, .iov_len = buflen };
95 return qio_channel_readv_full(ioc, &iov, 1, NULL, NULL, errp);
99 ssize_t qio_channel_write(QIOChannel *ioc,
100 const char *buf,
101 size_t buflen,
102 Error **errp)
104 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
105 return qio_channel_writev_full(ioc, &iov, 1, NULL, 0, errp);
109 int qio_channel_set_blocking(QIOChannel *ioc,
110 bool enabled,
111 Error **errp)
113 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
114 return klass->io_set_blocking(ioc, enabled, errp);
118 int qio_channel_close(QIOChannel *ioc,
119 Error **errp)
121 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
122 return klass->io_close(ioc, errp);
126 GSource *qio_channel_create_watch(QIOChannel *ioc,
127 GIOCondition condition)
129 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
130 return klass->io_create_watch(ioc, condition);
134 guint qio_channel_add_watch(QIOChannel *ioc,
135 GIOCondition condition,
136 QIOChannelFunc func,
137 gpointer user_data,
138 GDestroyNotify notify)
140 GSource *source;
141 guint id;
143 source = qio_channel_create_watch(ioc, condition);
145 g_source_set_callback(source, (GSourceFunc)func, user_data, notify);
147 id = g_source_attach(source, NULL);
148 g_source_unref(source);
150 return id;
154 int qio_channel_shutdown(QIOChannel *ioc,
155 QIOChannelShutdown how,
156 Error **errp)
158 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
160 if (!klass->io_shutdown) {
161 error_setg(errp, "Data path shutdown not supported");
162 return -1;
165 return klass->io_shutdown(ioc, how, errp);
169 void qio_channel_set_delay(QIOChannel *ioc,
170 bool enabled)
172 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
174 if (klass->io_set_delay) {
175 klass->io_set_delay(ioc, enabled);
180 void qio_channel_set_cork(QIOChannel *ioc,
181 bool enabled)
183 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
185 if (klass->io_set_cork) {
186 klass->io_set_cork(ioc, enabled);
191 off_t qio_channel_io_seek(QIOChannel *ioc,
192 off_t offset,
193 int whence,
194 Error **errp)
196 QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
198 if (!klass->io_seek) {
199 error_setg(errp, "Channel does not support random access");
200 return -1;
203 return klass->io_seek(ioc, offset, whence, errp);
207 typedef struct QIOChannelYieldData QIOChannelYieldData;
208 struct QIOChannelYieldData {
209 QIOChannel *ioc;
210 Coroutine *co;
214 static gboolean qio_channel_yield_enter(QIOChannel *ioc,
215 GIOCondition condition,
216 gpointer opaque)
218 QIOChannelYieldData *data = opaque;
219 qemu_coroutine_enter(data->co, NULL);
220 return FALSE;
224 void coroutine_fn qio_channel_yield(QIOChannel *ioc,
225 GIOCondition condition)
227 QIOChannelYieldData data;
229 assert(qemu_in_coroutine());
230 data.ioc = ioc;
231 data.co = qemu_coroutine_self();
232 qio_channel_add_watch(ioc,
233 condition,
234 qio_channel_yield_enter,
235 &data,
236 NULL);
237 qemu_coroutine_yield();
241 static gboolean qio_channel_wait_complete(QIOChannel *ioc,
242 GIOCondition condition,
243 gpointer opaque)
245 GMainLoop *loop = opaque;
247 g_main_loop_quit(loop);
248 return FALSE;
252 void qio_channel_wait(QIOChannel *ioc,
253 GIOCondition condition)
255 GMainContext *ctxt = g_main_context_new();
256 GMainLoop *loop = g_main_loop_new(ctxt, TRUE);
257 GSource *source;
259 source = qio_channel_create_watch(ioc, condition);
261 g_source_set_callback(source,
262 (GSourceFunc)qio_channel_wait_complete,
263 loop,
264 NULL);
266 g_source_attach(source, ctxt);
268 g_main_loop_run(loop);
270 g_source_unref(source);
271 g_main_loop_unref(loop);
272 g_main_context_unref(ctxt);
276 static const TypeInfo qio_channel_info = {
277 .parent = TYPE_OBJECT,
278 .name = TYPE_QIO_CHANNEL,
279 .instance_size = sizeof(QIOChannel),
280 .abstract = true,
281 .class_size = sizeof(QIOChannelClass),
285 static void qio_channel_register_types(void)
287 type_register_static(&qio_channel_info);
291 type_init(qio_channel_register_types);