qemu

Форк
0
/
channel-watch.c 
347 строк · 8.6 Кб
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.1 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
#ifdef CONFIG_WIN32
34
typedef struct QIOChannelSocketSource QIOChannelSocketSource;
35
struct QIOChannelSocketSource {
36
    GSource parent;
37
    GPollFD fd;
38
    QIOChannel *ioc;
39
    SOCKET socket;
40
    int revents;
41
    GIOCondition condition;
42
};
43

44
#endif
45

46

47
typedef struct QIOChannelFDPairSource QIOChannelFDPairSource;
48
struct QIOChannelFDPairSource {
49
    GSource parent;
50
    GPollFD fdread;
51
    GPollFD fdwrite;
52
    QIOChannel *ioc;
53
    GIOCondition condition;
54
};
55

56

57
static gboolean
58
qio_channel_fd_source_prepare(GSource *source G_GNUC_UNUSED,
59
                              gint *timeout)
60
{
61
    *timeout = -1;
62

63
    return FALSE;
64
}
65

66

67
static gboolean
68
qio_channel_fd_source_check(GSource *source)
69
{
70
    QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
71

72
    return ssource->fd.revents & ssource->condition;
73
}
74

75

76
static gboolean
77
qio_channel_fd_source_dispatch(GSource *source,
78
                               GSourceFunc callback,
79
                               gpointer user_data)
80
{
81
    QIOChannelFunc func = (QIOChannelFunc)callback;
82
    QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
83

84
    return (*func)(ssource->ioc,
85
                   ssource->fd.revents & ssource->condition,
86
                   user_data);
87
}
88

89

90
static void
91
qio_channel_fd_source_finalize(GSource *source)
92
{
93
    QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
94

95
    object_unref(OBJECT(ssource->ioc));
96
}
97

98

99
#ifdef CONFIG_WIN32
100
static gboolean
101
qio_channel_socket_source_prepare(GSource *source G_GNUC_UNUSED,
102
                                  gint *timeout)
103
{
104
    *timeout = -1;
105

106
    return FALSE;
107
}
108

109

110
/*
111
 * NB, this impl only works when the socket is in non-blocking
112
 * mode on Win32
113
 */
114
static gboolean
115
qio_channel_socket_source_check(GSource *source)
116
{
117
    static struct timeval tv0;
118
    QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
119
    fd_set rfds, wfds, xfds;
120

121
    if (!ssource->condition) {
122
        return 0;
123
    }
124

125
    FD_ZERO(&rfds);
126
    FD_ZERO(&wfds);
127
    FD_ZERO(&xfds);
128
    if (ssource->condition & G_IO_IN) {
129
        FD_SET(ssource->socket, &rfds);
130
    }
131
    if (ssource->condition & G_IO_OUT) {
132
        FD_SET(ssource->socket, &wfds);
133
    }
134
    if (ssource->condition & G_IO_PRI) {
135
        FD_SET(ssource->socket, &xfds);
136
    }
137
    ssource->revents = 0;
138
    if (select(0, &rfds, &wfds, &xfds, &tv0) == 0) {
139
        return 0;
140
    }
141

142
    if (FD_ISSET(ssource->socket, &rfds)) {
143
        ssource->revents |= G_IO_IN;
144
    }
145
    if (FD_ISSET(ssource->socket, &wfds)) {
146
        ssource->revents |= G_IO_OUT;
147
    }
148
    if (FD_ISSET(ssource->socket, &xfds)) {
149
        ssource->revents |= G_IO_PRI;
150
    }
151

152
    return ssource->revents;
153
}
154

155

156
static gboolean
157
qio_channel_socket_source_dispatch(GSource *source,
158
                                   GSourceFunc callback,
159
                                   gpointer user_data)
160
{
161
    QIOChannelFunc func = (QIOChannelFunc)callback;
162
    QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
163

164
    return (*func)(ssource->ioc, ssource->revents, user_data);
165
}
166

167

168
static void
169
qio_channel_socket_source_finalize(GSource *source)
170
{
171
    QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
172

173
    object_unref(OBJECT(ssource->ioc));
174
}
175

176

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
182
};
183
#endif
184

185

186
static gboolean
187
qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED,
188
                                   gint *timeout)
189
{
190
    *timeout = -1;
191

192
    return FALSE;
193
}
194

195

196
static gboolean
197
qio_channel_fd_pair_source_check(GSource *source)
198
{
199
    QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
200
    GIOCondition poll_condition = ssource->fdread.revents |
201
        ssource->fdwrite.revents;
202

203
    return poll_condition & ssource->condition;
204
}
205

206

207
static gboolean
208
qio_channel_fd_pair_source_dispatch(GSource *source,
209
                                    GSourceFunc callback,
210
                                    gpointer user_data)
211
{
212
    QIOChannelFunc func = (QIOChannelFunc)callback;
213
    QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
214
    GIOCondition poll_condition = ssource->fdread.revents |
215
        ssource->fdwrite.revents;
216

217
    return (*func)(ssource->ioc,
218
                   poll_condition & ssource->condition,
219
                   user_data);
220
}
221

222

223
static void
224
qio_channel_fd_pair_source_finalize(GSource *source)
225
{
226
    QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
227

228
    object_unref(OBJECT(ssource->ioc));
229
}
230

231

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
237
};
238

239

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
245
};
246

247

248
GSource *qio_channel_create_fd_watch(QIOChannel *ioc,
249
                                     int fd,
250
                                     GIOCondition condition)
251
{
252
    GSource *source;
253
    QIOChannelFDSource *ssource;
254

255
    source = g_source_new(&qio_channel_fd_source_funcs,
256
                          sizeof(QIOChannelFDSource));
257
    ssource = (QIOChannelFDSource *)source;
258

259
    ssource->ioc = ioc;
260
    object_ref(OBJECT(ioc));
261

262
    ssource->condition = condition;
263

264
#ifdef CONFIG_WIN32
265
    ssource->fd.fd = (gint64)_get_osfhandle(fd);
266
#else
267
    ssource->fd.fd = fd;
268
#endif
269
    ssource->fd.events = condition;
270

271
    g_source_add_poll(source, &ssource->fd);
272

273
    return source;
274
}
275

276
#ifdef CONFIG_WIN32
277
GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
278
                                         int sockfd,
279
                                         GIOCondition condition)
280
{
281
    GSource *source;
282
    QIOChannelSocketSource *ssource;
283

284
    qemu_socket_select(sockfd, ioc->event,
285
                       FD_READ | FD_ACCEPT | FD_CLOSE |
286
                       FD_CONNECT | FD_WRITE | FD_OOB, NULL);
287

288
    source = g_source_new(&qio_channel_socket_source_funcs,
289
                          sizeof(QIOChannelSocketSource));
290
    ssource = (QIOChannelSocketSource *)source;
291

292
    ssource->ioc = ioc;
293
    object_ref(OBJECT(ioc));
294

295
    ssource->condition = condition;
296
    ssource->socket = _get_osfhandle(sockfd);
297
    ssource->revents = 0;
298

299
    ssource->fd.fd = (gintptr)ioc->event;
300
    ssource->fd.events = G_IO_IN;
301

302
    g_source_add_poll(source, &ssource->fd);
303

304
    return source;
305
}
306
#else
307
GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
308
                                         int socket,
309
                                         GIOCondition condition)
310
{
311
    return qio_channel_create_fd_watch(ioc, socket, condition);
312
}
313
#endif
314

315
GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc,
316
                                          int fdread,
317
                                          int fdwrite,
318
                                          GIOCondition condition)
319
{
320
    GSource *source;
321
    QIOChannelFDPairSource *ssource;
322

323
    source = g_source_new(&qio_channel_fd_pair_source_funcs,
324
                          sizeof(QIOChannelFDPairSource));
325
    ssource = (QIOChannelFDPairSource *)source;
326

327
    ssource->ioc = ioc;
328
    object_ref(OBJECT(ioc));
329

330
    ssource->condition = condition;
331

332
#ifdef CONFIG_WIN32
333
    ssource->fdread.fd = (gint64)_get_osfhandle(fdread);
334
    ssource->fdwrite.fd = (gint64)_get_osfhandle(fdwrite);
335
#else
336
    ssource->fdread.fd = fdread;
337
    ssource->fdwrite.fd = fdwrite;
338
#endif
339

340
    ssource->fdread.events = condition & G_IO_IN;
341
    ssource->fdwrite.events = condition & G_IO_OUT;
342

343
    g_source_add_poll(source, &ssource->fdread);
344
    g_source_add_poll(source, &ssource->fdwrite);
345

346
    return source;
347
}
348

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.