int do_select(fd_set in, fd_set out, fd_set ex, fd_set *inp, fd_set *outp, fd_set *exp) { int count; select_table wait_table; int i; fd_set mask; mask = in | out | ex; for (i = 0 ; i < NR_OPEN ; i++,mask >>= 1) { if (!(mask & 1)) continue; if (!current->filp[i]) return -EBADF; if (!current->filp[i]->f_inode) return -EBADF; if (current->filp[i]->f_inode->i_pipe) continue; if (S_ISCHR(current->filp[i]->f_inode->i_mode)) continue; if (S_ISFIFO(current->filp[i]->f_inode->i_mode)) continue; return -EBADF; } repeat: wait_table.nr = 0; *inp = *outp = *exp = 0; count = 0; mask = 1; for (i = 0 ; i < NR_OPEN ; i++, mask += mask) { if (mask & in) if (check_in(&wait_table,current->filp[i]->f_inode)) { *inp |= mask; count++; } if (mask & out) if (check_out(&wait_table,current->filp[i]->f_inode)) { *outp |= mask; count++; } if (mask & ex) if (check_ex(&wait_table,current->filp[i]->f_inode)) { *exp |= mask; count++; } } if (!(current->signal & ~current->blocked) && (wait_table.nr || current->timeout) && !count) { current->state = TASK_INTERRUPTIBLE; schedule(); free_wait(&wait_table); goto repeat; } free_wait(&wait_table); return count; }
int sunos_poll(struct poll * ufds, size_t nfds, int timeout) { int i,j, count, fdcount, error, retflag; struct poll * fdpnt; struct poll * fds, *fds1; select_table wait_table, *wait; struct select_table_entry *entry; if ((error = verify_area(VERIFY_READ, ufds, nfds*sizeof(struct poll)))) return error; if (nfds > NR_OPEN) return -EINVAL; if (!(entry = (struct select_table_entry*)__get_free_page(GFP_KERNEL)) || !(fds = (struct poll *)kmalloc(nfds*sizeof(struct poll), GFP_KERNEL))) return -ENOMEM; memcpy_fromfs(fds, ufds, nfds*sizeof(struct poll)); if (timeout < 0) current->timeout = 0x7fffffff; else { current->timeout = jiffies + POLL_ROUND_UP(timeout, (1000/HZ)); if (current->timeout <= jiffies) current->timeout = 0; } count = 0; wait_table.nr = 0; wait_table.entry = entry; wait = &wait_table; for(fdpnt = fds, j = 0; j < (int)nfds; j++, fdpnt++) { i = fdpnt->fd; fdpnt->revents = 0; if (!current->files->fd[i] || !current->files->fd[i]->f_inode) fdpnt->revents = POLLNVAL; } repeat: current->state = TASK_INTERRUPTIBLE; for(fdpnt = fds, j = 0; j < (int)nfds; j++, fdpnt++) { i = fdpnt->fd; if(i < 0) continue; if (!current->files->fd[i] || !current->files->fd[i]->f_inode) continue; if ((fdpnt->events & LINUX_POLLIN) && check(SEL_IN, wait, current->files->fd[i])) { if (fdpnt->events & POLLIN) retflag = POLLIN; if (fdpnt->events & POLLRDNORM) retflag = POLLRDNORM; fdpnt->revents |= retflag; count++; wait = NULL; } if ((fdpnt->events & LINUX_POLLOUT) && check(SEL_OUT, wait, current->files->fd[i])) { fdpnt->revents |= (LINUX_POLLOUT & fdpnt->events); count++; wait = NULL; } if (check(SEL_EX, wait, current->files->fd[i])) { fdpnt->revents |= POLLHUP; count++; wait = NULL; } } if ((current->signal & (~current->blocked))) return -EINTR; wait = NULL; if (!count && current->timeout > jiffies) { schedule(); goto repeat; } free_wait(&wait_table); free_page((unsigned long) entry); /* OK, now copy the revents fields back to user space. */ fds1 = fds; fdcount = 0; for(i=0; i < (int)nfds; i++, ufds++, fds++) { if (fds->revents) { fdcount++; } put_fs_word(fds->revents, &ufds->revents); } kfree(fds1); current->timeout = 0; current->state = TASK_RUNNING; return fdcount; }