sigio.c revision 8e367065eea04a6fde5cb8f3854164af99c45693
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> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <errno.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <string.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sched.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/socket.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/poll.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "init.h" 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "user.h" 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "kern_util.h" 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "user_util.h" 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sigio.h" 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "os.h" 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Protected by sigio_lock(), also used by sigio_cleanup, which is an 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * exitcall. 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int write_sigio_pid = -1; 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These arrays are initialized before the sigio thread is started, and 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the descriptors closed after it is killed. So, it can't see them change. 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * On the UML side, they are changed under the sigio_lock. 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int write_sigio_fds[2] = { -1, -1 }; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sigio_private[2] = { -1, -1 }; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pollfds { 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pollfd *poll; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int used; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * synchronizes with it. 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pollfds current_poll = { 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .poll = NULL, 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .size = 0, 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .used = 0 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pollfds next_poll = { 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .poll = NULL, 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .size = 0, 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .used = 0 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int write_sigio_thread(void *unused) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pollfds *fds, tmp; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pollfd *p; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, n, respond_fd; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char c; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 63cd2ee4a30cc0775d8b54e5b958613361a7cacfecJeff Dike signal(SIGWINCH, SIG_IGN); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fds = ¤t_poll; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while(1){ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = poll(fds->poll, fds->used, -1); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n < 0){ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(errno == EINTR) continue; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("write_sigio_thread : poll returned %d, " 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "errno = %d\n", n, errno); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < fds->used; i++){ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = &fds->poll[i]; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(p->revents == 0) continue; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(p->fd == sigio_private[1]){ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = os_read_file(sigio_private[1], &c, sizeof(c)); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n != sizeof(c)) 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("write_sigio_thread : " 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "read failed, err = %d\n", -n); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = current_poll; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_poll = next_poll; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_poll = tmp; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds respond_fd = sigio_private[1]; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds respond_fd = write_sigio_fds[1]; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fds->used--; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(&fds->poll[i], &fds->poll[i + 1], 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (fds->used - i) * sizeof(*fds->poll)); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = os_write_file(respond_fd, &c, sizeof(c)); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n != sizeof(c)) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("write_sigio_thread : write failed, " 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "err = %d\n", -n); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 981b57e9c27882a908f180d4daf72ee12c6f137178Jeff Dike 991b57e9c27882a908f180d4daf72ee12c6f137178Jeff Dike return 0; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int need_poll(int n) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n <= next_poll.size){ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_poll.used = n; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(0); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 108b2325fe1b7e5654fac9e9419423aa2c58a3dbd83Jesper Juhl kfree(next_poll.poll); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(next_poll.poll == NULL){ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("need_poll : failed to allocate new pollfds\n"); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_poll.size = 0; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_poll.used = 0; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(-1); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_poll.size = n; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_poll.used = n; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(0); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Must be called with sigio_lock held, because it's needed by the marked 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * critical section. */ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void update_thread(void) 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char c; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags = set_signals(0); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = os_write_file(sigio_private[0], &c, sizeof(c)); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n != sizeof(c)){ 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("update_thread : write failed, err = %d\n", -n); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = os_read_file(sigio_private[0], &c, sizeof(c)); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n != sizeof(c)){ 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("update_thread : read failed, err = %d\n", -n); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_signals(flags); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fail: 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Critical section start */ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(write_sigio_pid != -1) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds os_kill_process(write_sigio_pid, 1); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_sigio_pid = -1; 1498e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(sigio_private[0]); 1508e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(sigio_private[1]); 1518e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(write_sigio_fds[0]); 1528e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(write_sigio_fds[1]); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Critical section end */ 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_signals(flags); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint add_sigio_fd(int fd, int read) 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0, i, n, events; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_lock(); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < current_poll.used; i++){ 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(current_poll.poll[i].fd == fd) 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n = current_poll.used + 1; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = need_poll(n); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(err) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < current_poll.used; i++) 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_poll.poll[i] = current_poll.poll[i]; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(read) events = POLLIN; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else events = POLLOUT; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd, 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .events = events, 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .revents = 0 }); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds update_thread(); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_unlock(); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(err); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint ignore_sigio_fd(int fd) 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pollfd *p; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0, i, n = 0; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_lock(); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < current_poll.used; i++){ 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(current_poll.poll[i].fd == fd) break; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(i == current_poll.used) 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = need_poll(current_poll.used - 1); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(err) 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < current_poll.used; i++){ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = ¤t_poll.poll[i]; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i]; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(n == i){ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("ignore_sigio_fd : fd %d not found\n", fd); 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -1; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds update_thread(); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_unlock(); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(err); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 219b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrussostatic struct pollfd* setup_initial_poll(int fd) 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pollfd *p; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 223b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso p = um_kmalloc(sizeof(struct pollfd)); 224b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if (p == NULL) { 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("setup_initial_poll : failed to allocate poll\n"); 226b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso return NULL; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *p = ((struct pollfd) { .fd = fd, 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .events = POLLIN, 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .revents = 0 }); 231b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso return p; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid write_sigio_workaround(void) 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long stack; 237b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso struct pollfd *p; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 239b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso int l_write_sigio_fds[2]; 240b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso int l_sigio_private[2]; 241b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso int l_write_sigio_pid; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 243b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso /* We call this *tons* of times - and most ones we must just fail. */ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_lock(); 245b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso l_write_sigio_pid = write_sigio_pid; 246b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso sigio_unlock(); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 248b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if (l_write_sigio_pid != -1) 249b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso return; 250b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 251b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso err = os_pipe(l_write_sigio_fds, 1, 1); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(err < 0){ 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("write_sigio_workaround - os_pipe 1 failed, " 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "err = %d\n", -err); 255b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso return; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 257b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso err = os_pipe(l_sigio_private, 1, 1); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(err < 0){ 259b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso printk("write_sigio_workaround - os_pipe 1 failed, " 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "err = %d\n", -err); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_close1; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 263b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 264b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso p = setup_initial_poll(l_sigio_private[1]); 265b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if(!p) 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_close2; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 268b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso sigio_lock(); 269b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 270b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso /* Did we race? Don't try to optimize this, please, it's not so likely 271b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso * to happen, and no more than once at the boot. */ 272b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if(write_sigio_pid != -1) 273b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso goto out_unlock; 274b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 275b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CLONE_FILES | CLONE_VM, &stack, 0); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 278b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if (write_sigio_pid < 0) 279b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso goto out_clear; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso if (write_sigio_irq(l_write_sigio_fds[0])) 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_kill; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 284b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso /* Success, finally. */ 285b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); 286b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); 287b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 288b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso current_poll = ((struct pollfds) { .poll = p, 289b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso .used = 1, 290b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso .size = 1 }); 291b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigio_unlock(); 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_kill: 296b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso l_write_sigio_pid = write_sigio_pid; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_sigio_pid = -1; 298b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso sigio_unlock(); 299b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso /* Going to call waitpid, avoid holding the lock. */ 300b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso os_kill_process(l_write_sigio_pid, 1); 301b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso goto out_free; 302b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso 303b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso out_clear: 304b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso write_sigio_pid = -1; 305b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso out_unlock: 306b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso sigio_unlock(); 307b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso out_free: 308b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso kfree(p); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_close2: 3108e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(l_sigio_private[0]); 3118e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(l_sigio_private[1]); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out_close1: 3138e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(l_write_sigio_fds[0]); 3148e367065eea04a6fde5cb8f3854164af99c45693Jeff Dike close(l_write_sigio_fds[1]); 315b6a2b13778873bd9edd0b4a7d24a7bd730369021Paolo 'Blaisorblade' Giarrusso return; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3188e367065eea04a6fde5cb8f3854164af99c45693Jeff Dikevoid sigio_cleanup(void) 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (write_sigio_pid != -1) { 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds os_kill_process(write_sigio_pid, 1); 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds write_sigio_pid = -1; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 325