ia64/xen-unstable

annotate tools/console/daemon/io.c @ 8264:eae64901e428

Remove timeout on select -- there is no need for it, since we don't do anything
in the main loop except service I/O.

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