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 qemu_socket_select(sockfd, ioc->event,
285 FD_READ | FD_ACCEPT | FD_CLOSE |
286 FD_CONNECT | FD_WRITE | FD_OOB, NULL);
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 = _get_osfhandle(sockfd);
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);