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 /* remove not used tmp_pfd */ 78 if (tmp_pfd != NULL) 79 kfree(tmp_pfd); 80 } 81 82 pollfds[pollfds_num] = ((struct pollfd) { .fd = fd, 83 .events = events, 84 .revents = 0 }); 85 pollfds_num++; 86 87 return(0); 88 } 89 90 void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg, 91 struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2) 92 { 93 struct irq_fd **prev; 94 int i = 0; 95 96 prev = &active_fds; 97 while(*prev != NULL){ 98 if((*test)(*prev, arg)){ 99 struct irq_fd *old_fd = *prev; 100 if((pollfds[i].fd != -1) && 101 (pollfds[i].fd != (*prev)->fd)){ 102 printk("os_free_irq_by_cb - mismatch between " 103 "active_fds and pollfds, fd %d vs %d\n", 104 (*prev)->fd, pollfds[i].fd); 105 goto out; 106 } 107 108 pollfds_num--; 109 110 /* This moves the *whole* array after pollfds[i] 111 * (though it doesn't spot as such)! 112 */ 113 114 memmove(&pollfds[i], &pollfds[i + 1], 115 (pollfds_num - i) * sizeof(pollfds[0])); 116 if(*last_irq_ptr2 == &old_fd->next) 117 *last_irq_ptr2 = prev; 118 119 *prev = (*prev)->next; 120 if(old_fd->type == IRQ_WRITE) 121 ignore_sigio_fd(old_fd->fd); 122 kfree(old_fd); 123 continue; 124 } 125 prev = &(*prev)->next; 126 i++; 127 } 128 out: 129 return; 130 } 131 132 133 int os_get_pollfd(int i) 134 { 135 return(pollfds[i].fd); 136 } 137 138 void os_set_pollfd(int i, int fd) 139 { 140 pollfds[i].fd = fd; 141 } 142 143 void os_set_ioignore(void) 144 { 145 set_handler(SIGIO, SIG_IGN, 0, -1); 146 } 147 148 void init_irq_signals(int on_sigstack) 149 { 150 __sighandler_t h; 151 int flags; 152 153 flags = on_sigstack ? SA_ONSTACK : 0; 154 if(timer_irq_inited) h = (__sighandler_t) alarm_handler; 155 else h = boot_timer_handler; 156 157 set_handler(SIGVTALRM, h, flags | SA_RESTART, 158 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); 159 set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, 160 SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); 161 signal(SIGWINCH, SIG_IGN); 162 } 163