X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fselect.c;h=8cd6dc31fbb657d34fcf40ad4e6376ec90028947;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=33b72ba0f86f45790bd7661053266cd8336c9757;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/fs/select.c b/fs/select.c index 33b72ba0f..8cd6dc31f 100644 --- a/fs/select.c +++ b/fs/select.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -65,7 +66,8 @@ EXPORT_SYMBOL(poll_initwait); static void free_poll_entry(struct poll_table_entry *entry) { - remove_wait_queue(entry->wait_address,&entry->wait); + if (remove_wait_queue(entry->wait_address,&entry->wait) < 0) + print_symbol("bad poll-entry for %s", (unsigned long) entry->filp->f_op->poll); fput(entry->filp); } @@ -546,38 +548,37 @@ struct poll_list { #define POLLFD_PER_PAGE ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd)) -/* - * Fish for pollable events on the pollfd->fd file descriptor. We're only - * interested in events matching the pollfd->events mask, and the result - * matching that mask is both recorded in pollfd->revents and returned. The - * pwait poll_table will be used by the fd-provided poll handler for waiting, - * if non-NULL. - */ -static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) +static void do_pollfd(unsigned int num, struct pollfd * fdpage, + poll_table ** pwait, int *count) { - unsigned int mask; - int fd; - - mask = 0; - fd = pollfd->fd; - if (fd >= 0) { - int fput_needed; - struct file * file; - - file = fget_light(fd, &fput_needed); - mask = POLLNVAL; - if (file != NULL) { - mask = DEFAULT_POLLMASK; - if (file->f_op && file->f_op->poll) - mask = file->f_op->poll(file, pwait); - /* Mask out unneeded events. */ - mask &= pollfd->events | POLLERR | POLLHUP; - fput_light(file, fput_needed); + int i; + + for (i = 0; i < num; i++) { + int fd; + unsigned int mask; + struct pollfd *fdp; + + mask = 0; + fdp = fdpage+i; + fd = fdp->fd; + if (fd >= 0) { + int fput_needed; + struct file * file = fget_light(fd, &fput_needed); + mask = POLLNVAL; + if (file != NULL) { + mask = DEFAULT_POLLMASK; + if (file->f_op && file->f_op->poll) + mask = file->f_op->poll(file, *pwait); + mask &= fdp->events | POLLERR | POLLHUP; + fput_light(file, fput_needed); + } + if (mask) { + *pwait = NULL; + (*count)++; + } } + fdp->revents = mask; } - pollfd->revents = mask; - - return mask; } static int do_poll(unsigned int nfds, struct poll_list *list, @@ -595,29 +596,11 @@ static int do_poll(unsigned int nfds, struct poll_list *list, long __timeout; set_current_state(TASK_INTERRUPTIBLE); - for (walk = list; walk != NULL; walk = walk->next) { - struct pollfd * pfd, * pfd_end; - - pfd = walk->entries; - pfd_end = pfd + walk->len; - for (; pfd != pfd_end; pfd++) { - /* - * Fish for events. If we found one, record it - * and kill the poll_table, so we don't - * needlessly register any other waiters after - * this. They'll get immediately deregistered - * when we break out and return. - */ - if (do_pollfd(pfd, pt)) { - count++; - pt = NULL; - } - } + walk = list; + while(walk != NULL) { + do_pollfd( walk->len, walk->entries, &pt, &count); + walk = walk->next; } - /* - * All waiters have already been registered, so don't provide - * a poll_table to them on the next loop iteration. - */ pt = NULL; if (count || !*timeout || signal_pending(current)) break; @@ -746,9 +729,9 @@ out_fds: asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, long timeout_msecs) { - s64 timeout_jiffies; + s64 timeout_jiffies = 0; - if (timeout_msecs > 0) { + if (timeout_msecs) { #if HZ > 1000 /* We can only overflow if HZ > 1000 */ if (timeout_msecs / 1000 > (s64)0x7fffffffffffffffULL / (s64)HZ) @@ -756,9 +739,6 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds, else #endif timeout_jiffies = msecs_to_jiffies(timeout_msecs); - } else { - /* Infinite (< 0) or no (0) timeout */ - timeout_jiffies = timeout_msecs; } return do_sys_poll(ufds, nfds, &timeout_jiffies);