root / iohandler.c @ a5c95808
History | View | Annotate | Download (5.5 kB)
1 | 02981419 | Paolo Bonzini | /*
|
---|---|---|---|
2 | 02981419 | Paolo Bonzini | * QEMU System Emulator - managing I/O handler
|
3 | 02981419 | Paolo Bonzini | *
|
4 | 02981419 | Paolo Bonzini | * Copyright (c) 2003-2008 Fabrice Bellard
|
5 | 02981419 | Paolo Bonzini | *
|
6 | 02981419 | Paolo Bonzini | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 02981419 | Paolo Bonzini | * of this software and associated documentation files (the "Software"), to deal
|
8 | 02981419 | Paolo Bonzini | * in the Software without restriction, including without limitation the rights
|
9 | 02981419 | Paolo Bonzini | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 02981419 | Paolo Bonzini | * copies of the Software, and to permit persons to whom the Software is
|
11 | 02981419 | Paolo Bonzini | * furnished to do so, subject to the following conditions:
|
12 | 02981419 | Paolo Bonzini | *
|
13 | 02981419 | Paolo Bonzini | * The above copyright notice and this permission notice shall be included in
|
14 | 02981419 | Paolo Bonzini | * all copies or substantial portions of the Software.
|
15 | 02981419 | Paolo Bonzini | *
|
16 | 02981419 | Paolo Bonzini | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 02981419 | Paolo Bonzini | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 02981419 | Paolo Bonzini | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 02981419 | Paolo Bonzini | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 02981419 | Paolo Bonzini | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 02981419 | Paolo Bonzini | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 02981419 | Paolo Bonzini | * THE SOFTWARE.
|
23 | 02981419 | Paolo Bonzini | */
|
24 | 02981419 | Paolo Bonzini | |
25 | 02981419 | Paolo Bonzini | #include "config-host.h" |
26 | 02981419 | Paolo Bonzini | #include "qemu-common.h" |
27 | 1de7afc9 | Paolo Bonzini | #include "qemu/queue.h" |
28 | 737e150e | Paolo Bonzini | #include "block/aio.h" |
29 | 1de7afc9 | Paolo Bonzini | #include "qemu/main-loop.h" |
30 | 02981419 | Paolo Bonzini | |
31 | 4d54ec78 | Paolo Bonzini | #ifndef _WIN32
|
32 | 4d54ec78 | Paolo Bonzini | #include <sys/wait.h> |
33 | 4d54ec78 | Paolo Bonzini | #endif
|
34 | 4d54ec78 | Paolo Bonzini | |
35 | 02981419 | Paolo Bonzini | typedef struct IOHandlerRecord { |
36 | 02981419 | Paolo Bonzini | IOCanReadHandler *fd_read_poll; |
37 | 02981419 | Paolo Bonzini | IOHandler *fd_read; |
38 | 02981419 | Paolo Bonzini | IOHandler *fd_write; |
39 | 02981419 | Paolo Bonzini | void *opaque;
|
40 | 02981419 | Paolo Bonzini | QLIST_ENTRY(IOHandlerRecord) next; |
41 | c97feed1 | Stefan Weil | int fd;
|
42 | c97feed1 | Stefan Weil | bool deleted;
|
43 | 02981419 | Paolo Bonzini | } IOHandlerRecord; |
44 | 02981419 | Paolo Bonzini | |
45 | 02981419 | Paolo Bonzini | static QLIST_HEAD(, IOHandlerRecord) io_handlers =
|
46 | 02981419 | Paolo Bonzini | QLIST_HEAD_INITIALIZER(io_handlers); |
47 | 02981419 | Paolo Bonzini | |
48 | 02981419 | Paolo Bonzini | |
49 | 02981419 | Paolo Bonzini | /* XXX: fd_read_poll should be suppressed, but an API change is
|
50 | 02981419 | Paolo Bonzini | necessary in the character devices to suppress fd_can_read(). */
|
51 | 02981419 | Paolo Bonzini | int qemu_set_fd_handler2(int fd, |
52 | 02981419 | Paolo Bonzini | IOCanReadHandler *fd_read_poll, |
53 | 02981419 | Paolo Bonzini | IOHandler *fd_read, |
54 | 02981419 | Paolo Bonzini | IOHandler *fd_write, |
55 | 02981419 | Paolo Bonzini | void *opaque)
|
56 | 02981419 | Paolo Bonzini | { |
57 | 02981419 | Paolo Bonzini | IOHandlerRecord *ioh; |
58 | 02981419 | Paolo Bonzini | |
59 | bbdd2ad0 | David Gibson | assert(fd >= 0);
|
60 | bbdd2ad0 | David Gibson | |
61 | 02981419 | Paolo Bonzini | if (!fd_read && !fd_write) {
|
62 | 02981419 | Paolo Bonzini | QLIST_FOREACH(ioh, &io_handlers, next) { |
63 | 02981419 | Paolo Bonzini | if (ioh->fd == fd) {
|
64 | 02981419 | Paolo Bonzini | ioh->deleted = 1;
|
65 | 02981419 | Paolo Bonzini | break;
|
66 | 02981419 | Paolo Bonzini | } |
67 | 02981419 | Paolo Bonzini | } |
68 | 02981419 | Paolo Bonzini | } else {
|
69 | 02981419 | Paolo Bonzini | QLIST_FOREACH(ioh, &io_handlers, next) { |
70 | 02981419 | Paolo Bonzini | if (ioh->fd == fd)
|
71 | 02981419 | Paolo Bonzini | goto found;
|
72 | 02981419 | Paolo Bonzini | } |
73 | 7267c094 | Anthony Liguori | ioh = g_malloc0(sizeof(IOHandlerRecord));
|
74 | 02981419 | Paolo Bonzini | QLIST_INSERT_HEAD(&io_handlers, ioh, next); |
75 | 02981419 | Paolo Bonzini | found:
|
76 | 02981419 | Paolo Bonzini | ioh->fd = fd; |
77 | 02981419 | Paolo Bonzini | ioh->fd_read_poll = fd_read_poll; |
78 | 02981419 | Paolo Bonzini | ioh->fd_read = fd_read; |
79 | 02981419 | Paolo Bonzini | ioh->fd_write = fd_write; |
80 | 02981419 | Paolo Bonzini | ioh->opaque = opaque; |
81 | 02981419 | Paolo Bonzini | ioh->deleted = 0;
|
82 | 55ce75fa | Alexey Kardashevskiy | qemu_notify_event(); |
83 | 02981419 | Paolo Bonzini | } |
84 | 02981419 | Paolo Bonzini | return 0; |
85 | 02981419 | Paolo Bonzini | } |
86 | 02981419 | Paolo Bonzini | |
87 | 02981419 | Paolo Bonzini | int qemu_set_fd_handler(int fd, |
88 | 02981419 | Paolo Bonzini | IOHandler *fd_read, |
89 | 02981419 | Paolo Bonzini | IOHandler *fd_write, |
90 | 02981419 | Paolo Bonzini | void *opaque)
|
91 | 02981419 | Paolo Bonzini | { |
92 | be08e65e | Paolo Bonzini | return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); |
93 | 02981419 | Paolo Bonzini | } |
94 | 02981419 | Paolo Bonzini | |
95 | 02981419 | Paolo Bonzini | void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) |
96 | 02981419 | Paolo Bonzini | { |
97 | 02981419 | Paolo Bonzini | IOHandlerRecord *ioh; |
98 | 02981419 | Paolo Bonzini | |
99 | 02981419 | Paolo Bonzini | QLIST_FOREACH(ioh, &io_handlers, next) { |
100 | 02981419 | Paolo Bonzini | if (ioh->deleted)
|
101 | 02981419 | Paolo Bonzini | continue;
|
102 | 02981419 | Paolo Bonzini | if (ioh->fd_read &&
|
103 | 02981419 | Paolo Bonzini | (!ioh->fd_read_poll || |
104 | 02981419 | Paolo Bonzini | ioh->fd_read_poll(ioh->opaque) != 0)) {
|
105 | 02981419 | Paolo Bonzini | FD_SET(ioh->fd, readfds); |
106 | 02981419 | Paolo Bonzini | if (ioh->fd > *pnfds)
|
107 | 02981419 | Paolo Bonzini | *pnfds = ioh->fd; |
108 | 02981419 | Paolo Bonzini | } |
109 | 02981419 | Paolo Bonzini | if (ioh->fd_write) {
|
110 | 02981419 | Paolo Bonzini | FD_SET(ioh->fd, writefds); |
111 | 02981419 | Paolo Bonzini | if (ioh->fd > *pnfds)
|
112 | 02981419 | Paolo Bonzini | *pnfds = ioh->fd; |
113 | 02981419 | Paolo Bonzini | } |
114 | 02981419 | Paolo Bonzini | } |
115 | 02981419 | Paolo Bonzini | } |
116 | 02981419 | Paolo Bonzini | |
117 | 02981419 | Paolo Bonzini | void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int ret) |
118 | 02981419 | Paolo Bonzini | { |
119 | 02981419 | Paolo Bonzini | if (ret > 0) { |
120 | 02981419 | Paolo Bonzini | IOHandlerRecord *pioh, *ioh; |
121 | 02981419 | Paolo Bonzini | |
122 | 02981419 | Paolo Bonzini | QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { |
123 | 02981419 | Paolo Bonzini | if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, readfds)) {
|
124 | 02981419 | Paolo Bonzini | ioh->fd_read(ioh->opaque); |
125 | 02981419 | Paolo Bonzini | } |
126 | 02981419 | Paolo Bonzini | if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, writefds)) {
|
127 | 02981419 | Paolo Bonzini | ioh->fd_write(ioh->opaque); |
128 | 02981419 | Paolo Bonzini | } |
129 | 02981419 | Paolo Bonzini | |
130 | 02981419 | Paolo Bonzini | /* Do this last in case read/write handlers marked it for deletion */
|
131 | 02981419 | Paolo Bonzini | if (ioh->deleted) {
|
132 | 02981419 | Paolo Bonzini | QLIST_REMOVE(ioh, next); |
133 | 7267c094 | Anthony Liguori | g_free(ioh); |
134 | 02981419 | Paolo Bonzini | } |
135 | 02981419 | Paolo Bonzini | } |
136 | 02981419 | Paolo Bonzini | } |
137 | 02981419 | Paolo Bonzini | } |
138 | 4d54ec78 | Paolo Bonzini | |
139 | 4d54ec78 | Paolo Bonzini | /* reaping of zombies. right now we're not passing the status to
|
140 | 4d54ec78 | Paolo Bonzini | anyone, but it would be possible to add a callback. */
|
141 | 4d54ec78 | Paolo Bonzini | #ifndef _WIN32
|
142 | 4d54ec78 | Paolo Bonzini | typedef struct ChildProcessRecord { |
143 | 4d54ec78 | Paolo Bonzini | int pid;
|
144 | 4d54ec78 | Paolo Bonzini | QLIST_ENTRY(ChildProcessRecord) next; |
145 | 4d54ec78 | Paolo Bonzini | } ChildProcessRecord; |
146 | 4d54ec78 | Paolo Bonzini | |
147 | 4d54ec78 | Paolo Bonzini | static QLIST_HEAD(, ChildProcessRecord) child_watches =
|
148 | 4d54ec78 | Paolo Bonzini | QLIST_HEAD_INITIALIZER(child_watches); |
149 | 4d54ec78 | Paolo Bonzini | |
150 | 4d54ec78 | Paolo Bonzini | static QEMUBH *sigchld_bh;
|
151 | 4d54ec78 | Paolo Bonzini | |
152 | 4d54ec78 | Paolo Bonzini | static void sigchld_handler(int signal) |
153 | 4d54ec78 | Paolo Bonzini | { |
154 | 4d54ec78 | Paolo Bonzini | qemu_bh_schedule(sigchld_bh); |
155 | 4d54ec78 | Paolo Bonzini | } |
156 | 4d54ec78 | Paolo Bonzini | |
157 | 4d54ec78 | Paolo Bonzini | static void sigchld_bh_handler(void *opaque) |
158 | 4d54ec78 | Paolo Bonzini | { |
159 | 4d54ec78 | Paolo Bonzini | ChildProcessRecord *rec, *next; |
160 | 4d54ec78 | Paolo Bonzini | |
161 | 4d54ec78 | Paolo Bonzini | QLIST_FOREACH_SAFE(rec, &child_watches, next, next) { |
162 | 4d54ec78 | Paolo Bonzini | if (waitpid(rec->pid, NULL, WNOHANG) == rec->pid) { |
163 | 4d54ec78 | Paolo Bonzini | QLIST_REMOVE(rec, next); |
164 | 7267c094 | Anthony Liguori | g_free(rec); |
165 | 4d54ec78 | Paolo Bonzini | } |
166 | 4d54ec78 | Paolo Bonzini | } |
167 | 4d54ec78 | Paolo Bonzini | } |
168 | 4d54ec78 | Paolo Bonzini | |
169 | 4d54ec78 | Paolo Bonzini | static void qemu_init_child_watch(void) |
170 | 4d54ec78 | Paolo Bonzini | { |
171 | 4d54ec78 | Paolo Bonzini | struct sigaction act;
|
172 | 4d54ec78 | Paolo Bonzini | sigchld_bh = qemu_bh_new(sigchld_bh_handler, NULL);
|
173 | 4d54ec78 | Paolo Bonzini | |
174 | 4d54ec78 | Paolo Bonzini | act.sa_handler = sigchld_handler; |
175 | 4d54ec78 | Paolo Bonzini | act.sa_flags = SA_NOCLDSTOP; |
176 | 4d54ec78 | Paolo Bonzini | sigaction(SIGCHLD, &act, NULL);
|
177 | 4d54ec78 | Paolo Bonzini | } |
178 | 4d54ec78 | Paolo Bonzini | |
179 | 4d54ec78 | Paolo Bonzini | int qemu_add_child_watch(pid_t pid)
|
180 | 4d54ec78 | Paolo Bonzini | { |
181 | 4d54ec78 | Paolo Bonzini | ChildProcessRecord *rec; |
182 | 4d54ec78 | Paolo Bonzini | |
183 | 4d54ec78 | Paolo Bonzini | if (!sigchld_bh) {
|
184 | 4d54ec78 | Paolo Bonzini | qemu_init_child_watch(); |
185 | 4d54ec78 | Paolo Bonzini | } |
186 | 4d54ec78 | Paolo Bonzini | |
187 | 4d54ec78 | Paolo Bonzini | QLIST_FOREACH(rec, &child_watches, next) { |
188 | 4d54ec78 | Paolo Bonzini | if (rec->pid == pid) {
|
189 | 4d54ec78 | Paolo Bonzini | return 1; |
190 | 4d54ec78 | Paolo Bonzini | } |
191 | 4d54ec78 | Paolo Bonzini | } |
192 | 7267c094 | Anthony Liguori | rec = g_malloc0(sizeof(ChildProcessRecord));
|
193 | 4d54ec78 | Paolo Bonzini | rec->pid = pid; |
194 | 4d54ec78 | Paolo Bonzini | QLIST_INSERT_HEAD(&child_watches, rec, next); |
195 | 4d54ec78 | Paolo Bonzini | return 0; |
196 | 4d54ec78 | Paolo Bonzini | } |
197 | 4d54ec78 | Paolo Bonzini | #endif |