xen-vtx-unstable

annotate tools/console/daemon/io.c @ 6758:bd951d23d713

merge?
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 10:14:20 2005 +0000 (2005-09-13)
parents 4d018790ff8a 7bc32f4c67fb
children 4d899a738d59 8ca0f98ba8e2
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@6757 90 u32 oldcons;
cl349@6474 91
cl349@6474 92 while ((size = ring->prod - ring->cons) != 0) {
cl349@6474 93 if ((buffer->capacity - buffer->size) < size) {
cl349@6474 94 buffer->capacity += (size + 1024);
cl349@6474 95 buffer->data = realloc(buffer->data, buffer->capacity);
cl349@6474 96 if (buffer->data == NULL) {
cl349@6474 97 dolog(LOG_ERR, "Memory allocation failed");
cl349@6474 98 exit(ENOMEM);
cl349@6474 99 }
kaf24@6038 100 }
kaf24@6038 101
cl349@6757 102 oldcons = ring->cons;
cl349@6757 103 while (ring->cons < (oldcons + size)) {
cl349@6474 104 buffer->data[buffer->size] =
cl349@6474 105 ring->buf[XENCONS_IDX(ring->cons)];
cl349@6474 106 buffer->size++;
cl349@6474 107 ring->cons++;
cl349@6474 108 }
kaf24@6038 109
cl349@6474 110 if (buffer->max_capacity &&
cl349@6474 111 buffer->size > buffer->max_capacity) {
cl349@6474 112 memmove(buffer->data + (buffer->size -
cl349@6474 113 buffer->max_capacity),
cl349@6474 114 buffer->data, buffer->max_capacity);
cl349@6474 115 buffer->data = realloc(buffer->data,
cl349@6474 116 buffer->max_capacity);
cl349@6474 117 buffer->capacity = buffer->max_capacity;
cl349@6474 118 }
kaf24@6038 119 }
kaf24@6038 120 }
kaf24@6038 121
kaf24@6038 122 static bool buffer_empty(struct buffer *buffer)
kaf24@6038 123 {
kaf24@6038 124 return buffer->size == 0;
kaf24@6038 125 }
kaf24@6038 126
kaf24@6038 127 static void buffer_advance(struct buffer *buffer, size_t size)
kaf24@6038 128 {
kaf24@6038 129 size = MIN(size, buffer->size);
kaf24@6038 130 memmove(buffer->data, buffer + size, buffer->size - size);
kaf24@6038 131 buffer->size -= size;
kaf24@6038 132 }
kaf24@6038 133
kaf24@6038 134 static bool domain_is_valid(int domid)
kaf24@6038 135 {
kaf24@6038 136 bool ret;
kaf24@6038 137 xc_dominfo_t info;
kaf24@6038 138
kaf24@6038 139 ret = (xc_domain_getinfo(xc, domid, 1, &info) == 1 &&
kaf24@6038 140 info.domid == domid);
kaf24@6038 141
kaf24@6038 142 return ret;
kaf24@6038 143 }
kaf24@6038 144
kaf24@6038 145 static int domain_create_tty(struct domain *dom)
kaf24@6038 146 {
cl349@6474 147 char *path;
kaf24@6038 148 int master;
cl349@6676 149 bool success;
kaf24@6038 150
kaf24@6038 151 if ((master = getpt()) == -1 ||
kaf24@6038 152 grantpt(master) == -1 || unlockpt(master) == -1) {
kaf24@6038 153 dolog(LOG_ERR, "Failed to create tty for domain-%d",
kaf24@6038 154 dom->domid);
kaf24@6038 155 master = -1;
kaf24@6038 156 } else {
kaf24@6038 157 const char *slave = ptsname(master);
kaf24@6038 158 struct termios term;
kaf24@6038 159 char *data;
kaf24@6038 160 unsigned int len;
kaf24@6038 161
kaf24@6038 162 if (tcgetattr(master, &term) != -1) {
kaf24@6038 163 cfmakeraw(&term);
kaf24@6038 164 tcsetattr(master, TCSAFLUSH, &term);
kaf24@6038 165 }
kaf24@6038 166
cl349@6676 167 success = asprintf(&path, "%s/tty", dom->conspath) != -1;
cl349@6676 168 if (!success)
cl349@6676 169 goto out;
cl349@6676 170 success = xs_write(xs, path, slave, strlen(slave), O_CREAT);
cl349@6474 171 free(path);
cl349@6676 172 if (!success)
cl349@6676 173 goto out;
kaf24@6038 174
cl349@6676 175 success = asprintf(&path, "%s/limit", dom->conspath) != -1;
cl349@6676 176 if (!success)
cl349@6676 177 goto out;
kaf24@6038 178 data = xs_read(xs, path, &len);
kaf24@6038 179 if (data) {
kaf24@6038 180 dom->buffer.max_capacity = strtoul(data, 0, 0);
kaf24@6038 181 free(data);
kaf24@6038 182 }
cl349@6474 183 free(path);
kaf24@6038 184 }
kaf24@6038 185
kaf24@6038 186 return master;
cl349@6676 187 out:
cl349@6676 188 close(master);
cl349@6676 189 return -1;
kaf24@6038 190 }
kaf24@6038 191
cl349@6474 192 /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
cl349@6474 193 int xs_gather(struct xs_handle *xs, const char *dir, ...)
cl349@6474 194 {
cl349@6474 195 va_list ap;
cl349@6474 196 const char *name;
cl349@6474 197 char *path;
cl349@6474 198 int ret = 0;
cl349@6474 199
cl349@6474 200 va_start(ap, dir);
cl349@6474 201 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
cl349@6474 202 const char *fmt = va_arg(ap, char *);
cl349@6474 203 void *result = va_arg(ap, void *);
cl349@6474 204 char *p;
cl349@6474 205
cl349@6474 206 asprintf(&path, "%s/%s", dir, name);
cl349@6474 207 p = xs_read(xs, path, NULL);
cl349@6474 208 free(path);
cl349@6474 209 if (p == NULL) {
cl349@6474 210 ret = ENOENT;
cl349@6474 211 break;
cl349@6474 212 }
cl349@6474 213 if (fmt) {
cl349@6474 214 if (sscanf(p, fmt, result) == 0)
cl349@6474 215 ret = EINVAL;
cl349@6474 216 free(p);
cl349@6474 217 } else
cl349@6474 218 *(char **)result = p;
cl349@6474 219 }
cl349@6474 220 va_end(ap);
cl349@6474 221 return ret;
cl349@6474 222 }
cl349@6474 223
cl349@6474 224 #define EVENTCHN_BIND _IO('E', 2)
cl349@6474 225 #define EVENTCHN_UNBIND _IO('E', 3)
cl349@6474 226
cl349@6474 227 static int domain_create_ring(struct domain *dom)
cl349@6474 228 {
cl349@6637 229 int err, local_port, ring_ref;
cl349@6474 230
cl349@6637 231 err = xs_gather(xs, dom->conspath,
cl349@6637 232 "ring-ref", "%u", &ring_ref,
cl349@6676 233 "port", "%i", &local_port,
cl349@6474 234 NULL);
cl349@6474 235 if (err)
cl349@6474 236 goto out;
cl349@6474 237
cl349@6637 238 if (ring_ref != dom->ring_ref) {
cl349@6637 239 if (dom->page)
cl349@6637 240 munmap(dom->page, getpagesize());
cl349@6484 241 dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
cl349@6484 242 PROT_READ|PROT_WRITE,
cl349@6637 243 (unsigned long)ring_ref);
cl349@6484 244 if (dom->page == NULL) {
cl349@6484 245 err = EINVAL;
cl349@6484 246 goto out;
cl349@6484 247 }
cl349@6637 248 dom->ring_ref = ring_ref;
cl349@6474 249 }
cl349@6474 250
cl349@6637 251 if (local_port != dom->local_port) {
cl349@6637 252 dom->local_port = -1;
cl349@6637 253 if (dom->evtchn_fd != -1)
cl349@6637 254 close(dom->evtchn_fd);
cl349@6484 255 /* Opening evtchn independently for each console is a bit
cl349@6484 256 * wastefule, but that's how the code is structured... */
cl349@6637 257 dom->evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
cl349@6637 258 if (dom->evtchn_fd == -1) {
cl349@6484 259 err = errno;
cl349@6484 260 goto out;
cl349@6484 261 }
cl349@6484 262
cl349@6637 263 if (ioctl(dom->evtchn_fd, EVENTCHN_BIND, local_port) == -1) {
cl349@6484 264 err = errno;
cl349@6484 265 close(dom->evtchn_fd);
cl349@6484 266 dom->evtchn_fd = -1;
cl349@6484 267 goto out;
cl349@6484 268 }
cl349@6637 269 dom->local_port = local_port;
cl349@6474 270 }
cl349@6474 271
cl349@6474 272 out:
cl349@6474 273 return err;
cl349@6474 274 }
cl349@6474 275
cl349@6637 276 static bool watch_domain(struct domain *dom, bool watch)
cl349@6637 277 {
cl349@6637 278 char domid_str[3 + MAX_STRLEN(dom->domid)];
cl349@6637 279 bool success;
cl349@6637 280
cl349@6637 281 sprintf(domid_str, "dom%u", dom->domid);
cl349@6637 282 if (watch)
cl349@6637 283 success = xs_watch(xs, dom->conspath, domid_str);
cl349@6637 284 else
cl349@6637 285 success = xs_unwatch(xs, dom->conspath, domid_str);
cl349@6637 286 if (success)
cl349@6637 287 domain_create_ring(dom);
cl349@6637 288 return success;
cl349@6637 289 }
cl349@6637 290
kaf24@6038 291 static struct domain *create_domain(int domid)
kaf24@6038 292 {
kaf24@6038 293 struct domain *dom;
cl349@6673 294 char *s;
kaf24@6038 295
kaf24@6038 296 dom = (struct domain *)malloc(sizeof(struct domain));
kaf24@6038 297 if (dom == NULL) {
kaf24@6038 298 dolog(LOG_ERR, "Out of memory %s:%s():L%d",
kaf24@6038 299 __FILE__, __FUNCTION__, __LINE__);
kaf24@6038 300 exit(ENOMEM);
kaf24@6038 301 }
kaf24@6038 302
kaf24@6038 303 dom->domid = domid;
cl349@6676 304
cl349@6676 305 dom->conspath = xs_get_domain_path(xs, dom->domid);
cl349@6676 306 if (dom->conspath == NULL)
cl349@6676 307 goto out;
cl349@6676 308 s = realloc(dom->conspath, strlen(dom->conspath) +
cl349@6676 309 strlen("/console") + 1);
cl349@6676 310 if (s == NULL)
cl349@6676 311 goto out;
cl349@6676 312 dom->conspath = s;
cl349@6676 313 strcat(dom->conspath, "/console");
cl349@6676 314
kaf24@6038 315 dom->tty_fd = domain_create_tty(dom);
kaf24@6189 316 dom->is_dead = false;
kaf24@6038 317 dom->buffer.data = 0;
kaf24@6038 318 dom->buffer.size = 0;
kaf24@6038 319 dom->buffer.capacity = 0;
kaf24@6038 320 dom->buffer.max_capacity = 0;
cl349@6474 321 dom->next = NULL;
cl349@6474 322
cl349@6637 323 dom->ring_ref = -1;
cl349@6637 324 dom->local_port = -1;
cl349@6484 325 dom->page = NULL;
cl349@6484 326 dom->evtchn_fd = -1;
cl349@6484 327
cl349@6637 328 if (!watch_domain(dom, true))
cl349@6637 329 goto out;
cl349@6637 330
cl349@6637 331 dom->next = dom_head;
cl349@6637 332 dom_head = dom;
kaf24@6038 333
kaf24@6038 334 dolog(LOG_DEBUG, "New domain %d", domid);
kaf24@6038 335
kaf24@6038 336 return dom;
cl349@6637 337 out:
cl349@6637 338 if (dom->conspath)
cl349@6637 339 free(dom->conspath);
cl349@6637 340 free(dom);
cl349@6637 341 return NULL;
kaf24@6038 342 }
kaf24@6038 343
kaf24@6038 344 static struct domain *lookup_domain(int domid)
kaf24@6038 345 {
cl349@6484 346 struct domain *dom;
kaf24@6038 347
cl349@6484 348 for (dom = dom_head; dom; dom = dom->next)
cl349@6484 349 if (dom->domid == domid)
kaf24@6038 350 return dom;
cl349@6637 351 return NULL;
kaf24@6038 352 }
kaf24@6038 353
kaf24@6038 354 static void remove_domain(struct domain *dom)
kaf24@6038 355 {
kaf24@6038 356 struct domain **pp;
kaf24@6038 357
kaf24@6038 358 dolog(LOG_DEBUG, "Removing domain-%d", dom->domid);
kaf24@6038 359
kaf24@6038 360 for (pp = &dom_head; *pp; pp = &(*pp)->next) {
cl349@6637 361 if (dom == *pp) {
cl349@6637 362 *pp = dom->next;
cl349@6637 363 free(dom);
kaf24@6038 364 break;
kaf24@6038 365 }
kaf24@6038 366 }
kaf24@6038 367 }
kaf24@6038 368
cl349@6637 369 static void cleanup_domain(struct domain *d)
kaf24@6189 370 {
cl349@6637 371 if (!buffer_empty(&d->buffer))
cl349@6637 372 return;
kaf24@6189 373
cl349@6637 374 if (d->buffer.data)
cl349@6637 375 free(d->buffer.data);
cl349@6637 376 d->buffer.data = NULL;
cl349@6637 377 if (d->tty_fd != -1)
cl349@6637 378 close(d->tty_fd);
cl349@6637 379 d->tty_fd = -1;
cl349@6637 380 remove_domain(d);
cl349@6637 381 }
cl349@6637 382
cl349@6637 383 static void shutdown_domain(struct domain *d)
cl349@6637 384 {
cl349@6637 385 d->is_dead = true;
cl349@6637 386 watch_domain(d, false);
cl349@6637 387 if (d->page)
cl349@6637 388 munmap(d->page, getpagesize());
cl349@6637 389 d->page = NULL;
cl349@6637 390 if (d->evtchn_fd != -1)
cl349@6637 391 close(d->evtchn_fd);
cl349@6637 392 d->evtchn_fd = -1;
cl349@6637 393 cleanup_domain(d);
kaf24@6189 394 }
kaf24@6189 395
cl349@6484 396 void enum_domains(void)
cl349@6484 397 {
cl349@6484 398 int domid = 1;
cl349@6484 399 xc_dominfo_t dominfo;
cl349@6484 400 struct domain *dom;
cl349@6484 401
cl349@6484 402 while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
cl349@6484 403 dom = lookup_domain(dominfo.domid);
cl349@6637 404 if (dominfo.dying || dominfo.crashed || dominfo.shutdown) {
cl349@6637 405 if (dom)
cl349@6637 406 shutdown_domain(dom);
cl349@6637 407 } else {
cl349@6637 408 if (dom == NULL)
cl349@6637 409 create_domain(dominfo.domid);
cl349@6637 410 }
cl349@6484 411 domid = dominfo.domid + 1;
cl349@6484 412 }
cl349@6484 413 }
cl349@6484 414
kaf24@6038 415 static void handle_tty_read(struct domain *dom)
kaf24@6038 416 {
kaf24@6038 417 ssize_t len;
cl349@6474 418 char msg[80];
cl349@6474 419 struct ring_head *inring =
cl349@6474 420 (struct ring_head *)(dom->page + PAGE_SIZE/2);
cl349@6474 421 int i;
kaf24@6038 422
cl349@6544 423 len = read(dom->tty_fd, msg, MIN(XENCONS_SPACE(inring), sizeof(msg)));
kaf24@6038 424 if (len < 1) {
kaf24@6038 425 close(dom->tty_fd);
cl349@6474 426 dom->tty_fd = -1;
kaf24@6038 427
kaf24@6038 428 if (domain_is_valid(dom->domid)) {
kaf24@6038 429 dom->tty_fd = domain_create_tty(dom);
kaf24@6038 430 } else {
cl349@6637 431 shutdown_domain(dom);
kaf24@6038 432 }
kaf24@6038 433 } else if (domain_is_valid(dom->domid)) {
cl349@6474 434 for (i = 0; i < len; i++) {
cl349@6474 435 inring->buf[XENCONS_IDX(inring->prod)] = msg[i];
cl349@6474 436 inring->prod++;
kaf24@6038 437 }
cl349@6474 438 xc_evtchn_send(xc, dom->local_port);
kaf24@6038 439 } else {
kaf24@6038 440 close(dom->tty_fd);
cl349@6474 441 dom->tty_fd = -1;
cl349@6637 442 shutdown_domain(dom);
kaf24@6038 443 }
kaf24@6038 444 }
kaf24@6038 445
kaf24@6038 446 static void handle_tty_write(struct domain *dom)
kaf24@6038 447 {
kaf24@6038 448 ssize_t len;
kaf24@6038 449
kaf24@6038 450 len = write(dom->tty_fd, dom->buffer.data, dom->buffer.size);
kaf24@6038 451 if (len < 1) {
kaf24@6038 452 close(dom->tty_fd);
cl349@6474 453 dom->tty_fd = -1;
kaf24@6038 454
kaf24@6038 455 if (domain_is_valid(dom->domid)) {
kaf24@6038 456 dom->tty_fd = domain_create_tty(dom);
kaf24@6038 457 } else {
cl349@6637 458 shutdown_domain(dom);
kaf24@6038 459 }
kaf24@6038 460 } else {
kaf24@6038 461 buffer_advance(&dom->buffer, len);
kaf24@6038 462 }
kaf24@6038 463 }
kaf24@6038 464
cl349@6474 465 static void handle_ring_read(struct domain *dom)
cl349@6474 466 {
cl349@6474 467 u16 v;
cl349@6474 468
cl349@6474 469 if (!read_sync(dom->evtchn_fd, &v, sizeof(v)))
cl349@6474 470 return;
cl349@6474 471
cl349@6474 472 buffer_append(dom);
cl349@6474 473
cl349@6474 474 (void)write_sync(dom->evtchn_fd, &v, sizeof(v));
cl349@6474 475 }
cl349@6474 476
cl349@6484 477 static void handle_xs(int fd)
kaf24@6038 478 {
cl349@6484 479 char **vec;
cl349@6484 480 int domid;
cl349@6474 481 struct domain *dom;
kaf24@6038 482
cl349@6484 483 vec = xs_read_watch(xs);
cl349@6484 484 if (!vec)
cl349@6484 485 return;
cl349@6484 486
cl349@6648 487 if (!strcmp(vec[1], "domlist"))
cl349@6637 488 enum_domains();
cl349@6637 489 else if (sscanf(vec[1], "dom%u", &domid) == 1) {
cl349@6484 490 dom = lookup_domain(domid);
cl349@6637 491 if (dom->is_dead == false)
cl349@6484 492 domain_create_ring(dom);
kaf24@6038 493 }
cl349@6484 494
cl349@6484 495 xs_acknowledge_watch(xs, vec[1]);
cl349@6484 496 free(vec);
kaf24@6038 497 }
kaf24@6038 498
kaf24@6038 499 void handle_io(void)
kaf24@6038 500 {
kaf24@6038 501 fd_set readfds, writefds;
kaf24@6038 502 int ret;
kaf24@6038 503
kaf24@6038 504 do {
cl349@6637 505 struct domain *d, *n;
cl349@6484 506 struct timeval tv = { 100, 0 };
cl349@6474 507 int max_fd = -1;
kaf24@6038 508
kaf24@6038 509 FD_ZERO(&readfds);
kaf24@6038 510 FD_ZERO(&writefds);
kaf24@6038 511
cl349@6484 512 FD_SET(xs_fileno(xs), &readfds);
cl349@6484 513 max_fd = MAX(xs_fileno(xs), max_fd);
cl349@6484 514
kaf24@6038 515 for (d = dom_head; d; d = d->next) {
cl349@6637 516 if (d->evtchn_fd != -1) {
cl349@6474 517 FD_SET(d->evtchn_fd, &readfds);
cl349@6637 518 max_fd = MAX(d->evtchn_fd, max_fd);
kaf24@6038 519 }
kaf24@6038 520
cl349@6637 521 if (d->tty_fd != -1) {
cl349@6637 522 if (!d->is_dead)
cl349@6637 523 FD_SET(d->tty_fd, &readfds);
cl349@6637 524
cl349@6637 525 if (!buffer_empty(&d->buffer))
cl349@6637 526 FD_SET(d->tty_fd, &writefds);
cl349@6637 527 max_fd = MAX(d->tty_fd, max_fd);
cl349@6637 528 }
kaf24@6038 529 }
kaf24@6038 530
kaf24@6038 531 ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
cl349@6484 532
cl349@6484 533 if (FD_ISSET(xs_fileno(xs), &readfds))
cl349@6484 534 handle_xs(xs_fileno(xs));
kaf24@6038 535
cl349@6637 536 for (d = dom_head; d; d = n) {
cl349@6637 537 n = d->next;
cl349@6637 538 if (d->evtchn_fd != -1 &&
cl349@6637 539 FD_ISSET(d->evtchn_fd, &readfds))
cl349@6474 540 handle_ring_read(d);
cl349@6474 541
cl349@6637 542 if (d->tty_fd != -1) {
cl349@6637 543 if (FD_ISSET(d->tty_fd, &readfds))
cl349@6637 544 handle_tty_read(d);
cl349@6637 545
cl349@6637 546 if (FD_ISSET(d->tty_fd, &writefds))
cl349@6637 547 handle_tty_write(d);
cl349@6637 548
cl349@6637 549 if (d->is_dead)
cl349@6637 550 cleanup_domain(d);
cl349@6637 551 }
kaf24@6038 552 }
kaf24@6038 553 } while (ret > -1);
kaf24@6038 554 }