11c809fa0SDaniel P. Berrange /* 21c809fa0SDaniel P. Berrange * QEMU I/O channels watch helper APIs 31c809fa0SDaniel P. Berrange * 41c809fa0SDaniel P. Berrange * Copyright (c) 2015 Red Hat, Inc. 51c809fa0SDaniel P. Berrange * 61c809fa0SDaniel P. Berrange * This library is free software; you can redistribute it and/or 71c809fa0SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 81c809fa0SDaniel P. Berrange * License as published by the Free Software Foundation; either 91c809fa0SDaniel P. Berrange * version 2 of the License, or (at your option) any later version. 101c809fa0SDaniel P. Berrange * 111c809fa0SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 121c809fa0SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 131c809fa0SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 141c809fa0SDaniel P. Berrange * Lesser General Public License for more details. 151c809fa0SDaniel P. Berrange * 161c809fa0SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 171c809fa0SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 181c809fa0SDaniel P. Berrange * 191c809fa0SDaniel P. Berrange */ 201c809fa0SDaniel P. Berrange 21cae9fc56SPeter Maydell #include "qemu/osdep.h" 221c809fa0SDaniel P. Berrange #include "io/channel-watch.h" 231c809fa0SDaniel P. Berrange 241c809fa0SDaniel P. Berrange typedef struct QIOChannelFDSource QIOChannelFDSource; 251c809fa0SDaniel P. Berrange struct QIOChannelFDSource { 261c809fa0SDaniel P. Berrange GSource parent; 271c809fa0SDaniel P. Berrange GPollFD fd; 281c809fa0SDaniel P. Berrange QIOChannel *ioc; 291c809fa0SDaniel P. Berrange GIOCondition condition; 301c809fa0SDaniel P. Berrange }; 311c809fa0SDaniel P. Berrange 321c809fa0SDaniel P. Berrange 331c809fa0SDaniel P. Berrange typedef struct QIOChannelFDPairSource QIOChannelFDPairSource; 341c809fa0SDaniel P. Berrange struct QIOChannelFDPairSource { 351c809fa0SDaniel P. Berrange GSource parent; 361c809fa0SDaniel P. Berrange GPollFD fdread; 371c809fa0SDaniel P. Berrange GPollFD fdwrite; 381c809fa0SDaniel P. Berrange QIOChannel *ioc; 391c809fa0SDaniel P. Berrange GIOCondition condition; 401c809fa0SDaniel P. Berrange }; 411c809fa0SDaniel P. Berrange 421c809fa0SDaniel P. Berrange 431c809fa0SDaniel P. Berrange static gboolean 441c809fa0SDaniel P. Berrange qio_channel_fd_source_prepare(GSource *source G_GNUC_UNUSED, 451c809fa0SDaniel P. Berrange gint *timeout) 461c809fa0SDaniel P. Berrange { 471c809fa0SDaniel P. Berrange *timeout = -1; 481c809fa0SDaniel P. Berrange 491c809fa0SDaniel P. Berrange return FALSE; 501c809fa0SDaniel P. Berrange } 511c809fa0SDaniel P. Berrange 521c809fa0SDaniel P. Berrange 531c809fa0SDaniel P. Berrange static gboolean 541c809fa0SDaniel P. Berrange qio_channel_fd_source_check(GSource *source) 551c809fa0SDaniel P. Berrange { 561c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 571c809fa0SDaniel P. Berrange 581c809fa0SDaniel P. Berrange return ssource->fd.revents & ssource->condition; 591c809fa0SDaniel P. Berrange } 601c809fa0SDaniel P. Berrange 611c809fa0SDaniel P. Berrange 621c809fa0SDaniel P. Berrange static gboolean 631c809fa0SDaniel P. Berrange qio_channel_fd_source_dispatch(GSource *source, 641c809fa0SDaniel P. Berrange GSourceFunc callback, 651c809fa0SDaniel P. Berrange gpointer user_data) 661c809fa0SDaniel P. Berrange { 671c809fa0SDaniel P. Berrange QIOChannelFunc func = (QIOChannelFunc)callback; 681c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 691c809fa0SDaniel P. Berrange 701c809fa0SDaniel P. Berrange return (*func)(ssource->ioc, 711c809fa0SDaniel P. Berrange ssource->fd.revents & ssource->condition, 721c809fa0SDaniel P. Berrange user_data); 731c809fa0SDaniel P. Berrange } 741c809fa0SDaniel P. Berrange 751c809fa0SDaniel P. Berrange 761c809fa0SDaniel P. Berrange static void 771c809fa0SDaniel P. Berrange qio_channel_fd_source_finalize(GSource *source) 781c809fa0SDaniel P. Berrange { 791c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 801c809fa0SDaniel P. Berrange 811c809fa0SDaniel P. Berrange object_unref(OBJECT(ssource->ioc)); 821c809fa0SDaniel P. Berrange } 831c809fa0SDaniel P. Berrange 841c809fa0SDaniel P. Berrange 851c809fa0SDaniel P. Berrange static gboolean 861c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED, 871c809fa0SDaniel P. Berrange gint *timeout) 881c809fa0SDaniel P. Berrange { 891c809fa0SDaniel P. Berrange *timeout = -1; 901c809fa0SDaniel P. Berrange 911c809fa0SDaniel P. Berrange return FALSE; 921c809fa0SDaniel P. Berrange } 931c809fa0SDaniel P. Berrange 941c809fa0SDaniel P. Berrange 951c809fa0SDaniel P. Berrange static gboolean 961c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_check(GSource *source) 971c809fa0SDaniel P. Berrange { 981c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 991c809fa0SDaniel P. Berrange GIOCondition poll_condition = ssource->fdread.revents | 1001c809fa0SDaniel P. Berrange ssource->fdwrite.revents; 1011c809fa0SDaniel P. Berrange 1021c809fa0SDaniel P. Berrange return poll_condition & ssource->condition; 1031c809fa0SDaniel P. Berrange } 1041c809fa0SDaniel P. Berrange 1051c809fa0SDaniel P. Berrange 1061c809fa0SDaniel P. Berrange static gboolean 1071c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_dispatch(GSource *source, 1081c809fa0SDaniel P. Berrange GSourceFunc callback, 1091c809fa0SDaniel P. Berrange gpointer user_data) 1101c809fa0SDaniel P. Berrange { 1111c809fa0SDaniel P. Berrange QIOChannelFunc func = (QIOChannelFunc)callback; 1121c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 1131c809fa0SDaniel P. Berrange GIOCondition poll_condition = ssource->fdread.revents | 1141c809fa0SDaniel P. Berrange ssource->fdwrite.revents; 1151c809fa0SDaniel P. Berrange 1161c809fa0SDaniel P. Berrange return (*func)(ssource->ioc, 1171c809fa0SDaniel P. Berrange poll_condition & ssource->condition, 1181c809fa0SDaniel P. Berrange user_data); 1191c809fa0SDaniel P. Berrange } 1201c809fa0SDaniel P. Berrange 1211c809fa0SDaniel P. Berrange 1221c809fa0SDaniel P. Berrange static void 1231c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_finalize(GSource *source) 1241c809fa0SDaniel P. Berrange { 1251c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 1261c809fa0SDaniel P. Berrange 1271c809fa0SDaniel P. Berrange object_unref(OBJECT(ssource->ioc)); 1281c809fa0SDaniel P. Berrange } 1291c809fa0SDaniel P. Berrange 1301c809fa0SDaniel P. Berrange 1311c809fa0SDaniel P. Berrange GSourceFuncs qio_channel_fd_source_funcs = { 1321c809fa0SDaniel P. Berrange qio_channel_fd_source_prepare, 1331c809fa0SDaniel P. Berrange qio_channel_fd_source_check, 1341c809fa0SDaniel P. Berrange qio_channel_fd_source_dispatch, 1351c809fa0SDaniel P. Berrange qio_channel_fd_source_finalize 1361c809fa0SDaniel P. Berrange }; 1371c809fa0SDaniel P. Berrange 1381c809fa0SDaniel P. Berrange 1391c809fa0SDaniel P. Berrange GSourceFuncs qio_channel_fd_pair_source_funcs = { 1401c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_prepare, 1411c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_check, 1421c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_dispatch, 1431c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_finalize 1441c809fa0SDaniel P. Berrange }; 1451c809fa0SDaniel P. Berrange 1461c809fa0SDaniel P. Berrange 1471c809fa0SDaniel P. Berrange GSource *qio_channel_create_fd_watch(QIOChannel *ioc, 1481c809fa0SDaniel P. Berrange int fd, 1491c809fa0SDaniel P. Berrange GIOCondition condition) 1501c809fa0SDaniel P. Berrange { 1511c809fa0SDaniel P. Berrange GSource *source; 1521c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource; 1531c809fa0SDaniel P. Berrange 1541c809fa0SDaniel P. Berrange source = g_source_new(&qio_channel_fd_source_funcs, 1551c809fa0SDaniel P. Berrange sizeof(QIOChannelFDSource)); 1561c809fa0SDaniel P. Berrange ssource = (QIOChannelFDSource *)source; 1571c809fa0SDaniel P. Berrange 1581c809fa0SDaniel P. Berrange ssource->ioc = ioc; 1591c809fa0SDaniel P. Berrange object_ref(OBJECT(ioc)); 1601c809fa0SDaniel P. Berrange 1611c809fa0SDaniel P. Berrange ssource->condition = condition; 1621c809fa0SDaniel P. Berrange 163e560d141SPaolo Bonzini #ifdef CONFIG_WIN32 164e560d141SPaolo Bonzini ssource->fd.fd = (gint64)_get_osfhandle(fd); 165e560d141SPaolo Bonzini #else 1661c809fa0SDaniel P. Berrange ssource->fd.fd = fd; 167e560d141SPaolo Bonzini #endif 1681c809fa0SDaniel P. Berrange ssource->fd.events = condition; 1691c809fa0SDaniel P. Berrange 1701c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fd); 1711c809fa0SDaniel P. Berrange 1721c809fa0SDaniel P. Berrange return source; 1731c809fa0SDaniel P. Berrange } 1741c809fa0SDaniel P. Berrange 175*b83b68a0SPaolo Bonzini #ifdef CONFIG_WIN32 176*b83b68a0SPaolo Bonzini GSource *qio_channel_create_socket_watch(QIOChannel *ioc, 177*b83b68a0SPaolo Bonzini int socket, 178*b83b68a0SPaolo Bonzini GIOCondition condition) 179*b83b68a0SPaolo Bonzini { 180*b83b68a0SPaolo Bonzini abort(); 181*b83b68a0SPaolo Bonzini } 182*b83b68a0SPaolo Bonzini #else 183*b83b68a0SPaolo Bonzini GSource *qio_channel_create_socket_watch(QIOChannel *ioc, 184*b83b68a0SPaolo Bonzini int socket, 185*b83b68a0SPaolo Bonzini GIOCondition condition) 186*b83b68a0SPaolo Bonzini { 187*b83b68a0SPaolo Bonzini return qio_channel_create_fd_watch(ioc, socket, condition); 188*b83b68a0SPaolo Bonzini } 189*b83b68a0SPaolo Bonzini #endif 1901c809fa0SDaniel P. Berrange 1911c809fa0SDaniel P. Berrange GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc, 1921c809fa0SDaniel P. Berrange int fdread, 1931c809fa0SDaniel P. Berrange int fdwrite, 1941c809fa0SDaniel P. Berrange GIOCondition condition) 1951c809fa0SDaniel P. Berrange { 1961c809fa0SDaniel P. Berrange GSource *source; 1971c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource; 1981c809fa0SDaniel P. Berrange 1991c809fa0SDaniel P. Berrange source = g_source_new(&qio_channel_fd_pair_source_funcs, 2001c809fa0SDaniel P. Berrange sizeof(QIOChannelFDPairSource)); 2011c809fa0SDaniel P. Berrange ssource = (QIOChannelFDPairSource *)source; 2021c809fa0SDaniel P. Berrange 2031c809fa0SDaniel P. Berrange ssource->ioc = ioc; 2041c809fa0SDaniel P. Berrange object_ref(OBJECT(ioc)); 2051c809fa0SDaniel P. Berrange 2061c809fa0SDaniel P. Berrange ssource->condition = condition; 2071c809fa0SDaniel P. Berrange 208e560d141SPaolo Bonzini #ifdef CONFIG_WIN32 209e560d141SPaolo Bonzini ssource->fdread.fd = (gint64)_get_osfhandle(fdread); 210e560d141SPaolo Bonzini ssource->fdwrite.fd = (gint64)_get_osfhandle(fdwrite); 211e560d141SPaolo Bonzini #else 2121c809fa0SDaniel P. Berrange ssource->fdread.fd = fdread; 2131c809fa0SDaniel P. Berrange ssource->fdwrite.fd = fdwrite; 214e560d141SPaolo Bonzini #endif 215e560d141SPaolo Bonzini 216e560d141SPaolo Bonzini ssource->fdread.events = condition & G_IO_IN; 2171c809fa0SDaniel P. Berrange ssource->fdwrite.events = condition & G_IO_OUT; 2181c809fa0SDaniel P. Berrange 2191c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fdread); 2201c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fdwrite); 2211c809fa0SDaniel P. Berrange 2221c809fa0SDaniel P. Berrange return source; 2231c809fa0SDaniel P. Berrange } 224