Merge tag 'v8.2.0-rc2'
[qemu/ar7.git] / io / channel-watch.c
blob045dd30b714d06ee3f3ac05761481eaa923a369c
1 /*
2 * QEMU I/O channels watch helper APIs
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.1 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-watch.h"
24 typedef struct QIOChannelFDSource QIOChannelFDSource;
25 struct QIOChannelFDSource {
26 GSource parent;
27 GPollFD fd;
28 QIOChannel *ioc;
29 GIOCondition condition;
33 #ifdef CONFIG_WIN32
34 typedef struct QIOChannelSocketSource QIOChannelSocketSource;
35 struct QIOChannelSocketSource {
36 GSource parent;
37 GPollFD fd;
38 QIOChannel *ioc;
39 SOCKET socket;
40 int revents;
41 GIOCondition condition;
44 #endif
47 typedef struct QIOChannelFDPairSource QIOChannelFDPairSource;
48 struct QIOChannelFDPairSource {
49 GSource parent;
50 GPollFD fdread;
51 GPollFD fdwrite;
52 QIOChannel *ioc;
53 GIOCondition condition;
57 static gboolean
58 qio_channel_fd_source_prepare(GSource *source G_GNUC_UNUSED,
59 gint *timeout)
61 *timeout = -1;
63 return FALSE;
67 static gboolean
68 qio_channel_fd_source_check(GSource *source)
70 QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
72 return ssource->fd.revents & ssource->condition;
76 static gboolean
77 qio_channel_fd_source_dispatch(GSource *source,
78 GSourceFunc callback,
79 gpointer user_data)
81 #pragma GCC diagnostic ignored "-Wcast-function-type"
82 QIOChannelFunc func = (QIOChannelFunc)callback;
83 QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
85 return (*func)(ssource->ioc,
86 ssource->fd.revents & ssource->condition,
87 user_data);
91 static void
92 qio_channel_fd_source_finalize(GSource *source)
94 QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
96 object_unref(OBJECT(ssource->ioc));
100 #ifdef CONFIG_WIN32
101 static gboolean
102 qio_channel_socket_source_prepare(GSource *source G_GNUC_UNUSED,
103 gint *timeout)
105 *timeout = -1;
107 return FALSE;
112 * NB, this impl only works when the socket is in non-blocking
113 * mode on Win32
115 static gboolean
116 qio_channel_socket_source_check(GSource *source)
118 static struct timeval tv0;
119 QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
120 fd_set rfds, wfds, xfds;
122 if (!ssource->condition) {
123 return 0;
126 FD_ZERO(&rfds);
127 FD_ZERO(&wfds);
128 FD_ZERO(&xfds);
129 if (ssource->condition & G_IO_IN) {
130 FD_SET(ssource->socket, &rfds);
132 if (ssource->condition & G_IO_OUT) {
133 FD_SET(ssource->socket, &wfds);
135 if (ssource->condition & G_IO_PRI) {
136 FD_SET(ssource->socket, &xfds);
138 ssource->revents = 0;
139 if (select(0, &rfds, &wfds, &xfds, &tv0) == 0) {
140 return 0;
143 if (FD_ISSET(ssource->socket, &rfds)) {
144 ssource->revents |= G_IO_IN;
146 if (FD_ISSET(ssource->socket, &wfds)) {
147 ssource->revents |= G_IO_OUT;
149 if (FD_ISSET(ssource->socket, &xfds)) {
150 ssource->revents |= G_IO_PRI;
153 return ssource->revents;
157 static gboolean
158 qio_channel_socket_source_dispatch(GSource *source,
159 GSourceFunc callback,
160 gpointer user_data)
162 #pragma GCC diagnostic ignored "-Wcast-function-type"
163 QIOChannelFunc func = (QIOChannelFunc)callback;
164 QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
166 return (*func)(ssource->ioc, ssource->revents, user_data);
170 static void
171 qio_channel_socket_source_finalize(GSource *source)
173 QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
175 object_unref(OBJECT(ssource->ioc));
179 GSourceFuncs qio_channel_socket_source_funcs = {
180 qio_channel_socket_source_prepare,
181 qio_channel_socket_source_check,
182 qio_channel_socket_source_dispatch,
183 qio_channel_socket_source_finalize
185 #endif
188 static gboolean
189 qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED,
190 gint *timeout)
192 *timeout = -1;
194 return FALSE;
198 static gboolean
199 qio_channel_fd_pair_source_check(GSource *source)
201 QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
202 GIOCondition poll_condition = ssource->fdread.revents |
203 ssource->fdwrite.revents;
205 return poll_condition & ssource->condition;
209 static gboolean
210 qio_channel_fd_pair_source_dispatch(GSource *source,
211 GSourceFunc callback,
212 gpointer user_data)
214 QIOChannelFunc func = (QIOChannelFunc)callback;
215 QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
216 GIOCondition poll_condition = ssource->fdread.revents |
217 ssource->fdwrite.revents;
219 return (*func)(ssource->ioc,
220 poll_condition & ssource->condition,
221 user_data);
225 static void
226 qio_channel_fd_pair_source_finalize(GSource *source)
228 QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
230 object_unref(OBJECT(ssource->ioc));
234 GSourceFuncs qio_channel_fd_source_funcs = {
235 qio_channel_fd_source_prepare,
236 qio_channel_fd_source_check,
237 qio_channel_fd_source_dispatch,
238 qio_channel_fd_source_finalize
242 GSourceFuncs qio_channel_fd_pair_source_funcs = {
243 qio_channel_fd_pair_source_prepare,
244 qio_channel_fd_pair_source_check,
245 qio_channel_fd_pair_source_dispatch,
246 qio_channel_fd_pair_source_finalize
250 GSource *qio_channel_create_fd_watch(QIOChannel *ioc,
251 int fd,
252 GIOCondition condition)
254 GSource *source;
255 QIOChannelFDSource *ssource;
257 source = g_source_new(&qio_channel_fd_source_funcs,
258 sizeof(QIOChannelFDSource));
259 ssource = (QIOChannelFDSource *)source;
261 ssource->ioc = ioc;
262 object_ref(OBJECT(ioc));
264 ssource->condition = condition;
266 #ifdef CONFIG_WIN32
267 ssource->fd.fd = (gint64)_get_osfhandle(fd);
268 #else
269 ssource->fd.fd = fd;
270 #endif
271 ssource->fd.events = condition;
273 g_source_add_poll(source, &ssource->fd);
275 return source;
278 #ifdef CONFIG_WIN32
279 GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
280 int sockfd,
281 GIOCondition condition)
283 GSource *source;
284 QIOChannelSocketSource *ssource;
286 qemu_socket_select(sockfd, ioc->event,
287 FD_READ | FD_ACCEPT | FD_CLOSE |
288 FD_CONNECT | FD_WRITE | FD_OOB, NULL);
290 source = g_source_new(&qio_channel_socket_source_funcs,
291 sizeof(QIOChannelSocketSource));
292 ssource = (QIOChannelSocketSource *)source;
294 ssource->ioc = ioc;
295 object_ref(OBJECT(ioc));
297 ssource->condition = condition;
298 ssource->socket = _get_osfhandle(sockfd);
299 ssource->revents = 0;
301 ssource->fd.fd = (gintptr)ioc->event;
302 ssource->fd.events = G_IO_IN;
304 g_source_add_poll(source, &ssource->fd);
306 return source;
308 #else
309 GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
310 int socket,
311 GIOCondition condition)
313 return qio_channel_create_fd_watch(ioc, socket, condition);
315 #endif
317 GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc,
318 int fdread,
319 int fdwrite,
320 GIOCondition condition)
322 GSource *source;
323 QIOChannelFDPairSource *ssource;
325 source = g_source_new(&qio_channel_fd_pair_source_funcs,
326 sizeof(QIOChannelFDPairSource));
327 ssource = (QIOChannelFDPairSource *)source;
329 ssource->ioc = ioc;
330 object_ref(OBJECT(ioc));
332 ssource->condition = condition;
334 #ifdef CONFIG_WIN32
335 ssource->fdread.fd = (gint64)_get_osfhandle(fdread);
336 ssource->fdwrite.fd = (gint64)_get_osfhandle(fdwrite);
337 #else
338 ssource->fdread.fd = fdread;
339 ssource->fdwrite.fd = fdwrite;
340 #endif
342 ssource->fdread.events = condition & G_IO_IN;
343 ssource->fdwrite.events = condition & G_IO_OUT;
345 g_source_add_poll(source, &ssource->fdread);
346 g_source_add_poll(source, &ssource->fdwrite);
348 return source;