root / iohandler.c @ d92aa883
History | View | Annotate | Download (6 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 | a3e4b4a8 | Stefan Hajnoczi | int pollfds_idx;
|
43 | c97feed1 | Stefan Weil | bool deleted;
|
44 | 02981419 | Paolo Bonzini | } IOHandlerRecord; |
45 | 02981419 | Paolo Bonzini | |
46 | 02981419 | Paolo Bonzini | static QLIST_HEAD(, IOHandlerRecord) io_handlers =
|
47 | 02981419 | Paolo Bonzini | QLIST_HEAD_INITIALIZER(io_handlers); |
48 | 02981419 | Paolo Bonzini | |
49 | 02981419 | Paolo Bonzini | |
50 | 02981419 | Paolo Bonzini | /* XXX: fd_read_poll should be suppressed, but an API change is
|
51 | 02981419 | Paolo Bonzini | necessary in the character devices to suppress fd_can_read(). */
|
52 | 02981419 | Paolo Bonzini | int qemu_set_fd_handler2(int fd, |
53 | 02981419 | Paolo Bonzini | IOCanReadHandler *fd_read_poll, |
54 | 02981419 | Paolo Bonzini | IOHandler *fd_read, |
55 | 02981419 | Paolo Bonzini | IOHandler *fd_write, |
56 | 02981419 | Paolo Bonzini | void *opaque)
|
57 | 02981419 | Paolo Bonzini | { |
58 | 02981419 | Paolo Bonzini | IOHandlerRecord *ioh; |
59 | 02981419 | Paolo Bonzini | |
60 | bbdd2ad0 | David Gibson | assert(fd >= 0);
|
61 | bbdd2ad0 | David Gibson | |
62 | 02981419 | Paolo Bonzini | if (!fd_read && !fd_write) {
|
63 | 02981419 | Paolo Bonzini | QLIST_FOREACH(ioh, &io_handlers, next) { |
64 | 02981419 | Paolo Bonzini | if (ioh->fd == fd) {
|
65 | 02981419 | Paolo Bonzini | ioh->deleted = 1;
|
66 | 02981419 | Paolo Bonzini | break;
|
67 | 02981419 | Paolo Bonzini | } |
68 | 02981419 | Paolo Bonzini | } |
69 | 02981419 | Paolo Bonzini | } else {
|
70 | 02981419 | Paolo Bonzini | QLIST_FOREACH(ioh, &io_handlers, next) { |
71 | 02981419 | Paolo Bonzini | if (ioh->fd == fd)
|
72 | 02981419 | Paolo Bonzini | goto found;
|
73 | 02981419 | Paolo Bonzini | } |
74 | 7267c094 | Anthony Liguori | ioh = g_malloc0(sizeof(IOHandlerRecord));
|
75 | 02981419 | Paolo Bonzini | QLIST_INSERT_HEAD(&io_handlers, ioh, next); |
76 | 02981419 | Paolo Bonzini | found:
|
77 | 02981419 | Paolo Bonzini | ioh->fd = fd; |
78 | 02981419 | Paolo Bonzini | ioh->fd_read_poll = fd_read_poll; |
79 | 02981419 | Paolo Bonzini | ioh->fd_read = fd_read; |
80 | 02981419 | Paolo Bonzini | ioh->fd_write = fd_write; |
81 | 02981419 | Paolo Bonzini | ioh->opaque = opaque; |
82 | a3e4b4a8 | Stefan Hajnoczi | ioh->pollfds_idx = -1;
|
83 | 02981419 | Paolo Bonzini | ioh->deleted = 0;
|
84 | 55ce75fa | Alexey Kardashevskiy | qemu_notify_event(); |
85 | 02981419 | Paolo Bonzini | } |
86 | 02981419 | Paolo Bonzini | return 0; |
87 | 02981419 | Paolo Bonzini | } |
88 | 02981419 | Paolo Bonzini | |
89 | 02981419 | Paolo Bonzini | int qemu_set_fd_handler(int fd, |
90 | 02981419 | Paolo Bonzini | IOHandler *fd_read, |
91 | 02981419 | Paolo Bonzini | IOHandler *fd_write, |
92 | 02981419 | Paolo Bonzini | void *opaque)
|
93 | 02981419 | Paolo Bonzini | { |
94 | be08e65e | Paolo Bonzini | return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); |
95 | 02981419 | Paolo Bonzini | } |
96 | 02981419 | Paolo Bonzini | |
97 | a3e4b4a8 | Stefan Hajnoczi | void qemu_iohandler_fill(GArray *pollfds)
|
98 | 02981419 | Paolo Bonzini | { |
99 | 02981419 | Paolo Bonzini | IOHandlerRecord *ioh; |
100 | 02981419 | Paolo Bonzini | |
101 | 02981419 | Paolo Bonzini | QLIST_FOREACH(ioh, &io_handlers, next) { |
102 | a3e4b4a8 | Stefan Hajnoczi | int events = 0; |
103 | a3e4b4a8 | Stefan Hajnoczi | |
104 | 02981419 | Paolo Bonzini | if (ioh->deleted)
|
105 | 02981419 | Paolo Bonzini | continue;
|
106 | 02981419 | Paolo Bonzini | if (ioh->fd_read &&
|
107 | 02981419 | Paolo Bonzini | (!ioh->fd_read_poll || |
108 | 02981419 | Paolo Bonzini | ioh->fd_read_poll(ioh->opaque) != 0)) {
|
109 | a3e4b4a8 | Stefan Hajnoczi | events |= G_IO_IN | G_IO_HUP | G_IO_ERR; |
110 | 02981419 | Paolo Bonzini | } |
111 | 02981419 | Paolo Bonzini | if (ioh->fd_write) {
|
112 | a3e4b4a8 | Stefan Hajnoczi | events |= G_IO_OUT | G_IO_ERR; |
113 | a3e4b4a8 | Stefan Hajnoczi | } |
114 | a3e4b4a8 | Stefan Hajnoczi | if (events) {
|
115 | a3e4b4a8 | Stefan Hajnoczi | GPollFD pfd = { |
116 | a3e4b4a8 | Stefan Hajnoczi | .fd = ioh->fd, |
117 | a3e4b4a8 | Stefan Hajnoczi | .events = events, |
118 | a3e4b4a8 | Stefan Hajnoczi | }; |
119 | a3e4b4a8 | Stefan Hajnoczi | ioh->pollfds_idx = pollfds->len; |
120 | a3e4b4a8 | Stefan Hajnoczi | g_array_append_val(pollfds, pfd); |
121 | a3e4b4a8 | Stefan Hajnoczi | } else {
|
122 | a3e4b4a8 | Stefan Hajnoczi | ioh->pollfds_idx = -1;
|
123 | 02981419 | Paolo Bonzini | } |
124 | 02981419 | Paolo Bonzini | } |
125 | 02981419 | Paolo Bonzini | } |
126 | 02981419 | Paolo Bonzini | |
127 | a3e4b4a8 | Stefan Hajnoczi | void qemu_iohandler_poll(GArray *pollfds, int ret) |
128 | 02981419 | Paolo Bonzini | { |
129 | 02981419 | Paolo Bonzini | if (ret > 0) { |
130 | 02981419 | Paolo Bonzini | IOHandlerRecord *pioh, *ioh; |
131 | 02981419 | Paolo Bonzini | |
132 | 02981419 | Paolo Bonzini | QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { |
133 | a3e4b4a8 | Stefan Hajnoczi | int revents = 0; |
134 | a3e4b4a8 | Stefan Hajnoczi | |
135 | a3e4b4a8 | Stefan Hajnoczi | if (!ioh->deleted && ioh->pollfds_idx != -1) { |
136 | a3e4b4a8 | Stefan Hajnoczi | GPollFD *pfd = &g_array_index(pollfds, GPollFD, |
137 | a3e4b4a8 | Stefan Hajnoczi | ioh->pollfds_idx); |
138 | a3e4b4a8 | Stefan Hajnoczi | revents = pfd->revents; |
139 | a3e4b4a8 | Stefan Hajnoczi | } |
140 | a3e4b4a8 | Stefan Hajnoczi | |
141 | a3e4b4a8 | Stefan Hajnoczi | if (!ioh->deleted && ioh->fd_read &&
|
142 | a3e4b4a8 | Stefan Hajnoczi | (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))) { |
143 | 02981419 | Paolo Bonzini | ioh->fd_read(ioh->opaque); |
144 | 02981419 | Paolo Bonzini | } |
145 | a3e4b4a8 | Stefan Hajnoczi | if (!ioh->deleted && ioh->fd_write &&
|
146 | a3e4b4a8 | Stefan Hajnoczi | (revents & (G_IO_OUT | G_IO_ERR))) { |
147 | 02981419 | Paolo Bonzini | ioh->fd_write(ioh->opaque); |
148 | 02981419 | Paolo Bonzini | } |
149 | 02981419 | Paolo Bonzini | |
150 | 02981419 | Paolo Bonzini | /* Do this last in case read/write handlers marked it for deletion */
|
151 | 02981419 | Paolo Bonzini | if (ioh->deleted) {
|
152 | 02981419 | Paolo Bonzini | QLIST_REMOVE(ioh, next); |
153 | 7267c094 | Anthony Liguori | g_free(ioh); |
154 | 02981419 | Paolo Bonzini | } |
155 | 02981419 | Paolo Bonzini | } |
156 | 02981419 | Paolo Bonzini | } |
157 | 02981419 | Paolo Bonzini | } |
158 | 4d54ec78 | Paolo Bonzini | |
159 | 4d54ec78 | Paolo Bonzini | /* reaping of zombies. right now we're not passing the status to
|
160 | 4d54ec78 | Paolo Bonzini | anyone, but it would be possible to add a callback. */
|
161 | 4d54ec78 | Paolo Bonzini | #ifndef _WIN32
|
162 | 4d54ec78 | Paolo Bonzini | typedef struct ChildProcessRecord { |
163 | 4d54ec78 | Paolo Bonzini | int pid;
|
164 | 4d54ec78 | Paolo Bonzini | QLIST_ENTRY(ChildProcessRecord) next; |
165 | 4d54ec78 | Paolo Bonzini | } ChildProcessRecord; |
166 | 4d54ec78 | Paolo Bonzini | |
167 | 4d54ec78 | Paolo Bonzini | static QLIST_HEAD(, ChildProcessRecord) child_watches =
|
168 | 4d54ec78 | Paolo Bonzini | QLIST_HEAD_INITIALIZER(child_watches); |
169 | 4d54ec78 | Paolo Bonzini | |
170 | 4d54ec78 | Paolo Bonzini | static QEMUBH *sigchld_bh;
|
171 | 4d54ec78 | Paolo Bonzini | |
172 | 4d54ec78 | Paolo Bonzini | static void sigchld_handler(int signal) |
173 | 4d54ec78 | Paolo Bonzini | { |
174 | 4d54ec78 | Paolo Bonzini | qemu_bh_schedule(sigchld_bh); |
175 | 4d54ec78 | Paolo Bonzini | } |
176 | 4d54ec78 | Paolo Bonzini | |
177 | 4d54ec78 | Paolo Bonzini | static void sigchld_bh_handler(void *opaque) |
178 | 4d54ec78 | Paolo Bonzini | { |
179 | 4d54ec78 | Paolo Bonzini | ChildProcessRecord *rec, *next; |
180 | 4d54ec78 | Paolo Bonzini | |
181 | 4d54ec78 | Paolo Bonzini | QLIST_FOREACH_SAFE(rec, &child_watches, next, next) { |
182 | 4d54ec78 | Paolo Bonzini | if (waitpid(rec->pid, NULL, WNOHANG) == rec->pid) { |
183 | 4d54ec78 | Paolo Bonzini | QLIST_REMOVE(rec, next); |
184 | 7267c094 | Anthony Liguori | g_free(rec); |
185 | 4d54ec78 | Paolo Bonzini | } |
186 | 4d54ec78 | Paolo Bonzini | } |
187 | 4d54ec78 | Paolo Bonzini | } |
188 | 4d54ec78 | Paolo Bonzini | |
189 | 4d54ec78 | Paolo Bonzini | static void qemu_init_child_watch(void) |
190 | 4d54ec78 | Paolo Bonzini | { |
191 | 4d54ec78 | Paolo Bonzini | struct sigaction act;
|
192 | 4d54ec78 | Paolo Bonzini | sigchld_bh = qemu_bh_new(sigchld_bh_handler, NULL);
|
193 | 4d54ec78 | Paolo Bonzini | |
194 | 4d54ec78 | Paolo Bonzini | act.sa_handler = sigchld_handler; |
195 | 4d54ec78 | Paolo Bonzini | act.sa_flags = SA_NOCLDSTOP; |
196 | 4d54ec78 | Paolo Bonzini | sigaction(SIGCHLD, &act, NULL);
|
197 | 4d54ec78 | Paolo Bonzini | } |
198 | 4d54ec78 | Paolo Bonzini | |
199 | 4d54ec78 | Paolo Bonzini | int qemu_add_child_watch(pid_t pid)
|
200 | 4d54ec78 | Paolo Bonzini | { |
201 | 4d54ec78 | Paolo Bonzini | ChildProcessRecord *rec; |
202 | 4d54ec78 | Paolo Bonzini | |
203 | 4d54ec78 | Paolo Bonzini | if (!sigchld_bh) {
|
204 | 4d54ec78 | Paolo Bonzini | qemu_init_child_watch(); |
205 | 4d54ec78 | Paolo Bonzini | } |
206 | 4d54ec78 | Paolo Bonzini | |
207 | 4d54ec78 | Paolo Bonzini | QLIST_FOREACH(rec, &child_watches, next) { |
208 | 4d54ec78 | Paolo Bonzini | if (rec->pid == pid) {
|
209 | 4d54ec78 | Paolo Bonzini | return 1; |
210 | 4d54ec78 | Paolo Bonzini | } |
211 | 4d54ec78 | Paolo Bonzini | } |
212 | 7267c094 | Anthony Liguori | rec = g_malloc0(sizeof(ChildProcessRecord));
|
213 | 4d54ec78 | Paolo Bonzini | rec->pid = pid; |
214 | 4d54ec78 | Paolo Bonzini | QLIST_INSERT_HEAD(&child_watches, rec, next); |
215 | 4d54ec78 | Paolo Bonzini | return 0; |
216 | 4d54ec78 | Paolo Bonzini | } |
217 | 4d54ec78 | Paolo Bonzini | #endif |