xen-vtx-unstable

annotate tools/console/daemon/io.c @ 6677:7bc32f4c67fb

merge?
author cl349@firebug.cl.cam.ac.uk
date Wed Sep 07 21:34:17 2005 +0000 (2005-09-07)
parents a39b1fa10edc 8db9c5873b9b
children 4d018790ff8a bd951d23d713 4d899a738d59 e7c7196fa329
rev   line source
kaf24@6038 1 /*\
kaf24@6038 2 * Copyright (C) International Business Machines Corp., 2005
kaf24@6038 3 * Author(s): Anthony Liguori <aliguori@us.ibm.com>
kaf24@6038 4 *
kaf24@6038 5 * Xen Console Daemon
kaf24@6038 6 *
kaf24@6038 7 * This program is free software; you can redistribute it and/or modify
kaf24@6038 8 * it under the terms of the GNU General Public License as published by
kaf24@6038 9 * the Free Software Foundation; under version 2 of the License.
kaf24@6038 10 *
kaf24@6038 11 * This program is distributed in the hope that it will be useful,
kaf24@6038 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
kaf24@6038 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kaf24@6038 14 * GNU General Public License for more details.
kaf24@6038 15 *
kaf24@6038 16 * You should have received a copy of the GNU General Public License
kaf24@6038 17 * along with this program; if not, write to the Free Software
kaf24@6038 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
kaf24@6038 19 \*/
kaf24@6038 20
kaf24@6038 21 #define _GNU_SOURCE
kaf24@6038 22
kaf24@6038 23 #include "utils.h"
kaf24@6038 24 #include "io.h"
kaf24@6038 25
cl349@6388 26 #include "xenctrl.h"
kaf24@6038 27 #include "xs.h"
kaf24@6038 28 #include "xen/io/domain_controller.h"
kaf24@6038 29
kaf24@6038 30 #include <malloc.h>
kaf24@6038 31 #include <stdlib.h>
kaf24@6038 32 #include <errno.h>
kaf24@6038 33 #include <string.h>
kaf24@6038 34 #include <sys/select.h>
kaf24@6038 35 #include <fcntl.h>
kaf24@6038 36 #include <unistd.h>
kaf24@6038 37 #include <termios.h>
cl349@6474 38 #include <stdarg.h>
cl349@6474 39 #include <sys/ioctl.h>
cl349@6474 40 #include <sys/mman.h>
kaf24@6038 41
kaf24@6038 42 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
kaf24@6038 43 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
kaf24@6038 44
cl349@6637 45 /* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
cl349@6637 46 #define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
cl349@6637 47
kaf24@6038 48 struct buffer
kaf24@6038 49 {
kaf24@6038 50 char *data;
kaf24@6038 51 size_t size;
kaf24@6038 52 size_t capacity;
kaf24@6038 53 size_t max_capacity;
kaf24@6038 54 };
kaf24@6038 55
cl349@6474 56 struct domain
cl349@6474 57 {
cl349@6474 58 int domid;
cl349@6474 59 int tty_fd;
cl349@6474 60 bool is_dead;
cl349@6474 61 struct buffer buffer;
cl349@6474 62 struct domain *next;
cl349@6637 63 char *conspath;
cl349@6637 64 int ring_ref;
cl349@6474 65 int local_port;
cl349@6474 66 char *page;
cl349@6474 67 int evtchn_fd;
cl349@6474 68 };
cl349@6474 69
cl349@6474 70 static struct domain *dom_head;
cl349@6474 71
cl349@6474 72 struct ring_head
kaf24@6038 73 {
cl349@6474 74 u32 cons;
cl349@6474 75 u32 prod;
cl349@6474 76 char buf[0];
cl349@6474 77 } __attribute__((packed));
cl349@6474 78
cl349@6474 79 #define PAGE_SIZE (getpagesize())
cl349@6474 80 #define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
cl349@6474 81 #define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
cl349@6474 82 #define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
cl349@6474 83 #define XENCONS_SPACE(ring) (XENCONS_RING_SIZE - ((ring)->prod - (ring)->cons))
cl349@6474 84
cl349@6474 85 static void buffer_append(struct domain *dom)
cl349@6474 86 {
cl349@6474 87 struct buffer *buffer = &dom->buffer;
cl349@6474 88 struct ring_head *ring = (struct ring_head *)dom->page;
cl349@6474 89 size_t size;
cl349@6474 90
cl349@6474 91 while ((size = ring->prod - ring->cons) != 0) {
cl349@6474 92 if ((buffer->capacity - buffer->size) < size) {
cl349@6474 93 buffer->capacity += (size + 1024);
cl349@6474 94 buffer->data = realloc(buffer->data, buffer->capacity);
cl349@6474 95 if (buffer->data == NULL) {
cl349@6474 96 dolog(LOG_ERR, "Memory allocation failed");
cl349@6474 97 exit(ENOMEM);
cl349@6474 98 }
kaf24@6038 99 }
kaf24@6038 100
cl349@6474 101 while (ring->cons < ring->prod) {
cl349@6474 102 buffer->data[buffer->size] =
cl349@6474 103 ring->buf[XENCONS_IDX(ring->cons)];
cl349@6474 104 buffer->size++;
cl349@6474 105 ring->cons++;
cl349@6474 106 }
kaf24@6038 107
cl349@6474 108 if (buffer->max_capacity &&
cl349@6474 109 buffer->size > buffer->max_capacity) {
cl349@6474 110 memmove(buffer->data + (buffer->size -
cl349@6474 111 buffer->max_capacity),
cl349@6474 112 buffer->data, buffer->max_capacity);
cl349@6474 113 buffer->data = realloc(buffer->data,
cl349@6474 114 buffer->max_capacity);
cl349@6474 115 buffer->capacity = buffer->max_capacity;
cl349@6474 116 }
kaf24@6038 117 }
kaf24@6038 118 }
kaf24@6038 119
kaf24@6038 120 static bool buffer_empty(struct buffer *buffer)
kaf24@6038 121 {
kaf24@6038 122 return buffer->size == 0;
kaf24@6038 123 }
kaf24@6038 124
kaf24@6038 125 static void buffer_advance(struct buffer *buffer, size_t size)
kaf24@6038 126 {
kaf24@6038 127 size = MIN(size, buffer->size);
kaf24@6038 128 memmove(buffer->data, buffer + size, buffer->size - size);
kaf24@6038 129 buffer->size -= size;
kaf24@6038 130 }
kaf24@6038 131
kaf24@6038 132 static bool domain_is_valid(int domid)
kaf24@6038 133 {
kaf24@6038 134 bool ret;
kaf24@6038 135 xc_dominfo_t info;
kaf24@6038 136
kaf24@6038 137 ret = (xc_domain_getinfo(xc, domid, 1, &info) == 1 &&
kaf24@6038 138 info.domid == domid);
kaf24@6038 139
kaf24@6038 140 return ret;
kaf24@6038 141 }
kaf24@6038 142
kaf24@6038 143 static int domain_create_tty(struct domain *dom)
kaf24@6038 144 {
cl349@6474 145 char *path;
kaf24@6038 146 int master;
cl349@6676 147 bool success;
kaf24@6038 148
kaf24@6038 149 if ((master = getpt()) == -1 ||
kaf24@6038 150 grantpt(master) == -1 || unlockpt(master) == -1) {
kaf24@6038 151 dolog(LOG_ERR, "Failed to create tty for domain-%d",
kaf24@6038 152 dom->domid);
kaf24@6038 153 master = -1;
kaf24@6038 154 } else {
kaf24@6038 155 const char *slave = ptsname(master);
kaf24@6038 156 struct termios term;
kaf24@6038 157 char *data;
kaf24@6038 158 unsigned int len;
kaf24@6038 159
kaf24@6038 160 if (tcgetattr(master, &term) != -1) {
kaf24@6038 161 cfmakeraw(&term);
kaf24@6038 162 tcsetattr(master, TCSAFLUSH, &term);
kaf24@6038 163 }
kaf24@6038 164
cl349@6676 165 success = asprintf(&path, "%s/tty", dom->conspath) != -1;
cl349@6676 166 if (!success)
cl349@6676 167 goto out;
cl349@6676 168 success = xs_write(xs, path, slave, strlen(slave), O_CREAT);
cl349@6474 169 free(path);
cl349@6676 170 if (!success)
cl349@6676 171 goto out;
kaf24@6038 172
cl349@6676 173 success = asprintf(&path, "%s/limit", dom->conspath) != -1;
cl349@6676 174 if (!success)
cl349@6676 175 goto out;
kaf24@6038 176 data = xs_read(xs, path, &len);
kaf24@6038 177 if (data) {
kaf24@6038 178 dom->buffer.max_capacity = strtoul(data, 0, 0);
kaf24@6038 179 free(data);
kaf24@6038 180 }
cl349@6474 181 free(path);
kaf24@6038 182 }
kaf24@6038 183
kaf24@6038 184 return master;
cl349@6676 185 out:
cl349@6676 186 close(master);
cl349@6676 187 return -1;
kaf24@6038 188 }
kaf24@6038 189
cl349@6474 190 /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
cl349@6474 191 int xs_gather(struct xs_handle *xs, const char *dir, ...)
cl349@6474 192 {
cl349@6474 193 va_list ap;
cl349@6474 194 const char *name;
cl349@6474 195 char *path;
cl349@6474 196 int ret = 0;
cl349@6474 197
cl349@6474 198 va_start(ap, dir);
cl349@6474 199 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
cl349@6474 200 const char *fmt = va_arg(ap, char *);
cl349@6474 201 void *result = va_arg(ap, void *);
cl349@6474 202 char *p;
cl349@6474 203
cl349@6474 204 asprintf(&path, "%s/%s", dir, name);
cl349@6474 205 p = xs_read(xs, path, NULL);
cl349@6474 206 free(path);
cl349@6474 207 if (p == NULL) {
cl349@6474 208 ret = ENOENT;
cl349@6474 209 break;
cl349@6474 210 }
cl349@6474 211 if (fmt) {
cl349@6474 212 if (sscanf(p, fmt, result) == 0)
cl349@6474 213 ret = EINVAL;
cl349@6474 214 free(p);
cl349@6474 215 } else
cl349@6474 216 *(char **)result = p;
cl349@6474 217 }
cl349@6474 218 va_end(ap);
cl349@6474 219 return ret;
cl349@6474 220 }
cl349@6474 221
cl349@6474 222 #define EVENTCHN_BIND _IO('E', 2)
cl349@6474 223 #define EVENTCHN_UNBIND _IO('E', 3)
cl349@6474 224
cl349@6474 225 static int domain_create_ring(struct domain *dom)
cl349@6474 226 {
cl349@6637 227 int err, local_port, ring_ref;
cl349@6474 228
cl349@6637 229 err = xs_gather(xs, dom->conspath,
cl349@6637 230 "ring-ref", "%u", &ring_ref,
cl349@6676 231 "port", "%i", &local_port,
cl349@6474 232 NULL);
cl349@6474 233 if (err)
cl349@6474 234 goto out;
cl349@6474 235
cl349@6637 236 if (ring_ref != dom->ring_ref) {
cl349@6637 237 if (dom->page)
cl349@6637 238 munmap(dom->page, getpagesize());
cl349@6484 239 dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
cl349@6484 240 PROT_READ|PROT_WRITE,
cl349@6637 241 (unsigned long)ring_ref);
cl349@6484 242 if (dom->page == NULL) {
cl349@6484 243 err = EINVAL;
cl349@6484 244 goto out;
cl349@6484 245 }
cl349@6637 246 dom->ring_ref = ring_ref;
cl349@6474 247 }
cl349@6474 248
cl349@6637 249 if (local_port != dom->local_port) {
cl349@6637 250 dom->local_port = -1;
cl349@6637 251 if (dom->evtchn_fd != -1)
cl349@6637 252 close(dom->evtchn_fd);
cl349@6484 253 /* Opening evtchn independently for each console is a bit
cl349@6484 254 * wastefule, but that's how the code is structured... */
cl349@6637 255 dom->evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
cl349@6637 256 if (dom->evtchn_fd == -1) {
cl349@6484 257 err = errno;
cl349@6484 258 goto out;
cl349@6484 259 }
cl349@6484 260
cl349@6637 261 if (ioctl(dom->evtchn_fd, EVENTCHN_BIND, local_port) == -1) {
cl349@6484 262 err = errno;
cl349@6484 263 close(dom->evtchn_fd);
cl349@6484 264 dom->evtchn_fd = -1;
cl349@6484 265 goto out;
cl349@6484 266 }
cl349@6637 267 dom->local_port = local_port;
cl349@6474 268 }
cl349@6474 269
cl349@6474 270 out:
cl349@6474 271 return err;
cl349@6474 272 }
cl349@6474 273
cl349@6637 274 static bool watch_domain(struct domain *dom, bool watch)
cl349@6637 275 {
cl349@6637 276 char domid_str[3 + MAX_STRLEN(dom->domid)];
cl349@6637 277 bool success;
cl349@6637 278
cl349@6637 279 sprintf(domid_str, "dom%u", dom->domid);
cl349@6637 280 if (watch)
cl349@6637 281 success = xs_watch(xs, dom->conspath, domid_str);
cl349@6637 282 else
cl349@6637 283 success = xs_unwatch(xs, dom->conspath, domid_str);
cl349@6637 284 if (success)
cl349@6637 285 domain_create_ring(dom);
cl349@6637 286 return success;
cl349@6637 287 }
cl349@6637 288
kaf24@6038 289 static struct domain *create_domain(int domid)
kaf24@6038 290 {
kaf24@6038 291 struct domain *dom;
cl349@6673 292 char *s;
kaf24@6038 293
kaf24@6038 294 dom = (struct domain *)malloc(sizeof(struct domain));
kaf24@6038 295 if (dom == NULL) {
kaf24@6038 296 dolog(LOG_ERR, "Out of memory %s:%s():L%d",
kaf24@6038 297 __FILE__, __FUNCTION__, __LINE__);
kaf24@6038 298 exit(ENOMEM);
kaf24@6038 299 }
kaf24@6038 300
kaf24@6038 301 dom->domid = domid;
cl349@6676 302
cl349@6676 303 dom->conspath = xs_get_domain_path(xs, dom->domid);
cl349@6676 304 if (dom->conspath == NULL)
cl349@6676 305 goto out;
cl349@6676 306 s = realloc(dom->conspath, strlen(dom->conspath) +
cl349@6676 307 strlen("/console") + 1);
cl349@6676 308 if (s == NULL)
cl349@6676 309 goto out;
cl349@6676 310 dom->conspath = s;
cl349@6676 311 strcat(dom->conspath, "/console");
cl349@6676 312
kaf24@6038 313 dom->tty_fd = domain_create_tty(dom);
kaf24@6189 314 dom->is_dead = false;
kaf24@6038 315 dom->buffer.data = 0;
kaf24@6038 316 dom->buffer.size = 0;
kaf24@6038 317 dom->buffer.capacity = 0;
kaf24@6038 318 dom->buffer.max_capacity = 0;
cl349@6474 319 dom->next = NULL;
cl349@6474 320
cl349@6637 321 dom->ring_ref = -1;
cl349@6637 322 dom->local_port = -1;
cl349@6484 323 dom->page = NULL;
cl349@6484 324 dom->evtchn_fd = -1;
cl349@6484 325
cl349@6637 326 if (!watch_domain(dom, true))
cl349@6637 327 goto out;
cl349@6637 328
cl349@6637 329 dom->next = dom_head;
cl349@6637 330 dom_head = dom;
kaf24@6038 331
kaf24@6038 332 dolog(LOG_DEBUG, "New domain %d", domid);
kaf24@6038 333
kaf24@6038 334 return dom;
cl349@6637 335 out:
cl349@6637 336 if (dom->conspath)
cl349@6637 337 free(dom->conspath);
cl349@6637 338 free(dom);
cl349@6637 339 return NULL;
kaf24@6038 340 }
kaf24@6038 341
kaf24@6038 342 static struct domain *lookup_domain(int domid)
kaf24@6038 343 {
cl349@6484 344 struct domain *dom;
kaf24@6038 345
cl349@6484 346 for (dom = dom_head; dom; dom = dom->next)
cl349@6484 347 if (dom->domid == domid)
kaf24@6038 348 return dom;
cl349@6637 349 return NULL;
kaf24@6038 350 }
kaf24@6038 351
kaf24@6038 352 static void remove_domain(struct domain *dom)
kaf24@6038 353 {
kaf24@6038 354 struct domain **pp;
kaf24@6038 355
kaf24@6038 356 dolog(LOG_DEBUG, "Removing domain-%d", dom->domid);
kaf24@6038 357
kaf24@6038 358 for (pp = &dom_head; *pp; pp = &(*pp)->next) {
cl349@6637 359 if (dom == *pp) {
cl349@6637 360 *pp = dom->next;
cl349@6637 361 free(dom);
kaf24@6038 362 break;
kaf24@6038 363 }
kaf24@6038 364 }
kaf24@6038 365 }
kaf24@6038 366
cl349@6637 367 static void cleanup_domain(struct domain *d)
kaf24@6189 368 {
cl349@6637 369 if (!buffer_empty(&d->buffer))
cl349@6637 370 return;
kaf24@6189 371
cl349@6637 372 if (d->buffer.data)
cl349@6637 373 free(d->buffer.data);
cl349@6637 374 d->buffer.data = NULL;
cl349@6637 375 if (d->tty_fd != -1)
cl349@6637 376 close(d->tty_fd);
cl349@6637 377 d->tty_fd = -1;
cl349@6637 378 remove_domain(d);
cl349@6637 379 }
cl349@6637 380
cl349@6637 381 static void shutdown_domain(struct domain *d)
cl349@6637 382 {
cl349@6637 383 d->is_dead = true;
cl349@6637 384 watch_domain(d, false);
cl349@6637 385 if (d->page)
cl349@6637 386 munmap(d->page, getpagesize());
cl349@6637 387 d->page = NULL;
cl349@6637 388 if (d->evtchn_fd != -1)
cl349@6637 389 close(d->evtchn_fd);
cl349@6637 390 d->evtchn_fd = -1;
cl349@6637 391 cleanup_domain(d);
kaf24@6189 392 }
kaf24@6189 393
cl349@6484 394 void enum_domains(void)
cl349@6484 395 {
cl349@6484 396 int domid = 1;
cl349@6484 397 xc_dominfo_t dominfo;
cl349@6484 398 struct domain *dom;
cl349@6484 399
cl349@6484 400 while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
cl349@6484 401 dom = lookup_domain(dominfo.domid);
cl349@6637 402 if (dominfo.dying || dominfo.crashed || dominfo.shutdown) {
cl349@6637 403 if (dom)
cl349@6637 404 shutdown_domain(dom);
cl349@6637 405 } else {
cl349@6637 406 if (dom == NULL)
cl349@6637 407 create_domain(dominfo.domid);
cl349@6637 408 }
cl349@6484 409 domid = dominfo.domid + 1;
cl349@6484 410 }
cl349@6484 411 }
cl349@6484 412
kaf24@6038 413 static void handle_tty_read(struct domain *dom)
kaf24@6038 414 {
kaf24@6038 415 ssize_t len;
cl349@6474 416 char msg[80];
cl349@6474 417 struct ring_head *inring =
cl349@6474 418 (struct ring_head *)(dom->page + PAGE_SIZE/2);
cl349@6474 419 int i;
kaf24@6038 420
cl349@6544 421 len = read(dom->tty_fd, msg, MIN(XENCONS_SPACE(inring), sizeof(msg)));
kaf24@6038 422 if (len < 1) {
kaf24@6038 423 close(dom->tty_fd);
cl349@6474 424 dom->tty_fd = -1;
kaf24@6038 425
kaf24@6038 426 if (domain_is_valid(dom->domid)) {
kaf24@6038 427 dom->tty_fd = domain_create_tty(dom);
kaf24@6038 428 } else {
cl349@6637 429 shutdown_domain(dom);
kaf24@6038 430 }
kaf24@6038 431 } else if (domain_is_valid(dom->domid)) {
cl349@6474 432 for (i = 0; i < len; i++) {
cl349@6474 433 inring->buf[XENCONS_IDX(inring->prod)] = msg[i];
cl349@6474 434 inring->prod++;
kaf24@6038 435 }
cl349@6474 436 xc_evtchn_send(xc, dom->local_port);
kaf24@6038 437 } else {
kaf24@6038 438 close(dom->tty_fd);
cl349@6474 439 dom->tty_fd = -1;
cl349@6637 440 shutdown_domain(dom);
kaf24@6038 441 }
kaf24@6038 442 }
kaf24@6038 443
kaf24@6038 444 static void handle_tty_write(struct domain *dom)
kaf24@6038 445 {
kaf24@6038 446 ssize_t len;
kaf24@6038 447
kaf24@6038 448 len = write(dom->tty_fd, dom->buffer.data, dom->buffer.size);
kaf24@6038 449 if (len < 1) {
kaf24@6038 450 close(dom->tty_fd);
cl349@6474 451 dom->tty_fd = -1;
kaf24@6038 452
kaf24@6038 453 if (domain_is_valid(dom->domid)) {
kaf24@6038 454 dom->tty_fd = domain_create_tty(dom);
kaf24@6038 455 } else {
cl349@6637 456 shutdown_domain(dom);
kaf24@6038 457 }
kaf24@6038 458 } else {
kaf24@6038 459 buffer_advance(&dom->buffer, len);
kaf24@6038 460 }
kaf24@6038 461 }
kaf24@6038 462
cl349@6474 463 static void handle_ring_read(struct domain *dom)
cl349@6474 464 {
cl349@6474 465 u16 v;
cl349@6474 466
cl349@6474 467 if (!read_sync(dom->evtchn_fd, &v, sizeof(v)))
cl349@6474 468 return;
cl349@6474 469
cl349@6474 470 buffer_append(dom);
cl349@6474 471
cl349@6474 472 (void)write_sync(dom->evtchn_fd, &v, sizeof(v));
cl349@6474 473 }
cl349@6474 474
cl349@6484 475 static void handle_xs(int fd)
kaf24@6038 476 {
cl349@6484 477 char **vec;
cl349@6484 478 int domid;
cl349@6474 479 struct domain *dom;
kaf24@6038 480
cl349@6484 481 vec = xs_read_watch(xs);
cl349@6484 482 if (!vec)
cl349@6484 483 return;
cl349@6484 484
cl349@6648 485 if (!strcmp(vec[1], "domlist"))
cl349@6637 486 enum_domains();
cl349@6637 487 else if (sscanf(vec[1], "dom%u", &domid) == 1) {
cl349@6484 488 dom = lookup_domain(domid);
cl349@6637 489 if (dom->is_dead == false)
cl349@6484 490 domain_create_ring(dom);
kaf24@6038 491 }
cl349@6484 492
cl349@6484 493 xs_acknowledge_watch(xs, vec[1]);
cl349@6484 494 free(vec);
kaf24@6038 495 }
kaf24@6038 496
kaf24@6038 497 void handle_io(void)
kaf24@6038 498 {
kaf24@6038 499 fd_set readfds, writefds;
kaf24@6038 500 int ret;
kaf24@6038 501
kaf24@6038 502 do {
cl349@6637 503 struct domain *d, *n;
cl349@6484 504 struct timeval tv = { 100, 0 };
cl349@6474 505 int max_fd = -1;
kaf24@6038 506
kaf24@6038 507 FD_ZERO(&readfds);
kaf24@6038 508 FD_ZERO(&writefds);
kaf24@6038 509
cl349@6484 510 FD_SET(xs_fileno(xs), &readfds);
cl349@6484 511 max_fd = MAX(xs_fileno(xs), max_fd);
cl349@6484 512
kaf24@6038 513 for (d = dom_head; d; d = d->next) {
cl349@6637 514 if (d->evtchn_fd != -1) {
cl349@6474 515 FD_SET(d->evtchn_fd, &readfds);
cl349@6637 516 max_fd = MAX(d->evtchn_fd, max_fd);
kaf24@6038 517 }
kaf24@6038 518
cl349@6637 519 if (d->tty_fd != -1) {
cl349@6637 520 if (!d->is_dead)
cl349@6637 521 FD_SET(d->tty_fd, &readfds);
cl349@6637 522
cl349@6637 523 if (!buffer_empty(&d->buffer))
cl349@6637 524 FD_SET(d->tty_fd, &writefds);
cl349@6637 525 max_fd = MAX(d->tty_fd, max_fd);
cl349@6637 526 }
kaf24@6038 527 }
kaf24@6038 528
kaf24@6038 529 ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
cl349@6484 530
cl349@6484 531 if (FD_ISSET(xs_fileno(xs), &readfds))
cl349@6484 532 handle_xs(xs_fileno(xs));
kaf24@6038 533
cl349@6637 534 for (d = dom_head; d; d = n) {
cl349@6637 535 n = d->next;
cl349@6637 536 if (d->evtchn_fd != -1 &&
cl349@6637 537 FD_ISSET(d->evtchn_fd, &readfds))
cl349@6474 538 handle_ring_read(d);
cl349@6474 539
cl349@6637 540 if (d->tty_fd != -1) {
cl349@6637 541 if (FD_ISSET(d->tty_fd, &readfds))
cl349@6637 542 handle_tty_read(d);
cl349@6637 543
cl349@6637 544 if (FD_ISSET(d->tty_fd, &writefds))
cl349@6637 545 handle_tty_write(d);
cl349@6637 546
cl349@6637 547 if (d->is_dead)
cl349@6637 548 cleanup_domain(d);
cl349@6637 549 }
kaf24@6038 550 }
kaf24@6038 551 } while (ret > -1);
kaf24@6038 552 }