root / iohandler.c @ 370521a1
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 | 02981419 | Paolo Bonzini | #include "qemu-char.h" |
28 | 02981419 | Paolo Bonzini | #include "qemu-queue.h" |
29 | 44a9b356 | Paolo Bonzini | #include "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 | int fd;
|
37 | 02981419 | Paolo Bonzini | IOCanReadHandler *fd_read_poll; |
38 | 02981419 | Paolo Bonzini | IOHandler *fd_read; |
39 | 02981419 | Paolo Bonzini | IOHandler *fd_write; |
40 | 02981419 | Paolo Bonzini | int deleted;
|
41 | 02981419 | Paolo Bonzini | void *opaque;
|
42 | 02981419 | Paolo Bonzini | QLIST_ENTRY(IOHandlerRecord) next; |
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 | 02981419 | Paolo Bonzini | if (!fd_read && !fd_write) {
|
60 | 02981419 | Paolo Bonzini | QLIST_FOREACH(ioh, &io_handlers, next) { |
61 | 02981419 | Paolo Bonzini | if (ioh->fd == fd) {
|
62 | 02981419 | Paolo Bonzini | ioh->deleted = 1;
|
63 | 02981419 | Paolo Bonzini | break;
|
64 | 02981419 | Paolo Bonzini | } |
65 | 02981419 | Paolo Bonzini | } |
66 | 02981419 | Paolo Bonzini | } else {
|
67 | 02981419 | Paolo Bonzini | QLIST_FOREACH(ioh, &io_handlers, next) { |
68 | 02981419 | Paolo Bonzini | if (ioh->fd == fd)
|
69 | 02981419 | Paolo Bonzini | goto found;
|
70 | 02981419 | Paolo Bonzini | } |
71 | 7267c094 | Anthony Liguori | ioh = g_malloc0(sizeof(IOHandlerRecord));
|
72 | 02981419 | Paolo Bonzini | QLIST_INSERT_HEAD(&io_handlers, ioh, next); |
73 | 02981419 | Paolo Bonzini | found:
|
74 | 02981419 | Paolo Bonzini | ioh->fd = fd; |
75 | 02981419 | Paolo Bonzini | ioh->fd_read_poll = fd_read_poll; |
76 | 02981419 | Paolo Bonzini | ioh->fd_read = fd_read; |
77 | 02981419 | Paolo Bonzini | ioh->fd_write = fd_write; |
78 | 02981419 | Paolo Bonzini | ioh->opaque = opaque; |
79 | 02981419 | Paolo Bonzini | ioh->deleted = 0;
|
80 | 02981419 | Paolo Bonzini | } |
81 | 02981419 | Paolo Bonzini | return 0; |
82 | 02981419 | Paolo Bonzini | } |
83 | 02981419 | Paolo Bonzini | |
84 | 02981419 | Paolo Bonzini | int qemu_set_fd_handler(int fd, |
85 | 02981419 | Paolo Bonzini | IOHandler *fd_read, |
86 | 02981419 | Paolo Bonzini | IOHandler *fd_write, |
87 | 02981419 | Paolo Bonzini | void *opaque)
|
88 | 02981419 | Paolo Bonzini | { |
89 | be08e65e | Paolo Bonzini | return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); |
90 | 02981419 | Paolo Bonzini | } |
91 | 02981419 | Paolo Bonzini | |
92 | 02981419 | Paolo Bonzini | void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds) |
93 | 02981419 | Paolo Bonzini | { |
94 | 02981419 | Paolo Bonzini | IOHandlerRecord *ioh; |
95 | 02981419 | Paolo Bonzini | |
96 | 02981419 | Paolo Bonzini | QLIST_FOREACH(ioh, &io_handlers, next) { |
97 | 02981419 | Paolo Bonzini | if (ioh->deleted)
|
98 | 02981419 | Paolo Bonzini | continue;
|
99 | 02981419 | Paolo Bonzini | if (ioh->fd_read &&
|
100 | 02981419 | Paolo Bonzini | (!ioh->fd_read_poll || |
101 | 02981419 | Paolo Bonzini | ioh->fd_read_poll(ioh->opaque) != 0)) {
|
102 | 02981419 | Paolo Bonzini | FD_SET(ioh->fd, readfds); |
103 | 02981419 | Paolo Bonzini | if (ioh->fd > *pnfds)
|
104 | 02981419 | Paolo Bonzini | *pnfds = ioh->fd; |
105 | 02981419 | Paolo Bonzini | } |
106 | 02981419 | Paolo Bonzini | if (ioh->fd_write) {
|
107 | 02981419 | Paolo Bonzini | FD_SET(ioh->fd, writefds); |
108 | 02981419 | Paolo Bonzini | if (ioh->fd > *pnfds)
|
109 | 02981419 | Paolo Bonzini | *pnfds = ioh->fd; |
110 | 02981419 | Paolo Bonzini | } |
111 | 02981419 | Paolo Bonzini | } |
112 | 02981419 | Paolo Bonzini | } |
113 | 02981419 | Paolo Bonzini | |
114 | 02981419 | Paolo Bonzini | void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int ret) |
115 | 02981419 | Paolo Bonzini | { |
116 | 02981419 | Paolo Bonzini | if (ret > 0) { |
117 | 02981419 | Paolo Bonzini | IOHandlerRecord *pioh, *ioh; |
118 | 02981419 | Paolo Bonzini | |
119 | 02981419 | Paolo Bonzini | QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { |
120 | 02981419 | Paolo Bonzini | if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, readfds)) {
|
121 | 02981419 | Paolo Bonzini | ioh->fd_read(ioh->opaque); |
122 | 02981419 | Paolo Bonzini | } |
123 | 02981419 | Paolo Bonzini | if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, writefds)) {
|
124 | 02981419 | Paolo Bonzini | ioh->fd_write(ioh->opaque); |
125 | 02981419 | Paolo Bonzini | } |
126 | 02981419 | Paolo Bonzini | |
127 | 02981419 | Paolo Bonzini | /* Do this last in case read/write handlers marked it for deletion */
|
128 | 02981419 | Paolo Bonzini | if (ioh->deleted) {
|
129 | 02981419 | Paolo Bonzini | QLIST_REMOVE(ioh, next); |
130 | 7267c094 | Anthony Liguori | g_free(ioh); |
131 | 02981419 | Paolo Bonzini | } |
132 | 02981419 | Paolo Bonzini | } |
133 | 02981419 | Paolo Bonzini | } |
134 | 02981419 | Paolo Bonzini | } |
135 | 4d54ec78 | Paolo Bonzini | |
136 | 4d54ec78 | Paolo Bonzini | /* reaping of zombies. right now we're not passing the status to
|
137 | 4d54ec78 | Paolo Bonzini | anyone, but it would be possible to add a callback. */
|
138 | 4d54ec78 | Paolo Bonzini | #ifndef _WIN32
|
139 | 4d54ec78 | Paolo Bonzini | typedef struct ChildProcessRecord { |
140 | 4d54ec78 | Paolo Bonzini | int pid;
|
141 | 4d54ec78 | Paolo Bonzini | QLIST_ENTRY(ChildProcessRecord) next; |
142 | 4d54ec78 | Paolo Bonzini | } ChildProcessRecord; |
143 | 4d54ec78 | Paolo Bonzini | |
144 | 4d54ec78 | Paolo Bonzini | static QLIST_HEAD(, ChildProcessRecord) child_watches =
|
145 | 4d54ec78 | Paolo Bonzini | QLIST_HEAD_INITIALIZER(child_watches); |
146 | 4d54ec78 | Paolo Bonzini | |
147 | 4d54ec78 | Paolo Bonzini | static QEMUBH *sigchld_bh;
|
148 | 4d54ec78 | Paolo Bonzini | |
149 | 4d54ec78 | Paolo Bonzini | static void sigchld_handler(int signal) |
150 | 4d54ec78 | Paolo Bonzini | { |
151 | 4d54ec78 | Paolo Bonzini | qemu_bh_schedule(sigchld_bh); |
152 | 4d54ec78 | Paolo Bonzini | } |
153 | 4d54ec78 | Paolo Bonzini | |
154 | 4d54ec78 | Paolo Bonzini | static void sigchld_bh_handler(void *opaque) |
155 | 4d54ec78 | Paolo Bonzini | { |
156 | 4d54ec78 | Paolo Bonzini | ChildProcessRecord *rec, *next; |
157 | 4d54ec78 | Paolo Bonzini | |
158 | 4d54ec78 | Paolo Bonzini | QLIST_FOREACH_SAFE(rec, &child_watches, next, next) { |
159 | 4d54ec78 | Paolo Bonzini | if (waitpid(rec->pid, NULL, WNOHANG) == rec->pid) { |
160 | 4d54ec78 | Paolo Bonzini | QLIST_REMOVE(rec, next); |
161 | 7267c094 | Anthony Liguori | g_free(rec); |
162 | 4d54ec78 | Paolo Bonzini | } |
163 | 4d54ec78 | Paolo Bonzini | } |
164 | 4d54ec78 | Paolo Bonzini | } |
165 | 4d54ec78 | Paolo Bonzini | |
166 | 4d54ec78 | Paolo Bonzini | static void qemu_init_child_watch(void) |
167 | 4d54ec78 | Paolo Bonzini | { |
168 | 4d54ec78 | Paolo Bonzini | struct sigaction act;
|
169 | 4d54ec78 | Paolo Bonzini | sigchld_bh = qemu_bh_new(sigchld_bh_handler, NULL);
|
170 | 4d54ec78 | Paolo Bonzini | |
171 | 4d54ec78 | Paolo Bonzini | act.sa_handler = sigchld_handler; |
172 | 4d54ec78 | Paolo Bonzini | act.sa_flags = SA_NOCLDSTOP; |
173 | 4d54ec78 | Paolo Bonzini | sigaction(SIGCHLD, &act, NULL);
|
174 | 4d54ec78 | Paolo Bonzini | } |
175 | 4d54ec78 | Paolo Bonzini | |
176 | 4d54ec78 | Paolo Bonzini | int qemu_add_child_watch(pid_t pid)
|
177 | 4d54ec78 | Paolo Bonzini | { |
178 | 4d54ec78 | Paolo Bonzini | ChildProcessRecord *rec; |
179 | 4d54ec78 | Paolo Bonzini | |
180 | 4d54ec78 | Paolo Bonzini | if (!sigchld_bh) {
|
181 | 4d54ec78 | Paolo Bonzini | qemu_init_child_watch(); |
182 | 4d54ec78 | Paolo Bonzini | } |
183 | 4d54ec78 | Paolo Bonzini | |
184 | 4d54ec78 | Paolo Bonzini | QLIST_FOREACH(rec, &child_watches, next) { |
185 | 4d54ec78 | Paolo Bonzini | if (rec->pid == pid) {
|
186 | 4d54ec78 | Paolo Bonzini | return 1; |
187 | 4d54ec78 | Paolo Bonzini | } |
188 | 4d54ec78 | Paolo Bonzini | } |
189 | 7267c094 | Anthony Liguori | rec = g_malloc0(sizeof(ChildProcessRecord));
|
190 | 4d54ec78 | Paolo Bonzini | rec->pid = pid; |
191 | 4d54ec78 | Paolo Bonzini | QLIST_INSERT_HEAD(&child_watches, rec, next); |
192 | 4d54ec78 | Paolo Bonzini | return 0; |
193 | 4d54ec78 | Paolo Bonzini | } |
194 | 4d54ec78 | Paolo Bonzini | #endif |