1 /* 2 * QEMU I/O channels watch helper APIs 3 * 4 * Copyright (c) 2015 Red Hat, Inc. 5 * 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 of the License, or (at your option) any later version. 10 * 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. 15 * 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/>. 18 * 19 */ 20 21 #include "qemu/osdep.h" 22 #include "io/channel-watch.h" 23 24 typedef struct QIOChannelFDSource QIOChannelFDSource; 25 struct QIOChannelFDSource { 26 GSource parent; 27 GPollFD fd; 28 QIOChannel *ioc; 29 GIOCondition condition; 30 }; 31 32 33 typedef struct QIOChannelFDPairSource QIOChannelFDPairSource; 34 struct QIOChannelFDPairSource { 35 GSource parent; 36 GPollFD fdread; 37 GPollFD fdwrite; 38 QIOChannel *ioc; 39 GIOCondition condition; 40 }; 41 42 43 static gboolean 44 qio_channel_fd_source_prepare(GSource *source G_GNUC_UNUSED, 45 gint *timeout) 46 { 47 *timeout = -1; 48 49 return FALSE; 50 } 51 52 53 static gboolean 54 qio_channel_fd_source_check(GSource *source) 55 { 56 QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 57 58 return ssource->fd.revents & ssource->condition; 59 } 60 61 62 static gboolean 63 qio_channel_fd_source_dispatch(GSource *source, 64 GSourceFunc callback, 65 gpointer user_data) 66 { 67 QIOChannelFunc func = (QIOChannelFunc)callback; 68 QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 69 70 return (*func)(ssource->ioc, 71 ssource->fd.revents & ssource->condition, 72 user_data); 73 } 74 75 76 static void 77 qio_channel_fd_source_finalize(GSource *source) 78 { 79 QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 80 81 object_unref(OBJECT(ssource->ioc)); 82 } 83 84 85 static gboolean 86 qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED, 87 gint *timeout) 88 { 89 *timeout = -1; 90 91 return FALSE; 92 } 93 94 95 static gboolean 96 qio_channel_fd_pair_source_check(GSource *source) 97 { 98 QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 99 GIOCondition poll_condition = ssource->fdread.revents | 100 ssource->fdwrite.revents; 101 102 return poll_condition & ssource->condition; 103 } 104 105 106 static gboolean 107 qio_channel_fd_pair_source_dispatch(GSource *source, 108 GSourceFunc callback, 109 gpointer user_data) 110 { 111 QIOChannelFunc func = (QIOChannelFunc)callback; 112 QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 113 GIOCondition poll_condition = ssource->fdread.revents | 114 ssource->fdwrite.revents; 115 116 return (*func)(ssource->ioc, 117 poll_condition & ssource->condition, 118 user_data); 119 } 120 121 122 static void 123 qio_channel_fd_pair_source_finalize(GSource *source) 124 { 125 QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 126 127 object_unref(OBJECT(ssource->ioc)); 128 } 129 130 131 GSourceFuncs qio_channel_fd_source_funcs = { 132 qio_channel_fd_source_prepare, 133 qio_channel_fd_source_check, 134 qio_channel_fd_source_dispatch, 135 qio_channel_fd_source_finalize 136 }; 137 138 139 GSourceFuncs qio_channel_fd_pair_source_funcs = { 140 qio_channel_fd_pair_source_prepare, 141 qio_channel_fd_pair_source_check, 142 qio_channel_fd_pair_source_dispatch, 143 qio_channel_fd_pair_source_finalize 144 }; 145 146 147 GSource *qio_channel_create_fd_watch(QIOChannel *ioc, 148 int fd, 149 GIOCondition condition) 150 { 151 GSource *source; 152 QIOChannelFDSource *ssource; 153 154 source = g_source_new(&qio_channel_fd_source_funcs, 155 sizeof(QIOChannelFDSource)); 156 ssource = (QIOChannelFDSource *)source; 157 158 ssource->ioc = ioc; 159 object_ref(OBJECT(ioc)); 160 161 ssource->condition = condition; 162 163 ssource->fd.fd = fd; 164 ssource->fd.events = condition; 165 166 g_source_add_poll(source, &ssource->fd); 167 168 return source; 169 } 170 171 172 GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc, 173 int fdread, 174 int fdwrite, 175 GIOCondition condition) 176 { 177 GSource *source; 178 QIOChannelFDPairSource *ssource; 179 180 source = g_source_new(&qio_channel_fd_pair_source_funcs, 181 sizeof(QIOChannelFDPairSource)); 182 ssource = (QIOChannelFDPairSource *)source; 183 184 ssource->ioc = ioc; 185 object_ref(OBJECT(ioc)); 186 187 ssource->condition = condition; 188 189 ssource->fdread.fd = fdread; 190 ssource->fdread.events = condition & G_IO_IN; 191 192 ssource->fdwrite.fd = fdwrite; 193 ssource->fdwrite.events = condition & G_IO_OUT; 194 195 g_source_add_poll(source, &ssource->fdread); 196 g_source_add_poll(source, &ssource->fdwrite); 197 198 return source; 199 } 200