diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-04-05 11:23:36 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-04-05 11:23:36 +0000 |
commit | 4318fbda2a7ee51caafdc4eb1f8028a3f0605142 (patch) | |
tree | cddb50a81d7d1a628cc400519162080c6d87868e /fs/select.c | |
parent | 36ea5120664550fae6d31f1c6f695e4f8975cb06 (diff) |
o Merge with Linux 2.1.91.
o First round of bugfixes for the SC/MC CPUs.
o FPU context switch fixes.
o Lazy context switches.
o Faster syscalls.
o Removed dead code.
o Shitloads of other things I forgot ...
Diffstat (limited to 'fs/select.c')
-rw-r--r-- | fs/select.c | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/fs/select.c b/fs/select.c index 1328660b0..a4e847e64 100644 --- a/fs/select.c +++ b/fs/select.c @@ -41,7 +41,7 @@ * sleep/wakeup mechanism works. * * Two very simple procedures, poll_wait() and free_wait() make all the - * work. poll_wait() is an inline-function defined in <linux/sched.h>, + * work. poll_wait() is an inline-function defined in <linux/poll.h>, * as all select/poll functions have to call it to add an entry to the * poll table. */ @@ -152,9 +152,8 @@ int do_select(int n, fd_set_buffer *fds, unsigned long timeout) n = retval; retval = 0; for (;;) { - struct file ** fd = current->files->fd; current->state = TASK_INTERRUPTIBLE; - for (i = 0 ; i < n ; i++, fd++) { + for (i = 0 ; i < n; i++) { unsigned long bit = BIT(i); unsigned long *in = MEM(i,fds->in); unsigned long mask; @@ -162,8 +161,12 @@ int do_select(int n, fd_set_buffer *fds, unsigned long timeout) if (!(bit & BITS(in))) continue; - - file = *fd; + /* + * The poll_wait routine will increment f_count if + * the file is added to the wait table, so we don't + * need to increment it now. + */ + file = fcheck(i); mask = POLLNVAL; if (file) { mask = DEFAULT_POLLMASK; @@ -286,23 +289,21 @@ out_nofds: static int do_poll(unsigned int nfds, struct pollfd *fds, poll_table *wait) { - int count; - struct file ** fd = current->files->fd; + int count = 0; - count = 0; for (;;) { unsigned int j; struct pollfd * fdpnt; current->state = TASK_INTERRUPTIBLE; for (fdpnt = fds, j = 0; j < nfds; j++, fdpnt++) { - unsigned int i; unsigned int mask; struct file * file; mask = POLLNVAL; - i = fdpnt->fd; - if (i < NR_OPEN && (file = fd[i]) != NULL) { + /* poll_wait increments f_count if needed */ + file = fcheck(fdpnt->fd); + if (file != NULL) { mask = DEFAULT_POLLMASK; if (file->f_op && file->f_op->poll) mask = file->f_op->poll(file, wait); @@ -326,18 +327,22 @@ static int do_poll(unsigned int nfds, struct pollfd *fds, poll_table *wait) asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout) { - int i, count, fdcount, err; + int i, fdcount, err, size; struct pollfd * fds, *fds1; - poll_table wait_table, *wait; + poll_table wait_table, *wait = NULL; lock_kernel(); + /* Do a sanity check on nfds ... */ + err = -EINVAL; + if (nfds > NR_OPEN) + goto out; + if (timeout < 0) timeout = 0x7fffffff; else if (timeout) timeout = ((unsigned long)timeout*HZ+999)/1000+jiffies+1; - err = -ENOMEM; - wait = NULL; + err = -ENOMEM; if (timeout) { struct poll_table_entry *entry; entry = (struct poll_table_entry *) __get_free_page(GFP_KERNEL); @@ -347,34 +352,32 @@ asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout) wait_table.entry = entry; wait = &wait_table; } - fds = (struct pollfd *) kmalloc(nfds*sizeof(struct pollfd), GFP_KERNEL); - if (!fds) { + + size = nfds * sizeof(struct pollfd); + fds = (struct pollfd *) kmalloc(size, GFP_KERNEL); + if (!fds) goto out; - } err = -EFAULT; - if (copy_from_user(fds, ufds, nfds*sizeof(struct pollfd))) { - kfree(fds); - goto out; - } + if (copy_from_user(fds, ufds, size)) + goto out_fds; current->timeout = timeout; - - count = 0; - fdcount = do_poll(nfds, fds, wait); current->timeout = 0; /* OK, now copy the revents fields back to user space. */ fds1 = fds; - for(i=0; i < (int)nfds; i++, ufds++, fds++) { - __put_user(fds->revents, &ufds->revents); + for(i=0; i < (int)nfds; i++, ufds++, fds1++) { + __put_user(fds1->revents, &ufds->revents); } - kfree(fds1); + + err = fdcount; if (!fdcount && signal_pending(current)) err = -EINTR; - else - err = fdcount; + +out_fds: + kfree(fds); out: if (wait) { free_wait(&wait_table); |