patch-2.1.91 linux/fs/select.c
Next file: linux/include/asm-alpha/init.h
Previous file: linux/fs/proc/link.c
Back to the patch index
Back to the overall index
- Lines: 138
- Date:
Mon Mar 23 10:13:52 1998
- Orig file:
v2.1.90/linux/fs/select.c
- Orig date:
Tue Mar 10 10:03:34 1998
diff -u --recursive --new-file v2.1.90/linux/fs/select.c linux/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 @@
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 @@
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 @@
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 @@
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 @@
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);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov