1*f206aabbSJeff Dike /* 2*f206aabbSJeff Dike * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 3*f206aabbSJeff Dike * Licensed under the GPL 4*f206aabbSJeff Dike */ 5*f206aabbSJeff Dike 6*f206aabbSJeff Dike #include <unistd.h> 7*f206aabbSJeff Dike #include <stdlib.h> 8*f206aabbSJeff Dike #include <termios.h> 9*f206aabbSJeff Dike #include <pty.h> 10*f206aabbSJeff Dike #include <signal.h> 11*f206aabbSJeff Dike #include <errno.h> 12*f206aabbSJeff Dike #include <string.h> 13*f206aabbSJeff Dike #include <sched.h> 14*f206aabbSJeff Dike #include <sys/socket.h> 15*f206aabbSJeff Dike #include <sys/poll.h> 16*f206aabbSJeff Dike #include "init.h" 17*f206aabbSJeff Dike #include "user.h" 18*f206aabbSJeff Dike #include "kern_util.h" 19*f206aabbSJeff Dike #include "user_util.h" 20*f206aabbSJeff Dike #include "sigio.h" 21*f206aabbSJeff Dike #include "os.h" 22*f206aabbSJeff Dike 23*f206aabbSJeff Dike /* Protected by sigio_lock(), also used by sigio_cleanup, which is an 24*f206aabbSJeff Dike * exitcall. 25*f206aabbSJeff Dike */ 26*f206aabbSJeff Dike static int write_sigio_pid = -1; 27*f206aabbSJeff Dike 28*f206aabbSJeff Dike /* These arrays are initialized before the sigio thread is started, and 29*f206aabbSJeff Dike * the descriptors closed after it is killed. So, it can't see them change. 30*f206aabbSJeff Dike * On the UML side, they are changed under the sigio_lock. 31*f206aabbSJeff Dike */ 32*f206aabbSJeff Dike static int write_sigio_fds[2] = { -1, -1 }; 33*f206aabbSJeff Dike static int sigio_private[2] = { -1, -1 }; 34*f206aabbSJeff Dike 35*f206aabbSJeff Dike struct pollfds { 36*f206aabbSJeff Dike struct pollfd *poll; 37*f206aabbSJeff Dike int size; 38*f206aabbSJeff Dike int used; 39*f206aabbSJeff Dike }; 40*f206aabbSJeff Dike 41*f206aabbSJeff Dike /* Protected by sigio_lock(). Used by the sigio thread, but the UML thread 42*f206aabbSJeff Dike * synchronizes with it. 43*f206aabbSJeff Dike */ 44*f206aabbSJeff Dike struct pollfds current_poll = { 45*f206aabbSJeff Dike .poll = NULL, 46*f206aabbSJeff Dike .size = 0, 47*f206aabbSJeff Dike .used = 0 48*f206aabbSJeff Dike }; 49*f206aabbSJeff Dike 50*f206aabbSJeff Dike struct pollfds next_poll = { 51*f206aabbSJeff Dike .poll = NULL, 52*f206aabbSJeff Dike .size = 0, 53*f206aabbSJeff Dike .used = 0 54*f206aabbSJeff Dike }; 55*f206aabbSJeff Dike 56*f206aabbSJeff Dike static int write_sigio_thread(void *unused) 57*f206aabbSJeff Dike { 58*f206aabbSJeff Dike struct pollfds *fds, tmp; 59*f206aabbSJeff Dike struct pollfd *p; 60*f206aabbSJeff Dike int i, n, respond_fd; 61*f206aabbSJeff Dike char c; 62*f206aabbSJeff Dike 63*f206aabbSJeff Dike signal(SIGWINCH, SIG_IGN); 64*f206aabbSJeff Dike fds = ¤t_poll; 65*f206aabbSJeff Dike while(1){ 66*f206aabbSJeff Dike n = poll(fds->poll, fds->used, -1); 67*f206aabbSJeff Dike if(n < 0){ 68*f206aabbSJeff Dike if(errno == EINTR) continue; 69*f206aabbSJeff Dike printk("write_sigio_thread : poll returned %d, " 70*f206aabbSJeff Dike "errno = %d\n", n, errno); 71*f206aabbSJeff Dike } 72*f206aabbSJeff Dike for(i = 0; i < fds->used; i++){ 73*f206aabbSJeff Dike p = &fds->poll[i]; 74*f206aabbSJeff Dike if(p->revents == 0) continue; 75*f206aabbSJeff Dike if(p->fd == sigio_private[1]){ 76*f206aabbSJeff Dike n = os_read_file(sigio_private[1], &c, sizeof(c)); 77*f206aabbSJeff Dike if(n != sizeof(c)) 78*f206aabbSJeff Dike printk("write_sigio_thread : " 79*f206aabbSJeff Dike "read failed, err = %d\n", -n); 80*f206aabbSJeff Dike tmp = current_poll; 81*f206aabbSJeff Dike current_poll = next_poll; 82*f206aabbSJeff Dike next_poll = tmp; 83*f206aabbSJeff Dike respond_fd = sigio_private[1]; 84*f206aabbSJeff Dike } 85*f206aabbSJeff Dike else { 86*f206aabbSJeff Dike respond_fd = write_sigio_fds[1]; 87*f206aabbSJeff Dike fds->used--; 88*f206aabbSJeff Dike memmove(&fds->poll[i], &fds->poll[i + 1], 89*f206aabbSJeff Dike (fds->used - i) * sizeof(*fds->poll)); 90*f206aabbSJeff Dike } 91*f206aabbSJeff Dike 92*f206aabbSJeff Dike n = os_write_file(respond_fd, &c, sizeof(c)); 93*f206aabbSJeff Dike if(n != sizeof(c)) 94*f206aabbSJeff Dike printk("write_sigio_thread : write failed, " 95*f206aabbSJeff Dike "err = %d\n", -n); 96*f206aabbSJeff Dike } 97*f206aabbSJeff Dike } 98*f206aabbSJeff Dike 99*f206aabbSJeff Dike return 0; 100*f206aabbSJeff Dike } 101*f206aabbSJeff Dike 102*f206aabbSJeff Dike static int need_poll(int n) 103*f206aabbSJeff Dike { 104*f206aabbSJeff Dike if(n <= next_poll.size){ 105*f206aabbSJeff Dike next_poll.used = n; 106*f206aabbSJeff Dike return(0); 107*f206aabbSJeff Dike } 108*f206aabbSJeff Dike kfree(next_poll.poll); 109*f206aabbSJeff Dike next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); 110*f206aabbSJeff Dike if(next_poll.poll == NULL){ 111*f206aabbSJeff Dike printk("need_poll : failed to allocate new pollfds\n"); 112*f206aabbSJeff Dike next_poll.size = 0; 113*f206aabbSJeff Dike next_poll.used = 0; 114*f206aabbSJeff Dike return(-1); 115*f206aabbSJeff Dike } 116*f206aabbSJeff Dike next_poll.size = n; 117*f206aabbSJeff Dike next_poll.used = n; 118*f206aabbSJeff Dike return(0); 119*f206aabbSJeff Dike } 120*f206aabbSJeff Dike 121*f206aabbSJeff Dike /* Must be called with sigio_lock held, because it's needed by the marked 122*f206aabbSJeff Dike * critical section. */ 123*f206aabbSJeff Dike static void update_thread(void) 124*f206aabbSJeff Dike { 125*f206aabbSJeff Dike unsigned long flags; 126*f206aabbSJeff Dike int n; 127*f206aabbSJeff Dike char c; 128*f206aabbSJeff Dike 129*f206aabbSJeff Dike flags = set_signals(0); 130*f206aabbSJeff Dike n = os_write_file(sigio_private[0], &c, sizeof(c)); 131*f206aabbSJeff Dike if(n != sizeof(c)){ 132*f206aabbSJeff Dike printk("update_thread : write failed, err = %d\n", -n); 133*f206aabbSJeff Dike goto fail; 134*f206aabbSJeff Dike } 135*f206aabbSJeff Dike 136*f206aabbSJeff Dike n = os_read_file(sigio_private[0], &c, sizeof(c)); 137*f206aabbSJeff Dike if(n != sizeof(c)){ 138*f206aabbSJeff Dike printk("update_thread : read failed, err = %d\n", -n); 139*f206aabbSJeff Dike goto fail; 140*f206aabbSJeff Dike } 141*f206aabbSJeff Dike 142*f206aabbSJeff Dike set_signals(flags); 143*f206aabbSJeff Dike return; 144*f206aabbSJeff Dike fail: 145*f206aabbSJeff Dike /* Critical section start */ 146*f206aabbSJeff Dike if(write_sigio_pid != -1) 147*f206aabbSJeff Dike os_kill_process(write_sigio_pid, 1); 148*f206aabbSJeff Dike write_sigio_pid = -1; 149*f206aabbSJeff Dike close(sigio_private[0]); 150*f206aabbSJeff Dike close(sigio_private[1]); 151*f206aabbSJeff Dike close(write_sigio_fds[0]); 152*f206aabbSJeff Dike close(write_sigio_fds[1]); 153*f206aabbSJeff Dike /* Critical section end */ 154*f206aabbSJeff Dike set_signals(flags); 155*f206aabbSJeff Dike } 156*f206aabbSJeff Dike 157*f206aabbSJeff Dike int add_sigio_fd(int fd, int read) 158*f206aabbSJeff Dike { 159*f206aabbSJeff Dike int err = 0, i, n, events; 160*f206aabbSJeff Dike 161*f206aabbSJeff Dike sigio_lock(); 162*f206aabbSJeff Dike for(i = 0; i < current_poll.used; i++){ 163*f206aabbSJeff Dike if(current_poll.poll[i].fd == fd) 164*f206aabbSJeff Dike goto out; 165*f206aabbSJeff Dike } 166*f206aabbSJeff Dike 167*f206aabbSJeff Dike n = current_poll.used + 1; 168*f206aabbSJeff Dike err = need_poll(n); 169*f206aabbSJeff Dike if(err) 170*f206aabbSJeff Dike goto out; 171*f206aabbSJeff Dike 172*f206aabbSJeff Dike for(i = 0; i < current_poll.used; i++) 173*f206aabbSJeff Dike next_poll.poll[i] = current_poll.poll[i]; 174*f206aabbSJeff Dike 175*f206aabbSJeff Dike if(read) events = POLLIN; 176*f206aabbSJeff Dike else events = POLLOUT; 177*f206aabbSJeff Dike 178*f206aabbSJeff Dike next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd, 179*f206aabbSJeff Dike .events = events, 180*f206aabbSJeff Dike .revents = 0 }); 181*f206aabbSJeff Dike update_thread(); 182*f206aabbSJeff Dike out: 183*f206aabbSJeff Dike sigio_unlock(); 184*f206aabbSJeff Dike return(err); 185*f206aabbSJeff Dike } 186*f206aabbSJeff Dike 187*f206aabbSJeff Dike int ignore_sigio_fd(int fd) 188*f206aabbSJeff Dike { 189*f206aabbSJeff Dike struct pollfd *p; 190*f206aabbSJeff Dike int err = 0, i, n = 0; 191*f206aabbSJeff Dike 192*f206aabbSJeff Dike sigio_lock(); 193*f206aabbSJeff Dike for(i = 0; i < current_poll.used; i++){ 194*f206aabbSJeff Dike if(current_poll.poll[i].fd == fd) break; 195*f206aabbSJeff Dike } 196*f206aabbSJeff Dike if(i == current_poll.used) 197*f206aabbSJeff Dike goto out; 198*f206aabbSJeff Dike 199*f206aabbSJeff Dike err = need_poll(current_poll.used - 1); 200*f206aabbSJeff Dike if(err) 201*f206aabbSJeff Dike goto out; 202*f206aabbSJeff Dike 203*f206aabbSJeff Dike for(i = 0; i < current_poll.used; i++){ 204*f206aabbSJeff Dike p = ¤t_poll.poll[i]; 205*f206aabbSJeff Dike if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i]; 206*f206aabbSJeff Dike } 207*f206aabbSJeff Dike if(n == i){ 208*f206aabbSJeff Dike printk("ignore_sigio_fd : fd %d not found\n", fd); 209*f206aabbSJeff Dike err = -1; 210*f206aabbSJeff Dike goto out; 211*f206aabbSJeff Dike } 212*f206aabbSJeff Dike 213*f206aabbSJeff Dike update_thread(); 214*f206aabbSJeff Dike out: 215*f206aabbSJeff Dike sigio_unlock(); 216*f206aabbSJeff Dike return(err); 217*f206aabbSJeff Dike } 218*f206aabbSJeff Dike 219*f206aabbSJeff Dike static struct pollfd *setup_initial_poll(int fd) 220*f206aabbSJeff Dike { 221*f206aabbSJeff Dike struct pollfd *p; 222*f206aabbSJeff Dike 223*f206aabbSJeff Dike p = um_kmalloc(sizeof(struct pollfd)); 224*f206aabbSJeff Dike if (p == NULL) { 225*f206aabbSJeff Dike printk("setup_initial_poll : failed to allocate poll\n"); 226*f206aabbSJeff Dike return NULL; 227*f206aabbSJeff Dike } 228*f206aabbSJeff Dike *p = ((struct pollfd) { .fd = fd, 229*f206aabbSJeff Dike .events = POLLIN, 230*f206aabbSJeff Dike .revents = 0 }); 231*f206aabbSJeff Dike return p; 232*f206aabbSJeff Dike } 233*f206aabbSJeff Dike 234*f206aabbSJeff Dike void write_sigio_workaround(void) 235*f206aabbSJeff Dike { 236*f206aabbSJeff Dike unsigned long stack; 237*f206aabbSJeff Dike struct pollfd *p; 238*f206aabbSJeff Dike int err; 239*f206aabbSJeff Dike int l_write_sigio_fds[2]; 240*f206aabbSJeff Dike int l_sigio_private[2]; 241*f206aabbSJeff Dike int l_write_sigio_pid; 242*f206aabbSJeff Dike 243*f206aabbSJeff Dike /* We call this *tons* of times - and most ones we must just fail. */ 244*f206aabbSJeff Dike sigio_lock(); 245*f206aabbSJeff Dike l_write_sigio_pid = write_sigio_pid; 246*f206aabbSJeff Dike sigio_unlock(); 247*f206aabbSJeff Dike 248*f206aabbSJeff Dike if (l_write_sigio_pid != -1) 249*f206aabbSJeff Dike return; 250*f206aabbSJeff Dike 251*f206aabbSJeff Dike err = os_pipe(l_write_sigio_fds, 1, 1); 252*f206aabbSJeff Dike if(err < 0){ 253*f206aabbSJeff Dike printk("write_sigio_workaround - os_pipe 1 failed, " 254*f206aabbSJeff Dike "err = %d\n", -err); 255*f206aabbSJeff Dike return; 256*f206aabbSJeff Dike } 257*f206aabbSJeff Dike err = os_pipe(l_sigio_private, 1, 1); 258*f206aabbSJeff Dike if(err < 0){ 259*f206aabbSJeff Dike printk("write_sigio_workaround - os_pipe 2 failed, " 260*f206aabbSJeff Dike "err = %d\n", -err); 261*f206aabbSJeff Dike goto out_close1; 262*f206aabbSJeff Dike } 263*f206aabbSJeff Dike 264*f206aabbSJeff Dike p = setup_initial_poll(l_sigio_private[1]); 265*f206aabbSJeff Dike if(!p) 266*f206aabbSJeff Dike goto out_close2; 267*f206aabbSJeff Dike 268*f206aabbSJeff Dike sigio_lock(); 269*f206aabbSJeff Dike 270*f206aabbSJeff Dike /* Did we race? Don't try to optimize this, please, it's not so likely 271*f206aabbSJeff Dike * to happen, and no more than once at the boot. */ 272*f206aabbSJeff Dike if(write_sigio_pid != -1) 273*f206aabbSJeff Dike goto out_unlock; 274*f206aabbSJeff Dike 275*f206aabbSJeff Dike write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, 276*f206aabbSJeff Dike CLONE_FILES | CLONE_VM, &stack, 0); 277*f206aabbSJeff Dike 278*f206aabbSJeff Dike if (write_sigio_pid < 0) 279*f206aabbSJeff Dike goto out_clear; 280*f206aabbSJeff Dike 281*f206aabbSJeff Dike if (write_sigio_irq(l_write_sigio_fds[0])) 282*f206aabbSJeff Dike goto out_kill; 283*f206aabbSJeff Dike 284*f206aabbSJeff Dike /* Success, finally. */ 285*f206aabbSJeff Dike memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); 286*f206aabbSJeff Dike memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); 287*f206aabbSJeff Dike 288*f206aabbSJeff Dike current_poll = ((struct pollfds) { .poll = p, 289*f206aabbSJeff Dike .used = 1, 290*f206aabbSJeff Dike .size = 1 }); 291*f206aabbSJeff Dike 292*f206aabbSJeff Dike sigio_unlock(); 293*f206aabbSJeff Dike return; 294*f206aabbSJeff Dike 295*f206aabbSJeff Dike out_kill: 296*f206aabbSJeff Dike l_write_sigio_pid = write_sigio_pid; 297*f206aabbSJeff Dike write_sigio_pid = -1; 298*f206aabbSJeff Dike sigio_unlock(); 299*f206aabbSJeff Dike /* Going to call waitpid, avoid holding the lock. */ 300*f206aabbSJeff Dike os_kill_process(l_write_sigio_pid, 1); 301*f206aabbSJeff Dike goto out_free; 302*f206aabbSJeff Dike 303*f206aabbSJeff Dike out_clear: 304*f206aabbSJeff Dike write_sigio_pid = -1; 305*f206aabbSJeff Dike out_unlock: 306*f206aabbSJeff Dike sigio_unlock(); 307*f206aabbSJeff Dike out_free: 308*f206aabbSJeff Dike kfree(p); 309*f206aabbSJeff Dike out_close2: 310*f206aabbSJeff Dike close(l_sigio_private[0]); 311*f206aabbSJeff Dike close(l_sigio_private[1]); 312*f206aabbSJeff Dike out_close1: 313*f206aabbSJeff Dike close(l_write_sigio_fds[0]); 314*f206aabbSJeff Dike close(l_write_sigio_fds[1]); 315*f206aabbSJeff Dike return; 316*f206aabbSJeff Dike } 317*f206aabbSJeff Dike 318*f206aabbSJeff Dike void sigio_cleanup(void) 319*f206aabbSJeff Dike { 320*f206aabbSJeff Dike if(write_sigio_pid != -1){ 321*f206aabbSJeff Dike os_kill_process(write_sigio_pid, 1); 322*f206aabbSJeff Dike write_sigio_pid = -1; 323*f206aabbSJeff Dike } 324*f206aabbSJeff Dike } 325