// $Header$ // Kernel Version: // VERSION = 2 // PATCHLEVEL = 5 // SUBLEVEL = 48 // EXTRAVERSION = --- 2.5/fs/select.c 2002-11-20 22:59:34.000000000 +0100 +++ build-2.5/fs/select.c 2002-11-20 22:59:25.000000000 +0100 @@ -225,7 +225,7 @@ return retval; } -static int scan_entries(fd_set_bits *fds, struct poll_table_entry *entries, int size, int *prev) +static int scan_select_entries(fd_set_bits *fds, struct poll_table_entry *entries, int size, int *prev) { int i; int retval = 0; @@ -294,7 +294,6 @@ if (retval) wait = NULL; } - wait = NULL; /* step two: now scan through the wait queues, that's faster * than the bit lookup */ for (;;) { @@ -309,10 +308,10 @@ __timeout = schedule_timeout(__timeout); set_current_state(TASK_INTERRUPTIBLE); prev = -1; - retval += scan_entries(fds, table.internal, table.nr, &prev); + retval = scan_select_entries(fds, table.internal, table.nr, &prev); pg = table.table; while (pg) { - retval += scan_entries(fds, pg->entries, pg->entry-pg->entries, &prev); + retval += scan_select_entries(fds, pg->entries, pg->entry-pg->entries, &prev); pg = pg->next; } } @@ -455,7 +454,7 @@ #define POLLFD_PER_PAGE ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd)) static void do_pollfd(unsigned int num, struct pollfd * fdpage, - poll_table ** pwait, int *count) + struct poll_wqueues **pwait, int *count) { int i; @@ -471,9 +470,11 @@ struct file * file = fget(fd); mask = POLLNVAL; if (file != NULL) { + if (*pwait) + (*pwait)->handle = fdp; mask = DEFAULT_POLLMASK; if (file->f_op && file->f_op->poll) - mask = file->f_op->poll(file, *pwait); + mask = file->f_op->poll(file, &(*pwait)->pt); mask &= fdp->events | POLLERR | POLLHUP; fput(file); } @@ -486,30 +487,74 @@ } } +static int scan_poll_entries(struct poll_table_entry *entries, int size, void **prev) +{ + int retval = 0; + int i; + + for (i=0;if_op && entries[i].filp->f_op->poll) + mask = entries[i].filp->f_op->poll(entries[i].filp, NULL); + mask &= fdp->events | POLLERR | POLLHUP; + if (mask) { + retval++; + fdp->revents = mask; + } + } + return retval; +} + static int do_poll(unsigned int nfds, struct poll_list *list, struct poll_wqueues *wait, long timeout) { + struct poll_list *walk; int count = 0; - poll_table* pt = &wait->pt; + struct poll_wqueues *pt = wait; if (!timeout) pt = NULL; - + + set_current_state(TASK_INTERRUPTIBLE); + walk = list; + while(walk != NULL) { + do_pollfd( walk->len, walk->entries, &pt, &count); + walk = walk->next; + } + pt = NULL; for (;;) { - struct poll_list *walk; - set_current_state(TASK_INTERRUPTIBLE); - walk = list; - while(walk != NULL) { - do_pollfd( walk->len, walk->entries, &pt, &count); - walk = walk->next; - } - pt = NULL; + struct poll_table_page *pg; + void *prev; + if (count || !timeout || signal_pending(current)) break; count = wait->error; if (count) break; timeout = schedule_timeout(timeout); + + set_current_state(TASK_INTERRUPTIBLE); + prev = NULL; + count = scan_poll_entries(wait->internal, wait->nr, &prev); + pg = wait->table; + while (pg) { + count += scan_poll_entries(pg->entries, pg->entry-pg->entries, &prev); + pg = pg->next; + } } current->state = TASK_RUNNING; return count;