sigio.c revision c65badbdf5dc117e45873e760f807063ad59a854
18e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Licensed under the GPL 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <unistd.h> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <stdlib.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <termios.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <pty.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <signal.h> 11c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike#include <fcntl.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <errno.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <string.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sched.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/socket.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/poll.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "init.h" 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "user.h" 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "kern_util.h" 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "user_util.h" 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sigio.h" 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "os.h" 23c13e569073b89eb75216a2551e89ae93ad1f9951Paolo 'Blaisorblade' Giarrusso#include "um_malloc.h" 24c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike#include "init.h" 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26f206aabb035318ac4bafbf0b87798335de3634dfJeff Dike/* Protected by sigio_lock(), also used by sigio_cleanup, which is an 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * exitcall. 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int write_sigio_pid = -1; 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These arrays are initialized before the sigio thread is started, and 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the descriptors closed after it is killed. So, it can't see them change. 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * On the UML side, they are changed under the sigio_lock. 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 355f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike#define SIGIO_FDS_INIT {-1, -1} 365f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike 375f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dikestatic int write_sigio_fds[2] = SIGIO_FDS_INIT; 385f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dikestatic int sigio_private[2] = SIGIO_FDS_INIT; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pollfds { 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pollfd *poll; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int used; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * synchronizes with it. 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4919bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dikestatic struct pollfds current_poll; 5019bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dikestatic struct pollfds next_poll; 5119bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dikestatic struct pollfds all_sigio_fds; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int write_sigio_thread(void *unused) 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pollfds *fds, tmp; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pollfd *p; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, n, respond_fd; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char c; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 60cd2ee4a30cc0775d8b54e5b958613361a7cacfecJeff Dike signal(SIGWINCH, SIG_IGN); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fds = ¤t_poll; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(1){ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = poll(fds->poll, fds->used, -1); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n < 0){ 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(errno == EINTR) continue; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("write_sigio_thread : poll returned %d, " 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "errno = %d\n", n, errno); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < fds->used; i++){ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = &fds->poll[i]; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(p->revents == 0) continue; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(p->fd == sigio_private[1]){ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = os_read_file(sigio_private[1], &c, sizeof(c)); 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n != sizeof(c)) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("write_sigio_thread : " 7619bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike "read on socket failed, " 7719bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike "err = %d\n", -n); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = current_poll; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_poll = next_poll; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_poll = tmp; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds respond_fd = sigio_private[1]; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds respond_fd = write_sigio_fds[1]; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fds->used--; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(&fds->poll[i], &fds->poll[i + 1], 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (fds->used - i) * sizeof(*fds->poll)); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = os_write_file(respond_fd, &c, sizeof(c)); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n != sizeof(c)) 9219bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike printk("write_sigio_thread : write on socket " 9319bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike "failed, err = %d\n", -n); 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 961b57e9c27882a908f180d4daf72ee12c6f137178Jeff Dike 971b57e9c27882a908f180d4daf72ee12c6f137178Jeff Dike return 0; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10019bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dikestatic int need_poll(struct pollfds *polls, int n) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 102838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike struct pollfd *new; 103838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike 104838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike if(n <= polls->size) 10519bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike return 0; 106838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike 107838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike new = um_kmalloc_atomic(n * sizeof(struct pollfd)); 108838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike if(new == NULL){ 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("need_poll : failed to allocate new pollfds\n"); 11019bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike return -ENOMEM; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 112838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike 113838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike memcpy(new, polls->poll, polls->used * sizeof(struct pollfd)); 114838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike kfree(polls->poll); 115838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike 116838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike polls->poll = new; 11719bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike polls->size = n; 11819bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike return 0; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Must be called with sigio_lock held, because it's needed by the marked 12219bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike * critical section. 12319bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike */ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void update_thread(void) 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char c; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags = set_signals(0); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = os_write_file(sigio_private[0], &c, sizeof(c)); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n != sizeof(c)){ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("update_thread : write failed, err = %d\n", -n); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = os_read_file(sigio_private[0], &c, sizeof(c)); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n != sizeof(c)){ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("update_thread : read failed, err = %d\n", -n); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_signals(flags); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fail: 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Critical section start */ 147f206aabb035318ac4bafbf0b87798335de3634dfJeff Dike if(write_sigio_pid != -1) 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds os_kill_process(write_sigio_pid, 1); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_sigio_pid = -1; 1508e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(sigio_private[0]); 1518e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(sigio_private[1]); 1528e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(write_sigio_fds[0]); 1538e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(write_sigio_fds[1]); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Critical section end */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_signals(flags); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15819bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dikeint add_sigio_fd(int fd) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16019bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike struct pollfd *p; 16119bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike int err = 0, i, n; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_lock(); 16419bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike for(i = 0; i < all_sigio_fds.used; i++){ 16519bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike if(all_sigio_fds.poll[i].fd == fd) 16619bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike break; 16719bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike } 16819bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike if(i == all_sigio_fds.used) 16919bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike goto out; 17019bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike 17119bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike p = &all_sigio_fds.poll[i]; 17219bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < current_poll.used; i++){ 174f206aabb035318ac4bafbf0b87798335de3634dfJeff Dike if(current_poll.poll[i].fd == fd) 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 178838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike n = current_poll.used; 179838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike err = need_poll(&next_poll, n + 1); 180f206aabb035318ac4bafbf0b87798335de3634dfJeff Dike if(err) 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 183838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike memcpy(next_poll.poll, current_poll.poll, 184838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike current_poll.used * sizeof(struct pollfd)); 185838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike next_poll.poll[n] = *p; 186838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike next_poll.used = n + 1; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds update_thread(); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_unlock(); 19019bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike return err; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ignore_sigio_fd(int fd) 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pollfd *p; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0, i, n = 0; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19861232f2fe44f7ac12d7512d099a8f10923eff7eaJeff Dike /* This is called from exitcalls elsewhere in UML - if 19961232f2fe44f7ac12d7512d099a8f10923eff7eaJeff Dike * sigio_cleanup has already run, then update_thread will hang 20061232f2fe44f7ac12d7512d099a8f10923eff7eaJeff Dike * or fail because the thread is no longer running. 20161232f2fe44f7ac12d7512d099a8f10923eff7eaJeff Dike */ 20261232f2fe44f7ac12d7512d099a8f10923eff7eaJeff Dike if(write_sigio_pid == -1) 20361232f2fe44f7ac12d7512d099a8f10923eff7eaJeff Dike return -EIO; 20461232f2fe44f7ac12d7512d099a8f10923eff7eaJeff Dike 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_lock(); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < current_poll.used; i++){ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(current_poll.poll[i].fd == fd) break; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i == current_poll.used) 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 211f206aabb035318ac4bafbf0b87798335de3634dfJeff Dike 21219bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike err = need_poll(&next_poll, current_poll.used - 1); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(err) 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < current_poll.used; i++){ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = ¤t_poll.poll[i]; 21819bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike if(p->fd != fd) 21919bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike next_poll.poll[n++] = *p; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 221838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike next_poll.used = current_poll.used - 1; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds update_thread(); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_unlock(); 22661232f2fe44f7ac12d7512d099a8f10923eff7eaJeff Dike return err; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 229f206aabb035318ac4bafbf0b87798335de3634dfJeff Dikestatic struct pollfd *setup_initial_poll(int fd) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pollfd *p; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 233b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso p = um_kmalloc(sizeof(struct pollfd)); 234b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if (p == NULL) { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("setup_initial_poll : failed to allocate poll\n"); 236b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso return NULL; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23819bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike *p = ((struct pollfd) { .fd = fd, 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .events = POLLIN, 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .revents = 0 }); 241b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso return p; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2448e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dikestatic void write_sigio_workaround(void) 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long stack; 247b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso struct pollfd *p; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 249b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso int l_write_sigio_fds[2]; 250b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso int l_sigio_private[2]; 251b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso int l_write_sigio_pid; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 253b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso /* We call this *tons* of times - and most ones we must just fail. */ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_lock(); 255b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso l_write_sigio_pid = write_sigio_pid; 256b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso sigio_unlock(); 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 258b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if (l_write_sigio_pid != -1) 259b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso return; 260b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 261b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso err = os_pipe(l_write_sigio_fds, 1, 1); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(err < 0){ 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("write_sigio_workaround - os_pipe 1 failed, " 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "err = %d\n", -err); 265b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso return; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 267b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso err = os_pipe(l_sigio_private, 1, 1); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(err < 0){ 269f206aabb035318ac4bafbf0b87798335de3634dfJeff Dike printk("write_sigio_workaround - os_pipe 2 failed, " 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "err = %d\n", -err); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_close1; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 273b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 274b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso p = setup_initial_poll(l_sigio_private[1]); 275b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if(!p) 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_close2; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 278b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso sigio_lock(); 279b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 280b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso /* Did we race? Don't try to optimize this, please, it's not so likely 281b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso * to happen, and no more than once at the boot. */ 282b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if(write_sigio_pid != -1) 2835f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike goto out_free; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2855f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike current_poll = ((struct pollfds) { .poll = p, 2865f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike .used = 1, 2875f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike .size = 1 }); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if (write_sigio_irq(l_write_sigio_fds[0])) 2905f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike goto out_clear_poll; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 292b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); 293b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); 294b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 2955f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, 2965f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike CLONE_FILES | CLONE_VM, &stack, 0); 297b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 2985f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike if (write_sigio_pid < 0) 2995f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike goto out_clear; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso sigio_unlock(); 3025f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike return; 303b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 3045f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dikeout_clear: 305b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso write_sigio_pid = -1; 3065f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike write_sigio_fds[0] = -1; 3075f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike write_sigio_fds[1] = -1; 3085f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike sigio_private[0] = -1; 3095f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike sigio_private[1] = -1; 3105f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dikeout_clear_poll: 3115f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike current_poll = ((struct pollfds) { .poll = NULL, 3125f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike .size = 0, 3135f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike .used = 0 }); 3145f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dikeout_free: 3155f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dike sigio_unlock(); 316e6fb54abb8a36703f54b7e27a756a3df6667c37bPaolo 'Blaisorblade' Giarrusso kfree(p); 3175f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dikeout_close2: 3188e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(l_sigio_private[0]); 3198e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(l_sigio_private[1]); 3205f4e8fd08f3993bc31a7dd91767fdb4da4fe6278Jeff Dikeout_close1: 3218e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(l_write_sigio_fds[0]); 3228e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(l_write_sigio_fds[1]); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 325c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike/* Changed during early boot */ 326c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikestatic int pty_output_sigio = 0; 327c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikestatic int pty_close_sigio = 0; 328c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 3298e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dikevoid maybe_sigio_broken(int fd, int read) 3308e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dike{ 33119bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike int err; 33219bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike 3338e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dike if(!isatty(fd)) 3348e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dike return; 3358e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dike 3368e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dike if((read || pty_output_sigio) && (!read || pty_close_sigio)) 3378e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dike return; 3388e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dike 3398e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dike write_sigio_workaround(); 34019bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike 34119bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike sigio_lock(); 34219bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1); 34304a51e66adcdc0de6ffaa488934ce3ffb3818ecfJeff Dike if(err){ 34404a51e66adcdc0de6ffaa488934ce3ffb3818ecfJeff Dike printk("maybe_sigio_broken - failed to add pollfd for " 34504a51e66adcdc0de6ffaa488934ce3ffb3818ecfJeff Dike "descriptor %d\n", fd); 34619bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike goto out; 34704a51e66adcdc0de6ffaa488934ce3ffb3818ecfJeff Dike } 348838e56a11cdb2abaf490eb7879ab021db938d47dJeff Dike 34919bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike all_sigio_fds.poll[all_sigio_fds.used++] = 35019bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike ((struct pollfd) { .fd = fd, 35119bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike .events = read ? POLLIN : POLLOUT, 35219bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike .revents = 0 }); 35319bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dikeout: 35419bdf0409f25a85a45874a5a8da6f3e4edcf4a49Jeff Dike sigio_unlock(); 3558e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dike} 3568e64d96aeb495709c13307e2d79f3ee37e96aa4eJeff Dike 35729ac1c2142346e1e0e072f41df31688fc42ff540Jeff Dikestatic void sigio_cleanup(void) 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 359f206aabb035318ac4bafbf0b87798335de3634dfJeff Dike if(write_sigio_pid != -1){ 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds os_kill_process(write_sigio_pid, 1); 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_sigio_pid = -1; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 36429ac1c2142346e1e0e072f41df31688fc42ff540Jeff Dike 36529ac1c2142346e1e0e072f41df31688fc42ff540Jeff Dike__uml_exitcall(sigio_cleanup); 366c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 367c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike/* Used as a flag during SIGIO testing early in boot */ 368c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikestatic volatile int got_sigio = 0; 369c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 370c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikestatic void __init handler(int sig) 371c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike{ 372c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike got_sigio = 1; 373c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike} 374c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 375c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikestruct openpty_arg { 376c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike int master; 377c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike int slave; 378c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike int err; 379c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike}; 380c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 381c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikestatic void openpty_cb(void *arg) 382c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike{ 383c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike struct openpty_arg *info = arg; 384c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 385c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike info->err = 0; 386c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) 387c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike info->err = -errno; 388c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike} 389c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 390c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikestatic int async_pty(int master, int slave) 391c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike{ 392c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike int flags; 393c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 394c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike flags = fcntl(master, F_GETFL); 395c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if(flags < 0) 396c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike return -errno; 397c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 398c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || 399c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike (fcntl(master, F_SETOWN, os_getpid()) < 0)) 400c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike return -errno; 401c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 402c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) 403c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike return -errno; 404c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 405c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike return(0); 406c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike} 407c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 408c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikestatic void __init check_one_sigio(void (*proc)(int, int)) 409c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike{ 410c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike struct sigaction old, new; 411c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike struct openpty_arg pty = { .master = -1, .slave = -1 }; 412c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike int master, slave, err; 413c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 414c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike initial_thread_cb(openpty_cb, &pty); 415c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if(pty.err){ 416c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike printk("openpty failed, errno = %d\n", -pty.err); 417c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike return; 418c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike } 419c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 420c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike master = pty.master; 421c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike slave = pty.slave; 422c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 423c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if((master == -1) || (slave == -1)){ 424c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike printk("openpty failed to allocate a pty\n"); 425c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike return; 426c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike } 427c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 428c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike /* Not now, but complain so we now where we failed. */ 429c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike err = raw(master); 430c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if (err < 0) 431c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike panic("check_sigio : __raw failed, errno = %d\n", -err); 432c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 433c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike err = async_pty(master, slave); 434c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if(err < 0) 435c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike panic("tty_fds : sigio_async failed, err = %d\n", -err); 436c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 437c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if(sigaction(SIGIO, NULL, &old) < 0) 438c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); 439c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike new = old; 440c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike new.sa_handler = handler; 441c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if(sigaction(SIGIO, &new, NULL) < 0) 442c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); 443c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 444c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike got_sigio = 0; 445c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike (*proc)(master, slave); 446c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 447c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike close(master); 448c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike close(slave); 449c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 450c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if(sigaction(SIGIO, &old, NULL) < 0) 451c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); 452c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike} 453c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 454c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikestatic void tty_output(int master, int slave) 455c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike{ 456c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike int n; 457c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike char buf[512]; 458c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 459c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike printk("Checking that host ptys support output SIGIO..."); 460c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 461c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike memset(buf, 0, sizeof(buf)); 462c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 463c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike while(os_write_file(master, buf, sizeof(buf)) > 0) ; 464c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if(errno != EAGAIN) 465c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike panic("check_sigio : write failed, errno = %d\n", errno); 466c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; 467c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 468c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if(got_sigio){ 469c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike printk("Yes\n"); 470c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike pty_output_sigio = 1; 471c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike } 472c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike else if(n == -EAGAIN) printk("No, enabling workaround\n"); 473c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike else panic("check_sigio : read failed, err = %d\n", n); 474c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike} 475c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 476c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikestatic void tty_close(int master, int slave) 477c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike{ 478c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike printk("Checking that host ptys support SIGIO on close..."); 479c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 480c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike close(slave); 481c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if(got_sigio){ 482c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike printk("Yes\n"); 483c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike pty_close_sigio = 1; 484c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike } 485c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike else printk("No, enabling workaround\n"); 486c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike} 487c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 488c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikevoid __init check_sigio(void) 489c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike{ 490c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && 491c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ 492c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike printk("No pseudo-terminals available - skipping pty SIGIO " 493c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike "check\n"); 494c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike return; 495c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike } 496c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike check_one_sigio(tty_output); 497c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike check_one_sigio(tty_close); 498c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike} 499c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike 500c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike/* Here because it only does the SIGIO testing for now */ 501c65badbdf5dc117e45873e760f807063ad59a854Jeff Dikevoid __init os_check_bugs(void) 502c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike{ 503c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike check_sigio(); 504c65badbdf5dc117e45873e760f807063ad59a854Jeff Dike} 505