// $Header$ // Kernel Version: // VERSION = 2 // PATCHLEVEL = 5 // SUBLEVEL = 48 // EXTRAVERSION = --- 2.5/fs/select.c 2002-11-20 23:25:46.000000000 +0100 +++ build-2.5/fs/select.c 2002-11-20 23:21:51.000000000 +0100 @@ -225,13 +225,16 @@ return retval; } -static int scan_select_entries(fd_set_bits *fds, struct poll_table_entry *entries, int size, int *prev) +static int scan_entries(struct poll_table_entry *entries, int size, void **prev, + int (*actor)(void *priv, void *handle, unsigned long mask), void *priv) { - int i; 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); - retval += parse_mask(fds, mask, fd/__NFDBITS, BIT(fd)); + retval += actor(priv, handle, mask); + } return retval; } +static int wait_for_events(struct poll_wqueues *wait, long *timeout, + int (*actor)(void *priv, void *handle, unsigned long mask), void *priv) +{ + int count = 0; + for (;;) { + 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_entries(wait->internal, wait->nr, &prev, actor, priv); + pg = wait->table; + while (pg) { + count += scan_entries(pg->entries, pg->entry-pg->entries, &prev, actor, priv); + pg = pg->next; + } + } + return count; +} + +static int select_actor(void *priv, void *handle, unsigned long mask) +{ + int fd = (int)handle; + return parse_mask(priv, mask, fd/__NFDBITS, BIT(fd)); +} + int do_select(int n, fd_set_bits *fds, long *timeout) { struct poll_wqueues table; @@ -294,27 +330,8 @@ if (retval) wait = NULL; } - /* step two: now scan through the wait queues, that's faster - * than the bit lookup */ - for (;;) { - struct poll_table_page *pg; - int prev; - if (retval || !__timeout || signal_pending(current)) - break; - if(table.error) { - retval = table.error; - break; - } - __timeout = schedule_timeout(__timeout); - set_current_state(TASK_INTERRUPTIBLE); - prev = -1; - retval = scan_select_entries(fds, table.internal, table.nr, &prev); - pg = table.table; - while (pg) { - retval += scan_select_entries(fds, pg->entries, pg->entry-pg->entries, &prev); - pg = pg->next; - } - } + if (!retval && __timeout) + retval = wait_for_events(&table, &__timeout, select_actor, fds); current->state = TASK_RUNNING; poll_freewait(&table); @@ -487,36 +504,16 @@ } } -static int scan_poll_entries(struct poll_table_entry *entries, int size, void **prev) +int poll_actor(void *priv, void *handle, unsigned long mask) { - 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; - } + mask &= fdp->events | POLLERR | POLLHUP; + if (mask) { + fdp->revents = mask; + return 1; } - return retval; + return 0; } static int do_poll(unsigned int nfds, struct poll_list *list, @@ -535,27 +532,8 @@ do_pollfd( walk->len, walk->entries, &pt, &count); walk = walk->next; } - pt = NULL; - for (;;) { - 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; - } - } + if (!count && timeout) + count = wait_for_events(wait, &timeout, poll_actor, NULL); current->state = TASK_RUNNING; return count; }