Revision 02981419

b/Makefile.objs
98 98
common-obj-y += qemu-char.o savevm.o #aio.o
99 99
common-obj-y += msmouse.o ps2.o
100 100
common-obj-y += qdev.o qdev-properties.o
101
common-obj-y += block-migration.o
101
common-obj-y += block-migration.o iohandler.o
102 102
common-obj-y += pflib.o
103 103
common-obj-y += bitmap.o bitops.o
104 104

  
b/iohandler.c
1
/*
2
 * QEMU System Emulator - managing I/O handler
3
 *
4
 * Copyright (c) 2003-2008 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24

  
25
#include "config-host.h"
26
#include "qemu-common.h"
27
#include "qemu-char.h"
28
#include "qemu-queue.h"
29

  
30
typedef struct IOHandlerRecord {
31
    int fd;
32
    IOCanReadHandler *fd_read_poll;
33
    IOHandler *fd_read;
34
    IOHandler *fd_write;
35
    int deleted;
36
    void *opaque;
37
    QLIST_ENTRY(IOHandlerRecord) next;
38
} IOHandlerRecord;
39

  
40
static QLIST_HEAD(, IOHandlerRecord) io_handlers =
41
    QLIST_HEAD_INITIALIZER(io_handlers);
42

  
43

  
44
/* XXX: fd_read_poll should be suppressed, but an API change is
45
   necessary in the character devices to suppress fd_can_read(). */
46
int qemu_set_fd_handler2(int fd,
47
                         IOCanReadHandler *fd_read_poll,
48
                         IOHandler *fd_read,
49
                         IOHandler *fd_write,
50
                         void *opaque)
51
{
52
    IOHandlerRecord *ioh;
53

  
54
    if (!fd_read && !fd_write) {
55
        QLIST_FOREACH(ioh, &io_handlers, next) {
56
            if (ioh->fd == fd) {
57
                ioh->deleted = 1;
58
                break;
59
            }
60
        }
61
    } else {
62
        QLIST_FOREACH(ioh, &io_handlers, next) {
63
            if (ioh->fd == fd)
64
                goto found;
65
        }
66
        ioh = qemu_mallocz(sizeof(IOHandlerRecord));
67
        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
68
    found:
69
        ioh->fd = fd;
70
        ioh->fd_read_poll = fd_read_poll;
71
        ioh->fd_read = fd_read;
72
        ioh->fd_write = fd_write;
73
        ioh->opaque = opaque;
74
        ioh->deleted = 0;
75
    }
76
    return 0;
77
}
78

  
79
int qemu_set_fd_handler(int fd,
80
                        IOHandler *fd_read,
81
                        IOHandler *fd_write,
82
                        void *opaque)
83
{
84
    return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
85
}
86

  
87
void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds)
88
{
89
    IOHandlerRecord *ioh;
90

  
91
    QLIST_FOREACH(ioh, &io_handlers, next) {
92
        if (ioh->deleted)
93
            continue;
94
        if (ioh->fd_read &&
95
            (!ioh->fd_read_poll ||
96
             ioh->fd_read_poll(ioh->opaque) != 0)) {
97
            FD_SET(ioh->fd, readfds);
98
            if (ioh->fd > *pnfds)
99
                *pnfds = ioh->fd;
100
        }
101
        if (ioh->fd_write) {
102
            FD_SET(ioh->fd, writefds);
103
            if (ioh->fd > *pnfds)
104
                *pnfds = ioh->fd;
105
        }
106
    }
107
}
108

  
109
void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int ret)
110
{
111
    if (ret > 0) {
112
        IOHandlerRecord *pioh, *ioh;
113

  
114
        QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
115
            if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, readfds)) {
116
                ioh->fd_read(ioh->opaque);
117
            }
118
            if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, writefds)) {
119
                ioh->fd_write(ioh->opaque);
120
            }
121

  
122
            /* Do this last in case read/write handlers marked it for deletion */
123
            if (ioh->deleted) {
124
                QLIST_REMOVE(ioh, next);
125
                qemu_free(ioh);
126
            }
127
        }
128
    }
129
}
b/qemu-common.h
227 227
typedef int IOCanReadHandler(void *opaque);
228 228
typedef void IOHandler(void *opaque);
229 229

  
230
void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds);
231
void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc);
232

  
230 233
struct ParallelIOArg {
231 234
    void *buffer;
232 235
    int count;
b/vl.c
1023 1023
}
1024 1024

  
1025 1025
/***********************************************************/
1026
/* I/O handling */
1027

  
1028
typedef struct IOHandlerRecord {
1029
    int fd;
1030
    IOCanReadHandler *fd_read_poll;
1031
    IOHandler *fd_read;
1032
    IOHandler *fd_write;
1033
    int deleted;
1034
    void *opaque;
1035
    /* temporary data */
1036
    struct pollfd *ufd;
1037
    QLIST_ENTRY(IOHandlerRecord) next;
1038
} IOHandlerRecord;
1039

  
1040
static QLIST_HEAD(, IOHandlerRecord) io_handlers =
1041
    QLIST_HEAD_INITIALIZER(io_handlers);
1042

  
1043

  
1044
/* XXX: fd_read_poll should be suppressed, but an API change is
1045
   necessary in the character devices to suppress fd_can_read(). */
1046
int qemu_set_fd_handler2(int fd,
1047
                         IOCanReadHandler *fd_read_poll,
1048
                         IOHandler *fd_read,
1049
                         IOHandler *fd_write,
1050
                         void *opaque)
1051
{
1052
    IOHandlerRecord *ioh;
1053

  
1054
    if (!fd_read && !fd_write) {
1055
        QLIST_FOREACH(ioh, &io_handlers, next) {
1056
            if (ioh->fd == fd) {
1057
                ioh->deleted = 1;
1058
                break;
1059
            }
1060
        }
1061
    } else {
1062
        QLIST_FOREACH(ioh, &io_handlers, next) {
1063
            if (ioh->fd == fd)
1064
                goto found;
1065
        }
1066
        ioh = qemu_mallocz(sizeof(IOHandlerRecord));
1067
        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
1068
    found:
1069
        ioh->fd = fd;
1070
        ioh->fd_read_poll = fd_read_poll;
1071
        ioh->fd_read = fd_read;
1072
        ioh->fd_write = fd_write;
1073
        ioh->opaque = opaque;
1074
        ioh->deleted = 0;
1075
    }
1076
    return 0;
1077
}
1078

  
1079
int qemu_set_fd_handler(int fd,
1080
                        IOHandler *fd_read,
1081
                        IOHandler *fd_write,
1082
                        void *opaque)
1083
{
1084
    return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
1085
}
1086

  
1087
/***********************************************************/
1088 1026
/* machine registration */
1089 1027

  
1090 1028
static QEMUMachine *first_machine = NULL;
......
1343 1281

  
1344 1282
void main_loop_wait(int nonblocking)
1345 1283
{
1346
    IOHandlerRecord *ioh;
1347 1284
    fd_set rfds, wfds, xfds;
1348 1285
    int ret, nfds;
1349 1286
    struct timeval tv;
......
1358 1295

  
1359 1296
    os_host_main_loop_wait(&timeout);
1360 1297

  
1298
    tv.tv_sec = timeout / 1000;
1299
    tv.tv_usec = (timeout % 1000) * 1000;
1300

  
1361 1301
    /* poll any events */
1362 1302
    /* XXX: separate device handlers from system ones */
1363 1303
    nfds = -1;
1364 1304
    FD_ZERO(&rfds);
1365 1305
    FD_ZERO(&wfds);
1366 1306
    FD_ZERO(&xfds);
1367
    QLIST_FOREACH(ioh, &io_handlers, next) {
1368
        if (ioh->deleted)
1369
            continue;
1370
        if (ioh->fd_read &&
1371
            (!ioh->fd_read_poll ||
1372
             ioh->fd_read_poll(ioh->opaque) != 0)) {
1373
            FD_SET(ioh->fd, &rfds);
1374
            if (ioh->fd > nfds)
1375
                nfds = ioh->fd;
1376
        }
1377
        if (ioh->fd_write) {
1378
            FD_SET(ioh->fd, &wfds);
1379
            if (ioh->fd > nfds)
1380
                nfds = ioh->fd;
1381
        }
1382
    }
1383

  
1384
    tv.tv_sec = timeout / 1000;
1385
    tv.tv_usec = (timeout % 1000) * 1000;
1386

  
1307
    qemu_iohandler_fill(&nfds, &rfds, &wfds, &xfds);
1387 1308
    slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
1388 1309

  
1389 1310
    qemu_mutex_unlock_iothread();
1390 1311
    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
1391 1312
    qemu_mutex_lock_iothread();
1392
    if (ret > 0) {
1393
        IOHandlerRecord *pioh;
1394

  
1395
        QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
1396
            if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
1397
                ioh->fd_read(ioh->opaque);
1398
            }
1399
            if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
1400
                ioh->fd_write(ioh->opaque);
1401
            }
1402

  
1403
            /* Do this last in case read/write handlers marked it for deletion */
1404
            if (ioh->deleted) {
1405
                QLIST_REMOVE(ioh, next);
1406
                qemu_free(ioh);
1407
            }
1408
        }
1409
    }
1410 1313

  
1314
    qemu_iohandler_poll(&rfds, &wfds, &xfds, ret);
1411 1315
    slirp_select_poll(&rfds, &wfds, &xfds, (ret < 0));
1412 1316

  
1413 1317
    qemu_run_all_timers();

Also available in: Unified diff