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
{
29 GIOCondition condition
;
34 typedef struct QIOChannelSocketSource QIOChannelSocketSource
;
35 struct QIOChannelSocketSource
{
41 GIOCondition condition
;
47 typedef struct QIOChannelFDPairSource QIOChannelFDPairSource
;
48 struct QIOChannelFDPairSource
{
53 GIOCondition condition
;
58 qio_channel_fd_source_prepare(GSource
*source G_GNUC_UNUSED
,
68 qio_channel_fd_source_check(GSource
*source
)
70 QIOChannelFDSource
*ssource
= (QIOChannelFDSource
*)source
;
72 return ssource
->fd
.revents
& ssource
->condition
;
77 qio_channel_fd_source_dispatch(GSource
*source
,
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
,
92 qio_channel_fd_source_finalize(GSource
*source
)
94 QIOChannelFDSource
*ssource
= (QIOChannelFDSource
*)source
;
96 object_unref(OBJECT(ssource
->ioc
));
102 qio_channel_socket_source_prepare(GSource
*source G_GNUC_UNUSED
,
112 * NB, this impl only works when the socket is in non-blocking
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
) {
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) {
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
;
158 qio_channel_socket_source_dispatch(GSource
*source
,
159 GSourceFunc callback
,
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
);
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
189 qio_channel_fd_pair_source_prepare(GSource
*source G_GNUC_UNUSED
,
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
;
210 qio_channel_fd_pair_source_dispatch(GSource
*source
,
211 GSourceFunc callback
,
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
,
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
,
252 GIOCondition condition
)
255 QIOChannelFDSource
*ssource
;
257 source
= g_source_new(&qio_channel_fd_source_funcs
,
258 sizeof(QIOChannelFDSource
));
259 ssource
= (QIOChannelFDSource
*)source
;
262 object_ref(OBJECT(ioc
));
264 ssource
->condition
= condition
;
267 ssource
->fd
.fd
= (gint64
)_get_osfhandle(fd
);
271 ssource
->fd
.events
= condition
;
273 g_source_add_poll(source
, &ssource
->fd
);
279 GSource
*qio_channel_create_socket_watch(QIOChannel
*ioc
,
281 GIOCondition condition
)
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
;
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
);
309 GSource
*qio_channel_create_socket_watch(QIOChannel
*ioc
,
311 GIOCondition condition
)
313 return qio_channel_create_fd_watch(ioc
, socket
, condition
);
317 GSource
*qio_channel_create_fd_pair_watch(QIOChannel
*ioc
,
320 GIOCondition condition
)
323 QIOChannelFDPairSource
*ssource
;
325 source
= g_source_new(&qio_channel_fd_pair_source_funcs
,
326 sizeof(QIOChannelFDPairSource
));
327 ssource
= (QIOChannelFDPairSource
*)source
;
330 object_ref(OBJECT(ioc
));
332 ssource
->condition
= condition
;
335 ssource
->fdread
.fd
= (gint64
)_get_osfhandle(fdread
);
336 ssource
->fdwrite
.fd
= (gint64
)_get_osfhandle(fdwrite
);
338 ssource
->fdread
.fd
= fdread
;
339 ssource
->fdwrite
.fd
= fdwrite
;
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
);