diff -urN linux-2.0.31/fs/select.c linux/fs/select.c --- linux-2.0.31/fs/select.c Tue Dec 31 00:57:02 1996 +++ linux/fs/select.c Sun Sep 7 19:31:01 1997 @@ -67,7 +67,7 @@ * and we aren't going to sleep on the select_table. -- jrs */ -static int check(int flag, select_table * wait, struct file * file) +static inline int check(int flag, select_table * wait, struct file * file) { struct inode * inode; struct file_operations *fops; @@ -83,11 +83,9 @@ } static int do_select(int n, fd_set *in, fd_set *out, fd_set *ex, - fd_set *res_in, fd_set *res_out, fd_set *res_ex) + fd_set *res_in, fd_set *res_out, fd_set *res_ex, select_table *wait) { int count; - select_table wait_table, *wait; - struct select_table_entry *entry; unsigned long set; int i,j; int max = -1; @@ -113,12 +111,7 @@ } end_check: n = max + 1; - if(!(entry = (struct select_table_entry*) __get_free_page(GFP_KERNEL))) - return -ENOMEM; count = 0; - wait_table.nr = 0; - wait_table.entry = entry; - wait = &wait_table; repeat: current->state = TASK_INTERRUPTIBLE; for (i = 0 ; i < n ; i++) { @@ -146,8 +139,6 @@ schedule(); goto repeat; } - free_wait(&wait_table); - free_page((unsigned long) entry); current->state = TASK_RUNNING; return count; } @@ -244,25 +235,35 @@ limited_fd_set res_out, out; limited_fd_set res_ex, ex; unsigned long timeout; + select_table wait_table, *wait; - error = -EINVAL; - if (n < 0) - goto out; - if (n > NR_OPEN) - n = NR_OPEN; - if ((error = get_fd_set(n, inp, &in)) || - (error = get_fd_set(n, outp, &out)) || - (error = get_fd_set(n, exp, &ex))) goto out; timeout = ~0UL; if (tvp) { error = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp)); if (error) - goto out; + return error; timeout = ROUND_UP(get_user(&tvp->tv_usec),(1000000/HZ)); timeout += get_user(&tvp->tv_sec) * (unsigned long) HZ; if (timeout) timeout += jiffies + 1; } + wait = NULL; + if (timeout) { + struct select_table_entry *entry; + if(!(entry = (struct select_table_entry*) __get_free_page(GFP_KERNEL))) + return -ENOMEM; + wait_table.nr = 0; + wait_table.entry = entry; + wait = &wait_table; + } + error = -EINVAL; + if (n < 0) + goto out; + if (n > NR_OPEN) + n = NR_OPEN; + if ((error = get_fd_set(n, inp, &in)) || + (error = get_fd_set(n, outp, &out)) || + (error = get_fd_set(n, exp, &ex))) goto out; zero_fd_set(n, &res_in); zero_fd_set(n, &res_out); zero_fd_set(n, &res_ex); @@ -273,7 +274,8 @@ (fd_set *) &ex, (fd_set *) &res_in, (fd_set *) &res_out, - (fd_set *) &res_ex); + (fd_set *) &res_ex, + wait); timeout = current->timeout - jiffies - 1; current->timeout = 0; if ((long) timeout < 0) @@ -296,5 +298,9 @@ set_fd_set(n, outp, &res_out); set_fd_set(n, exp, &res_ex); out: + if (wait) { + free_wait(&wait_table); + free_page((unsigned long) wait->entry); + } return error; }