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_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds) 56 { 57 if (pollfds_num == pollfds_size) { 58 if (size_tmpfds <= pollfds_size * sizeof(pollfds[0])) { 59 /* return min size needed for new pollfds area */ 60 return((pollfds_size + 1) * sizeof(pollfds[0])); 61 } 62 63 if (pollfds != NULL) { 64 memcpy(tmp_pfd, pollfds, 65 sizeof(pollfds[0]) * pollfds_size); 66 /* remove old pollfds */ 67 kfree(pollfds); 68 } 69 pollfds = tmp_pfd; 70 pollfds_size++; 71 } else 72 kfree(tmp_pfd); /* remove not used tmp_pfd */ 73 74 pollfds[pollfds_num] = ((struct pollfd) { .fd = fd, 75 .events = events, 76 .revents = 0 }); 77 pollfds_num++; 78 79 return 0; 80 } 81 82 void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg, 83 struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2) 84 { 85 struct irq_fd **prev; 86 int i = 0; 87 88 prev = &active_fds; 89 while (*prev != NULL) { 90 if ((*test)(*prev, arg)) { 91 struct irq_fd *old_fd = *prev; 92 if ((pollfds[i].fd != -1) && 93 (pollfds[i].fd != (*prev)->fd)) { 94 printk("os_free_irq_by_cb - mismatch between " 95 "active_fds and pollfds, fd %d vs %d\n", 96 (*prev)->fd, pollfds[i].fd); 97 goto out; 98 } 99 100 pollfds_num--; 101 102 /* This moves the *whole* array after pollfds[i] 103 * (though it doesn't spot as such)! 104 */ 105 memmove(&pollfds[i], &pollfds[i + 1], 106 (pollfds_num - i) * sizeof(pollfds[0])); 107 if(*last_irq_ptr2 == &old_fd->next) 108 *last_irq_ptr2 = prev; 109 110 *prev = (*prev)->next; 111 if(old_fd->type == IRQ_WRITE) 112 ignore_sigio_fd(old_fd->fd); 113 kfree(old_fd); 114 continue; 115 } 116 prev = &(*prev)->next; 117 i++; 118 } 119 out: 120 return; 121 } 122 123 int os_get_pollfd(int i) 124 { 125 return pollfds[i].fd; 126 } 127 128 void os_set_pollfd(int i, int fd) 129 { 130 pollfds[i].fd = fd; 131 } 132 133 void os_set_ioignore(void) 134 { 135 set_handler(SIGIO, SIG_IGN, 0, -1); 136 } 137 138 void init_irq_signals(int on_sigstack) 139 { 140 int flags; 141 142 flags = on_sigstack ? SA_ONSTACK : 0; 143 144 set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, 145 flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); 146 set_handler(SIGALRM, (__sighandler_t) alarm_handler, 147 flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); 148 set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, 149 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); 150 signal(SIGWINCH, SIG_IGN); 151 } 152