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 QIOChannelFunc func
= (QIOChannelFunc
)callback
;
82 QIOChannelFDSource
*ssource
= (QIOChannelFDSource
*)source
;
84 return (*func
)(ssource
->ioc
,
85 ssource
->fd
.revents
& ssource
->condition
,
91 qio_channel_fd_source_finalize(GSource
*source
)
93 QIOChannelFDSource
*ssource
= (QIOChannelFDSource
*)source
;
95 object_unref(OBJECT(ssource
->ioc
));
101 qio_channel_socket_source_prepare(GSource
*source G_GNUC_UNUSED
,
111 * NB, this impl only works when the socket is in non-blocking
115 qio_channel_socket_source_check(GSource
*source
)
117 static struct timeval tv0
;
118 QIOChannelSocketSource
*ssource
= (QIOChannelSocketSource
*)source
;
119 fd_set rfds
, wfds
, xfds
;
121 if (!ssource
->condition
) {
128 if (ssource
->condition
& G_IO_IN
) {
129 FD_SET(ssource
->socket
, &rfds
);
131 if (ssource
->condition
& G_IO_OUT
) {
132 FD_SET(ssource
->socket
, &wfds
);
134 if (ssource
->condition
& G_IO_PRI
) {
135 FD_SET(ssource
->socket
, &xfds
);
137 ssource
->revents
= 0;
138 if (select(0, &rfds
, &wfds
, &xfds
, &tv0
) == 0) {
142 if (FD_ISSET(ssource
->socket
, &rfds
)) {
143 ssource
->revents
|= G_IO_IN
;
145 if (FD_ISSET(ssource
->socket
, &wfds
)) {
146 ssource
->revents
|= G_IO_OUT
;
148 if (FD_ISSET(ssource
->socket
, &xfds
)) {
149 ssource
->revents
|= G_IO_PRI
;
152 return ssource
->revents
;
157 qio_channel_socket_source_dispatch(GSource
*source
,
158 GSourceFunc callback
,
161 QIOChannelFunc func
= (QIOChannelFunc
)callback
;
162 QIOChannelSocketSource
*ssource
= (QIOChannelSocketSource
*)source
;
164 return (*func
)(ssource
->ioc
, ssource
->revents
, user_data
);
169 qio_channel_socket_source_finalize(GSource
*source
)
171 QIOChannelSocketSource
*ssource
= (QIOChannelSocketSource
*)source
;
173 object_unref(OBJECT(ssource
->ioc
));
177 GSourceFuncs qio_channel_socket_source_funcs
= {
178 qio_channel_socket_source_prepare
,
179 qio_channel_socket_source_check
,
180 qio_channel_socket_source_dispatch
,
181 qio_channel_socket_source_finalize
187 qio_channel_fd_pair_source_prepare(GSource
*source G_GNUC_UNUSED
,
197 qio_channel_fd_pair_source_check(GSource
*source
)
199 QIOChannelFDPairSource
*ssource
= (QIOChannelFDPairSource
*)source
;
200 GIOCondition poll_condition
= ssource
->fdread
.revents
|
201 ssource
->fdwrite
.revents
;
203 return poll_condition
& ssource
->condition
;
208 qio_channel_fd_pair_source_dispatch(GSource
*source
,
209 GSourceFunc callback
,
212 QIOChannelFunc func
= (QIOChannelFunc
)callback
;
213 QIOChannelFDPairSource
*ssource
= (QIOChannelFDPairSource
*)source
;
214 GIOCondition poll_condition
= ssource
->fdread
.revents
|
215 ssource
->fdwrite
.revents
;
217 return (*func
)(ssource
->ioc
,
218 poll_condition
& ssource
->condition
,
224 qio_channel_fd_pair_source_finalize(GSource
*source
)
226 QIOChannelFDPairSource
*ssource
= (QIOChannelFDPairSource
*)source
;
228 object_unref(OBJECT(ssource
->ioc
));
232 GSourceFuncs qio_channel_fd_source_funcs
= {
233 qio_channel_fd_source_prepare
,
234 qio_channel_fd_source_check
,
235 qio_channel_fd_source_dispatch
,
236 qio_channel_fd_source_finalize
240 GSourceFuncs qio_channel_fd_pair_source_funcs
= {
241 qio_channel_fd_pair_source_prepare
,
242 qio_channel_fd_pair_source_check
,
243 qio_channel_fd_pair_source_dispatch
,
244 qio_channel_fd_pair_source_finalize
248 GSource
*qio_channel_create_fd_watch(QIOChannel
*ioc
,
250 GIOCondition condition
)
253 QIOChannelFDSource
*ssource
;
255 source
= g_source_new(&qio_channel_fd_source_funcs
,
256 sizeof(QIOChannelFDSource
));
257 ssource
= (QIOChannelFDSource
*)source
;
260 object_ref(OBJECT(ioc
));
262 ssource
->condition
= condition
;
265 ssource
->fd
.fd
= (gint64
)_get_osfhandle(fd
);
269 ssource
->fd
.events
= condition
;
271 g_source_add_poll(source
, &ssource
->fd
);
277 GSource
*qio_channel_create_socket_watch(QIOChannel
*ioc
,
279 GIOCondition condition
)
282 QIOChannelSocketSource
*ssource
;
284 WSAEventSelect(socket
, ioc
->event
,
285 FD_READ
| FD_ACCEPT
| FD_CLOSE
|
286 FD_CONNECT
| FD_WRITE
| FD_OOB
);
288 source
= g_source_new(&qio_channel_socket_source_funcs
,
289 sizeof(QIOChannelSocketSource
));
290 ssource
= (QIOChannelSocketSource
*)source
;
293 object_ref(OBJECT(ioc
));
295 ssource
->condition
= condition
;
296 ssource
->socket
= socket
;
297 ssource
->revents
= 0;
299 ssource
->fd
.fd
= (gintptr
)ioc
->event
;
300 ssource
->fd
.events
= G_IO_IN
;
302 g_source_add_poll(source
, &ssource
->fd
);
307 GSource
*qio_channel_create_socket_watch(QIOChannel
*ioc
,
309 GIOCondition condition
)
311 return qio_channel_create_fd_watch(ioc
, socket
, condition
);
315 GSource
*qio_channel_create_fd_pair_watch(QIOChannel
*ioc
,
318 GIOCondition condition
)
321 QIOChannelFDPairSource
*ssource
;
323 source
= g_source_new(&qio_channel_fd_pair_source_funcs
,
324 sizeof(QIOChannelFDPairSource
));
325 ssource
= (QIOChannelFDPairSource
*)source
;
328 object_ref(OBJECT(ioc
));
330 ssource
->condition
= condition
;
333 ssource
->fdread
.fd
= (gint64
)_get_osfhandle(fdread
);
334 ssource
->fdwrite
.fd
= (gint64
)_get_osfhandle(fdwrite
);
336 ssource
->fdread
.fd
= fdread
;
337 ssource
->fdwrite
.fd
= fdwrite
;
340 ssource
->fdread
.events
= condition
& G_IO_IN
;
341 ssource
->fdwrite
.events
= condition
& G_IO_OUT
;
343 g_source_add_poll(source
, &ssource
->fdread
);
344 g_source_add_poll(source
, &ssource
->fdwrite
);