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