1 /* 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 3 * Licensed under the GPL 4 */ 5 6 #include <stdlib.h> 7 #include <unistd.h> 8 #include <errno.h> 9 #include <signal.h> 10 #include <string.h> 11 #include <sys/poll.h> 12 #include <sys/types.h> 13 #include <sys/time.h> 14 #include "user_util.h" 15 #include "kern_util.h" 16 #include "user.h" 17 #include "process.h" 18 #include "sigio.h" 19 #include "irq_user.h" 20 #include "os.h" 21 22 static struct pollfd *pollfds = NULL; 23 static int pollfds_num = 0; 24 static int pollfds_size = 0; 25 26 int os_waiting_for_events(struct irq_fd *active_fds) 27 { 28 struct irq_fd *irq_fd; 29 int i, n, err; 30 31 n = poll(pollfds, pollfds_num, 0); 32 if (n < 0) { 33 err = -errno; 34 if (errno != EINTR) 35 printk("sigio_handler: os_waiting_for_events:" 36 " poll returned %d, errno = %d\n", n, errno); 37 return err; 38 } 39 40 if (n == 0) 41 return 0; 42 43 irq_fd = active_fds; 44 45 for (i = 0; i < pollfds_num; i++) { 46 if (pollfds[i].revents != 0) { 47 irq_fd->current_events = pollfds[i].revents; 48 pollfds[i].fd = -1; 49 } 50 irq_fd = irq_fd->next; 51 } 52 return n; 53 } 54 55 int os_isatty(int fd) 56 { 57 return isatty(fd); 58 } 59 60 int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds) 61 { 62 if (pollfds_num == pollfds_size) { 63 if (size_tmpfds <= pollfds_size * sizeof(pollfds[0])) { 64 /* return min size needed for new pollfds area */ 65 return((pollfds_size + 1) * sizeof(pollfds[0])); 66 } 67 68 if (pollfds != NULL) { 69 memcpy(tmp_pfd, pollfds, 70 sizeof(pollfds[0]) * pollfds_size); 71 /* remove old pollfds */ 72 kfree(pollfds); 73 } 74 pollfds = tmp_pfd; 75 pollfds_size++; 76 } else 77 kfree(tmp_pfd); /* remove not used tmp_pfd */ 78 79 pollfds[pollfds_num] = ((struct pollfd) { .fd = fd, 80 .events = events, 81 .revents = 0 }); 82 pollfds_num++; 83 84 return 0; 85 } 86 87 void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg, 88 struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2) 89 { 90 struct irq_fd **prev; 91 int i = 0; 92 93 prev = &active_fds; 94 while (*prev != NULL) { 95 if ((*test)(*prev, arg)) { 96 struct irq_fd *old_fd = *prev; 97 if ((pollfds[i].fd != -1) && 98 (pollfds[i].fd != (*prev)->fd)) { 99 printk("os_free_irq_by_cb - mismatch between " 100 "active_fds and pollfds, fd %d vs %d\n", 101 (*prev)->fd, pollfds[i].fd); 102 goto out; 103 } 104 105 pollfds_num--; 106 107 /* This moves the *whole* array after pollfds[i] 108 * (though it doesn't spot as such)! 109 */ 110 memmove(&pollfds[i], &pollfds[i + 1], 111 (pollfds_num - i) * sizeof(pollfds[0])); 112 if(*last_irq_ptr2 == &old_fd->next) 113 *last_irq_ptr2 = prev; 114 115 *prev = (*prev)->next; 116 if(old_fd->type == IRQ_WRITE) 117 ignore_sigio_fd(old_fd->fd); 118 kfree(old_fd); 119 continue; 120 } 121 prev = &(*prev)->next; 122 i++; 123 } 124 out: 125 return; 126 } 127 128 int os_get_pollfd(int i) 129 { 130 return pollfds[i].fd; 131 } 132 133 void os_set_pollfd(int i, int fd) 134 { 135 pollfds[i].fd = fd; 136 } 137 138 void os_set_ioignore(void) 139 { 140 set_handler(SIGIO, SIG_IGN, 0, -1); 141 } 142 143 void init_irq_signals(int on_sigstack) 144 { 145 __sighandler_t h; 146 int flags; 147 148 flags = on_sigstack ? SA_ONSTACK : 0; 149 if (timer_irq_inited) 150 h = (__sighandler_t)alarm_handler; 151 else 152 h = boot_timer_handler; 153 154 set_handler(SIGVTALRM, h, flags | SA_RESTART, 155 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); 156 set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, 157 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); 158 signal(SIGWINCH, SIG_IGN); 159 } 160