The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/sys_generic.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1982, 1986, 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  * (c) UNIX System Laboratories, Inc.
    5  * All or some portions of this file are derived from material licensed
    6  * to the University of California by American Telephone and Telegraph
    7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    8  * the permission of UNIX System Laboratories, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the University of
   21  *      California, Berkeley and its contributors.
   22  * 4. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      @(#)sys_generic.c       8.5 (Berkeley) 1/21/94
   39  * $FreeBSD$
   40  */
   41 
   42 #include "opt_ktrace.h"
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/sysproto.h>
   47 #include <sys/filedesc.h>
   48 #include <sys/filio.h>
   49 #include <sys/ttycom.h>
   50 #include <sys/fcntl.h>
   51 #include <sys/file.h>
   52 #include <sys/proc.h>
   53 #include <sys/signalvar.h>
   54 #include <sys/socketvar.h>
   55 #include <sys/uio.h>
   56 #include <sys/kernel.h>
   57 #include <sys/malloc.h>
   58 #include <sys/poll.h>
   59 #include <sys/sysent.h>
   60 #ifdef KTRACE
   61 #include <sys/ktrace.h>
   62 #endif
   63 
   64 #include <machine/limits.h>
   65 
   66 static MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer");
   67 static MALLOC_DEFINE(M_SELECT, "select", "select() buffer");
   68 MALLOC_DEFINE(M_IOV, "iov", "large iov's");
   69 
   70 static int      pollscan __P((struct proc *, struct pollfd *, int));
   71 static int      selscan __P((struct proc *, fd_mask **, fd_mask **, int));
   72 static struct file* getfp __P((struct filedesc *, int, int));
   73 static int      dofileread __P((struct proc *, struct file *, int, void *,
   74                     size_t, off_t, int));
   75 static int      dofilewrite __P((struct proc *, struct file *, int,
   76                     const void *, size_t, off_t, int));
   77 
   78 static struct file*
   79 getfp(fdp, fd, flag)
   80         struct filedesc* fdp;
   81         int fd, flag;
   82 {
   83         struct file* fp;
   84 
   85         if (((u_int)fd) >= fdp->fd_nfiles ||
   86             (fp = fdp->fd_ofiles[fd]) == NULL ||
   87             (fp->f_flag & flag) == 0)
   88                 return (NULL);
   89         return (fp);
   90 }
   91 
   92 /*
   93  * Read system call.
   94  */
   95 #ifndef _SYS_SYSPROTO_H_
   96 struct read_args {
   97         int     fd;
   98         void    *buf;
   99         size_t  nbyte;
  100 };
  101 #endif
  102 int
  103 read(p, uap)
  104         struct proc *p;
  105         register struct read_args *uap;
  106 {
  107         register struct file *fp;
  108 
  109         if ((fp = getfp(p->p_fd, uap->fd, FREAD)) == NULL)
  110                 return (EBADF);
  111         return (dofileread(p, fp, uap->fd, uap->buf, uap->nbyte, (off_t)-1, 0));
  112 }
  113 
  114 /*
  115  * Pread system call
  116  */
  117 #ifndef _SYS_SYSPROTO_H_
  118 struct pread_args {
  119         int     fd;
  120         void    *buf;
  121         size_t  nbyte;
  122         int     pad;
  123         off_t   offset;
  124 };
  125 #endif
  126 int
  127 pread(p, uap)
  128         struct proc *p;
  129         register struct pread_args *uap;
  130 {
  131         register struct file *fp;
  132 
  133         if ((fp = getfp(p->p_fd, uap->fd, FREAD)) == NULL)
  134                 return (EBADF);
  135         if (fp->f_type != DTYPE_VNODE)
  136                 return (ESPIPE);
  137         return (dofileread(p, fp, uap->fd, uap->buf, uap->nbyte, uap->offset, 
  138             FOF_OFFSET));
  139 }
  140 
  141 /*
  142  * Code common for read and pread
  143  */
  144 int
  145 dofileread(p, fp, fd, buf, nbyte, offset, flags)
  146         struct proc *p;
  147         struct file *fp;
  148         int fd, flags;
  149         void *buf;
  150         size_t nbyte;
  151         off_t offset;
  152 {
  153         struct uio auio;
  154         struct iovec aiov;
  155         long cnt, error = 0;
  156 #ifdef KTRACE
  157         struct iovec ktriov;
  158         struct uio ktruio;
  159         int didktr = 0;
  160 #endif
  161 
  162         aiov.iov_base = (caddr_t)buf;
  163         aiov.iov_len = nbyte;
  164         auio.uio_iov = &aiov;
  165         auio.uio_iovcnt = 1;
  166         auio.uio_offset = offset;
  167         if (nbyte > INT_MAX)
  168                 return (EINVAL);
  169         auio.uio_resid = nbyte;
  170         auio.uio_rw = UIO_READ;
  171         auio.uio_segflg = UIO_USERSPACE;
  172         auio.uio_procp = p;
  173 #ifdef KTRACE
  174         /*
  175          * if tracing, save a copy of iovec
  176          */
  177         if (KTRPOINT(p, KTR_GENIO)) {
  178                 ktriov = aiov;
  179                 ktruio = auio;
  180                 didktr = 1;
  181         }
  182 #endif
  183         cnt = nbyte;
  184         if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred, flags)))
  185                 if (auio.uio_resid != cnt && (error == ERESTART ||
  186                     error == EINTR || error == EWOULDBLOCK))
  187                         error = 0;
  188         cnt -= auio.uio_resid;
  189 #ifdef KTRACE
  190         if (didktr && error == 0) {
  191                 ktruio.uio_iov = &ktriov;
  192                 ktruio.uio_resid = cnt;
  193                 ktrgenio(p->p_tracep, fd, UIO_READ, &ktruio, error);
  194         }
  195 #endif
  196         p->p_retval[0] = cnt;
  197         return (error);
  198 }
  199 
  200 /*
  201  * Scatter read system call.
  202  */
  203 #ifndef _SYS_SYSPROTO_H_
  204 struct readv_args {
  205         int     fd;
  206         struct  iovec *iovp;
  207         u_int   iovcnt;
  208 };
  209 #endif
  210 int
  211 readv(p, uap)
  212         struct proc *p;
  213         register struct readv_args *uap;
  214 {
  215         register struct file *fp;
  216         register struct filedesc *fdp = p->p_fd;
  217         struct uio auio;
  218         register struct iovec *iov;
  219         struct iovec *needfree;
  220         struct iovec aiov[UIO_SMALLIOV];
  221         long i, cnt, error = 0;
  222         u_int iovlen;
  223 #ifdef KTRACE
  224         struct iovec *ktriov = NULL;
  225         struct uio ktruio;
  226 #endif
  227 
  228         if ((fp = getfp(fdp, uap->fd, FREAD)) == NULL)
  229                 return (EBADF);
  230         /* note: can't use iovlen until iovcnt is validated */
  231         iovlen = uap->iovcnt * sizeof (struct iovec);
  232         if (uap->iovcnt > UIO_SMALLIOV) {
  233                 if (uap->iovcnt > UIO_MAXIOV)
  234                         return (EINVAL);
  235                 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
  236                 needfree = iov;
  237         } else {
  238                 iov = aiov;
  239                 needfree = NULL;
  240         }
  241         auio.uio_iov = iov;
  242         auio.uio_iovcnt = uap->iovcnt;
  243         auio.uio_rw = UIO_READ;
  244         auio.uio_segflg = UIO_USERSPACE;
  245         auio.uio_procp = p;
  246         auio.uio_offset = -1;
  247         if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
  248                 goto done;
  249         auio.uio_resid = 0;
  250         for (i = 0; i < uap->iovcnt; i++) {
  251                 if (iov->iov_len > INT_MAX - auio.uio_resid) {
  252                         error = EINVAL;
  253                         goto done;
  254                 }
  255                 auio.uio_resid += iov->iov_len;
  256                 iov++;
  257         }
  258 #ifdef KTRACE
  259         /*
  260          * if tracing, save a copy of iovec
  261          */
  262         if (KTRPOINT(p, KTR_GENIO))  {
  263                 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
  264                 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
  265                 ktruio = auio;
  266         }
  267 #endif
  268         cnt = auio.uio_resid;
  269         if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred, 0)))
  270                 if (auio.uio_resid != cnt && (error == ERESTART ||
  271                     error == EINTR || error == EWOULDBLOCK))
  272                         error = 0;
  273         cnt -= auio.uio_resid;
  274 #ifdef KTRACE
  275         if (ktriov != NULL) {
  276                 if (error == 0) {
  277                         ktruio.uio_iov = ktriov;
  278                         ktruio.uio_resid = cnt;
  279                         ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktruio,
  280                             error);
  281                 }
  282                 FREE(ktriov, M_TEMP);
  283         }
  284 #endif
  285         p->p_retval[0] = cnt;
  286 done:
  287         if (needfree)
  288                 FREE(needfree, M_IOV);
  289         return (error);
  290 }
  291 
  292 /*
  293  * Write system call
  294  */
  295 #ifndef _SYS_SYSPROTO_H_
  296 struct write_args {
  297         int     fd;
  298         const void *buf;
  299         size_t  nbyte;
  300 };
  301 #endif
  302 int
  303 write(p, uap)
  304         struct proc *p;
  305         register struct write_args *uap;
  306 {
  307         register struct file *fp;
  308 
  309         if ((fp = getfp(p->p_fd, uap->fd, FWRITE)) == NULL)
  310                 return (EBADF);
  311         return (dofilewrite(p, fp, uap->fd, uap->buf, uap->nbyte, (off_t)-1, 0));
  312 }
  313 
  314 /*
  315  * Pwrite system call
  316  */
  317 #ifndef _SYS_SYSPROTO_H_
  318 struct pwrite_args {
  319         int     fd;
  320         const void *buf;
  321         size_t  nbyte;
  322         int     pad;
  323         off_t   offset;
  324 };
  325 #endif
  326 int
  327 pwrite(p, uap)
  328         struct proc *p;
  329         register struct pwrite_args *uap;
  330 {
  331         register struct file *fp;
  332 
  333         if ((fp = getfp(p->p_fd, uap->fd, FWRITE)) == NULL)
  334                 return (EBADF);
  335         if (fp->f_type != DTYPE_VNODE)
  336                 return (ESPIPE);
  337         return (dofilewrite(p, fp, uap->fd, uap->buf, uap->nbyte, uap->offset,
  338             FOF_OFFSET));
  339 }
  340 
  341 static int
  342 dofilewrite(p, fp, fd, buf, nbyte, offset, flags)
  343         struct proc *p;
  344         struct file *fp;
  345         int fd, flags;
  346         const void *buf;
  347         size_t nbyte;
  348         off_t offset;
  349 {
  350         struct uio auio;
  351         struct iovec aiov;
  352         long cnt, error = 0;
  353 #ifdef KTRACE
  354         struct iovec ktriov;
  355         struct uio ktruio;
  356         int didktr = 0;
  357 #endif
  358 
  359         aiov.iov_base = (void *)buf;
  360         aiov.iov_len = nbyte;
  361         auio.uio_iov = &aiov;
  362         auio.uio_iovcnt = 1;
  363         auio.uio_offset = offset;
  364         if (nbyte > INT_MAX)
  365                 return (EINVAL);
  366         auio.uio_resid = nbyte;
  367         auio.uio_rw = UIO_WRITE;
  368         auio.uio_segflg = UIO_USERSPACE;
  369         auio.uio_procp = p;
  370 #ifdef KTRACE
  371         /*
  372          * if tracing, save a copy of iovec and uio
  373          */
  374         if (KTRPOINT(p, KTR_GENIO)) {
  375                 ktriov = aiov;
  376                 ktruio = auio;
  377                 didktr = 1;
  378         }
  379 #endif
  380         cnt = nbyte;
  381         if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred, flags))) {
  382                 if (auio.uio_resid != cnt && (error == ERESTART ||
  383                     error == EINTR || error == EWOULDBLOCK))
  384                         error = 0;
  385                 if (error == EPIPE)
  386                         psignal(p, SIGPIPE);
  387         }
  388         cnt -= auio.uio_resid;
  389 #ifdef KTRACE
  390         if (didktr && error == 0) {
  391                 ktruio.uio_iov = &ktriov;
  392                 ktruio.uio_resid = cnt;
  393                 ktrgenio(p->p_tracep, fd, UIO_WRITE, &ktruio, error);
  394         }
  395 #endif
  396         p->p_retval[0] = cnt;
  397         return (error);
  398 }
  399 
  400 /*
  401  * Gather write system call
  402  */
  403 #ifndef _SYS_SYSPROTO_H_
  404 struct writev_args {
  405         int     fd;
  406         struct  iovec *iovp;
  407         u_int   iovcnt;
  408 };
  409 #endif
  410 int
  411 writev(p, uap)
  412         struct proc *p;
  413         register struct writev_args *uap;
  414 {
  415         register struct file *fp;
  416         register struct filedesc *fdp = p->p_fd;
  417         struct uio auio;
  418         register struct iovec *iov;
  419         struct iovec *needfree;
  420         struct iovec aiov[UIO_SMALLIOV];
  421         long i, cnt, error = 0;
  422         u_int iovlen;
  423 #ifdef KTRACE
  424         struct iovec *ktriov = NULL;
  425         struct uio ktruio;
  426 #endif
  427 
  428         if ((fp = getfp(fdp, uap->fd, FWRITE)) == NULL)
  429                 return (EBADF);
  430         /* note: can't use iovlen until iovcnt is validated */
  431         iovlen = uap->iovcnt * sizeof (struct iovec);
  432         if (uap->iovcnt > UIO_SMALLIOV) {
  433                 if (uap->iovcnt > UIO_MAXIOV)
  434                         return (EINVAL);
  435                 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
  436                 needfree = iov;
  437         } else {
  438                 iov = aiov;
  439                 needfree = NULL;
  440         }
  441         auio.uio_iov = iov;
  442         auio.uio_iovcnt = uap->iovcnt;
  443         auio.uio_rw = UIO_WRITE;
  444         auio.uio_segflg = UIO_USERSPACE;
  445         auio.uio_procp = p;
  446         auio.uio_offset = -1;
  447         if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
  448                 goto done;
  449         auio.uio_resid = 0;
  450         for (i = 0; i < uap->iovcnt; i++) {
  451                 if (iov->iov_len > INT_MAX - auio.uio_resid) {
  452                         error = EINVAL;
  453                         goto done;
  454                 }
  455                 auio.uio_resid += iov->iov_len;
  456                 iov++;
  457         }
  458 #ifdef KTRACE
  459         /*
  460          * if tracing, save a copy of iovec and uio
  461          */
  462         if (KTRPOINT(p, KTR_GENIO))  {
  463                 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
  464                 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
  465                 ktruio = auio;
  466         }
  467 #endif
  468         cnt = auio.uio_resid;
  469         if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred, 0))) {
  470                 if (auio.uio_resid != cnt && (error == ERESTART ||
  471                     error == EINTR || error == EWOULDBLOCK))
  472                         error = 0;
  473                 if (error == EPIPE)
  474                         psignal(p, SIGPIPE);
  475         }
  476         cnt -= auio.uio_resid;
  477 #ifdef KTRACE
  478         if (ktriov != NULL) {
  479                 if (error == 0) {
  480                         ktruio.uio_iov = ktriov;
  481                         ktruio.uio_resid = cnt;
  482                         ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, &ktruio,
  483                             error);
  484                 }
  485                 FREE(ktriov, M_TEMP);
  486         }
  487 #endif
  488         p->p_retval[0] = cnt;
  489 done:
  490         if (needfree)
  491                 FREE(needfree, M_IOV);
  492         return (error);
  493 }
  494 
  495 /*
  496  * Ioctl system call
  497  */
  498 #ifndef _SYS_SYSPROTO_H_
  499 struct ioctl_args {
  500         int     fd;
  501         u_long  com;
  502         caddr_t data;
  503 };
  504 #endif
  505 /* ARGSUSED */
  506 int
  507 ioctl(p, uap)
  508         struct proc *p;
  509         register struct ioctl_args *uap;
  510 {
  511         register struct file *fp;
  512         register struct filedesc *fdp;
  513         register u_long com;
  514         int error;
  515         register u_int size;
  516         caddr_t data, memp;
  517         int tmp;
  518 #define STK_PARAMS      128
  519         char stkbuf[STK_PARAMS];
  520 
  521         fdp = p->p_fd;
  522         if ((u_int)uap->fd >= fdp->fd_nfiles ||
  523             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  524                 return (EBADF);
  525 
  526         if ((fp->f_flag & (FREAD | FWRITE)) == 0)
  527                 return (EBADF);
  528 
  529         switch (com = uap->com) {
  530         case FIONCLEX:
  531                 fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE;
  532                 return (0);
  533         case FIOCLEX:
  534                 fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE;
  535                 return (0);
  536         }
  537 
  538         /*
  539          * Interpret high order word to find amount of data to be
  540          * copied to/from the user's address space.
  541          */
  542         size = IOCPARM_LEN(com);
  543         if (size > IOCPARM_MAX)
  544                 return (ENOTTY);
  545         memp = NULL;
  546         if (size > sizeof (stkbuf)) {
  547                 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
  548                 data = memp;
  549         } else
  550                 data = stkbuf;
  551         if (com&IOC_IN) {
  552                 if (size) {
  553                         error = copyin(uap->data, data, (u_int)size);
  554                         if (error) {
  555                                 if (memp)
  556                                         free(memp, M_IOCTLOPS);
  557                                 return (error);
  558                         }
  559                 } else
  560                         *(caddr_t *)data = uap->data;
  561         } else if ((com&IOC_OUT) && size)
  562                 /*
  563                  * Zero the buffer so the user always
  564                  * gets back something deterministic.
  565                  */
  566                 bzero(data, size);
  567         else if (com&IOC_VOID)
  568                 *(caddr_t *)data = uap->data;
  569 
  570         switch (com) {
  571 
  572         case FIONBIO:
  573                 if ((tmp = *(int *)data))
  574                         fp->f_flag |= FNONBLOCK;
  575                 else
  576                         fp->f_flag &= ~FNONBLOCK;
  577                 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
  578                 break;
  579 
  580         case FIOASYNC:
  581                 if ((tmp = *(int *)data))
  582                         fp->f_flag |= FASYNC;
  583                 else
  584                         fp->f_flag &= ~FASYNC;
  585                 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
  586                 break;
  587 
  588         default:
  589                 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
  590                 /*
  591                  * Copy any data to user, size was
  592                  * already set and checked above.
  593                  */
  594                 if (error == 0 && (com&IOC_OUT) && size)
  595                         error = copyout(data, uap->data, (u_int)size);
  596                 break;
  597         }
  598         if (memp)
  599                 free(memp, M_IOCTLOPS);
  600         return (error);
  601 }
  602 
  603 static int      nselcoll;
  604 int     selwait;
  605 
  606 /*
  607  * Select system call.
  608  */
  609 #ifndef _SYS_SYSPROTO_H_
  610 struct select_args {
  611         int     nd;
  612         fd_set  *in, *ou, *ex;
  613         struct  timeval *tv;
  614 };
  615 #endif
  616 int
  617 select(p, uap)
  618         register struct proc *p;
  619         register struct select_args *uap;
  620 {
  621         /*
  622          * The magic 2048 here is chosen to be just enough for FD_SETSIZE
  623          * infds with the new FD_SETSIZE of 1024, and more than enough for
  624          * FD_SETSIZE infds, outfds and exceptfds with the old FD_SETSIZE
  625          * of 256.
  626          */
  627         fd_mask s_selbits[howmany(2048, NFDBITS)];
  628         fd_mask *ibits[3], *obits[3], *selbits, *sbp;
  629         struct timeval atv, rtv, ttv;
  630         int s, ncoll, error, timo;
  631         u_int nbufbytes, ncpbytes, nfdbits;
  632 
  633         if (uap->nd < 0)
  634                 return (EINVAL);
  635         if (uap->nd > p->p_fd->fd_nfiles)
  636                 uap->nd = p->p_fd->fd_nfiles;   /* forgiving; slightly wrong */
  637 
  638         /*
  639          * Allocate just enough bits for the non-null fd_sets.  Use the
  640          * preallocated auto buffer if possible.
  641          */
  642         nfdbits = roundup(uap->nd, NFDBITS);
  643         ncpbytes = nfdbits / NBBY;
  644         nbufbytes = 0;
  645         if (uap->in != NULL)
  646                 nbufbytes += 2 * ncpbytes;
  647         if (uap->ou != NULL)
  648                 nbufbytes += 2 * ncpbytes;
  649         if (uap->ex != NULL)
  650                 nbufbytes += 2 * ncpbytes;
  651         if (nbufbytes <= sizeof s_selbits)
  652                 selbits = &s_selbits[0];
  653         else
  654                 selbits = malloc(nbufbytes, M_SELECT, M_WAITOK);
  655 
  656         /*
  657          * Assign pointers into the bit buffers and fetch the input bits.
  658          * Put the output buffers together so that they can be bzeroed
  659          * together.
  660          */
  661         sbp = selbits;
  662 #define getbits(name, x) \
  663         do {                                                            \
  664                 if (uap->name == NULL)                                  \
  665                         ibits[x] = NULL;                                \
  666                 else {                                                  \
  667                         ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp;   \
  668                         obits[x] = sbp;                                 \
  669                         sbp += ncpbytes / sizeof *sbp;                  \
  670                         error = copyin(uap->name, ibits[x], ncpbytes);  \
  671                         if (error != 0)                                 \
  672                                 goto done;                              \
  673                 }                                                       \
  674         } while (0)
  675         getbits(in, 0);
  676         getbits(ou, 1);
  677         getbits(ex, 2);
  678 #undef  getbits
  679         if (nbufbytes != 0)
  680                 bzero(selbits, nbufbytes / 2);
  681 
  682         if (uap->tv) {
  683                 error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
  684                         sizeof (atv));
  685                 if (error)
  686                         goto done;
  687                 if (itimerfix(&atv)) {
  688                         error = EINVAL;
  689                         goto done;
  690                 }
  691                 getmicrouptime(&rtv);
  692                 timevaladd(&atv, &rtv);
  693         } else
  694                 atv.tv_sec = 0;
  695         timo = 0;
  696 retry:
  697         ncoll = nselcoll;
  698         p->p_flag |= P_SELECT;
  699         error = selscan(p, ibits, obits, uap->nd);
  700         if (error || p->p_retval[0])
  701                 goto done;
  702         if (atv.tv_sec) {
  703                 getmicrouptime(&rtv);
  704                 if (timevalcmp(&rtv, &atv, >=)) 
  705                         goto done;
  706                 ttv = atv;
  707                 timevalsub(&ttv, &rtv);
  708                 timo = ttv.tv_sec > 24 * 60 * 60 ?
  709                     24 * 60 * 60 * hz : tvtohz(&ttv);
  710         }
  711         s = splhigh();
  712         if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
  713                 splx(s);
  714                 goto retry;
  715         }
  716         p->p_flag &= ~P_SELECT;
  717         error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
  718         splx(s);
  719         if (error == 0)
  720                 goto retry;
  721 done:
  722         p->p_flag &= ~P_SELECT;
  723         /* select is not restarted after signals... */
  724         if (error == ERESTART)
  725                 error = EINTR;
  726         if (error == EWOULDBLOCK)
  727                 error = 0;
  728 #define putbits(name, x) \
  729         if (uap->name && (error2 = copyout(obits[x], uap->name, ncpbytes))) \
  730                 error = error2;
  731         if (error == 0) {
  732                 int error2;
  733 
  734                 putbits(in, 0);
  735                 putbits(ou, 1);
  736                 putbits(ex, 2);
  737 #undef putbits
  738         }
  739         if (selbits != &s_selbits[0])
  740                 free(selbits, M_SELECT);
  741         return (error);
  742 }
  743 
  744 static int
  745 selscan(p, ibits, obits, nfd)
  746         struct proc *p;
  747         fd_mask **ibits, **obits;
  748         int nfd;
  749 {
  750         register struct filedesc *fdp = p->p_fd;
  751         register int msk, i, j, fd;
  752         register fd_mask bits;
  753         struct file *fp;
  754         int n = 0;
  755         /* Note: backend also returns POLLHUP/POLLERR if appropriate. */
  756         static int flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };
  757 
  758         for (msk = 0; msk < 3; msk++) {
  759                 if (ibits[msk] == NULL)
  760                         continue;
  761                 for (i = 0; i < nfd; i += NFDBITS) {
  762                         bits = ibits[msk][i/NFDBITS];
  763                         while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
  764                                 bits &= ~(1 << j);
  765                                 fp = fdp->fd_ofiles[fd];
  766                                 if (fp == NULL)
  767                                         return (EBADF);
  768                                 if ((*fp->f_ops->fo_poll)(fp, flag[msk],
  769                                     fp->f_cred, p)) {
  770                                         obits[msk][(fd)/NFDBITS] |=
  771                                                 (1 << ((fd) % NFDBITS));
  772                                         n++;
  773                                 }
  774                         }
  775                 }
  776         }
  777         p->p_retval[0] = n;
  778         return (0);
  779 }
  780 
  781 /*
  782  * Poll system call.
  783  */
  784 #ifndef _SYS_SYSPROTO_H_
  785 struct poll_args {
  786         struct pollfd *fds;
  787         u_int   nfds;
  788         int     timeout;
  789 };
  790 #endif
  791 int
  792 poll(p, uap)
  793         register struct proc *p;
  794         register struct poll_args *uap;
  795 {
  796         caddr_t bits;
  797         char smallbits[32 * sizeof(struct pollfd)];
  798         struct timeval atv, rtv, ttv;
  799         int s, ncoll, error = 0, timo;
  800         size_t ni;
  801 
  802         if (SCARG(uap, nfds) > p->p_fd->fd_nfiles) {
  803                 /* forgiving; slightly wrong */
  804                 SCARG(uap, nfds) = p->p_fd->fd_nfiles;
  805         }
  806         ni = SCARG(uap, nfds) * sizeof(struct pollfd);
  807         if (ni > sizeof(smallbits))
  808                 bits = malloc(ni, M_TEMP, M_WAITOK);
  809         else
  810                 bits = smallbits;
  811         error = copyin(SCARG(uap, fds), bits, ni);
  812         if (error)
  813                 goto done;
  814         if (SCARG(uap, timeout) != INFTIM) {
  815                 atv.tv_sec = SCARG(uap, timeout) / 1000;
  816                 atv.tv_usec = (SCARG(uap, timeout) % 1000) * 1000;
  817                 if (itimerfix(&atv)) {
  818                         error = EINVAL;
  819                         goto done;
  820                 }
  821                 getmicrouptime(&rtv);
  822                 timevaladd(&atv, &rtv);
  823         } else
  824                 atv.tv_sec = 0;
  825         timo = 0;
  826 retry:
  827         ncoll = nselcoll;
  828         p->p_flag |= P_SELECT;
  829         error = pollscan(p, (struct pollfd *)bits, SCARG(uap, nfds));
  830         if (error || p->p_retval[0])
  831                 goto done;
  832         if (atv.tv_sec) {
  833                 getmicrouptime(&rtv);
  834                 if (timevalcmp(&rtv, &atv, >=))
  835                         goto done;
  836                 ttv = atv;
  837                 timevalsub(&ttv, &rtv);
  838                 timo = ttv.tv_sec > 24 * 60 * 60 ?
  839                     24 * 60 * 60 * hz : tvtohz(&ttv);
  840         } 
  841         s = splhigh(); 
  842         if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
  843                 splx(s);
  844                 goto retry;
  845         }
  846         p->p_flag &= ~P_SELECT;
  847         error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "poll", timo);
  848         splx(s);
  849         if (error == 0)
  850                 goto retry;
  851 done:
  852         p->p_flag &= ~P_SELECT;
  853         /* poll is not restarted after signals... */
  854         if (error == ERESTART)
  855                 error = EINTR;
  856         if (error == EWOULDBLOCK)
  857                 error = 0;
  858         if (error == 0) {
  859                 error = copyout(bits, SCARG(uap, fds), ni);
  860                 if (error)
  861                         goto out;
  862         }
  863 out:
  864         if (ni > sizeof(smallbits))
  865                 free(bits, M_TEMP);
  866         return (error);
  867 }
  868 
  869 static int
  870 pollscan(p, fds, nfd)
  871         struct proc *p;
  872         struct pollfd *fds;
  873         int nfd;
  874 {
  875         register struct filedesc *fdp = p->p_fd;
  876         int i;
  877         struct file *fp;
  878         int n = 0;
  879 
  880         for (i = 0; i < nfd; i++, fds++) {
  881                 if (fds->fd >= fdp->fd_nfiles) {
  882                         fds->revents = POLLNVAL;
  883                         n++;
  884                 } else if (fds->fd < 0) {
  885                         fds->revents = 0;
  886                 } else {
  887                         fp = fdp->fd_ofiles[fds->fd];
  888                         if (fp == 0) {
  889                                 fds->revents = POLLNVAL;
  890                                 n++;
  891                         } else {
  892                                 /*
  893                                  * Note: backend also returns POLLHUP and
  894                                  * POLLERR if appropriate.
  895                                  */
  896                                 fds->revents = (*fp->f_ops->fo_poll)(fp,
  897                                     fds->events, fp->f_cred, p);
  898                                 if (fds->revents != 0)
  899                                         n++;
  900                         }
  901                 }
  902         }
  903         p->p_retval[0] = n;
  904         return (0);
  905 }
  906 
  907 /*
  908  * OpenBSD poll system call.
  909  * XXX this isn't quite a true representation..  OpenBSD uses select ops.
  910  */
  911 #ifndef _SYS_SYSPROTO_H_
  912 struct openbsd_poll_args {
  913         struct pollfd *fds;
  914         u_int   nfds;
  915         int     timeout;
  916 };
  917 #endif
  918 int
  919 openbsd_poll(p, uap)
  920         register struct proc *p;
  921         register struct openbsd_poll_args *uap;
  922 {
  923         return (poll(p, (struct poll_args *)uap));
  924 }
  925 
  926 /*ARGSUSED*/
  927 int
  928 seltrue(dev, events, p)
  929         dev_t dev;
  930         int events;
  931         struct proc *p;
  932 {
  933 
  934         return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
  935 }
  936 
  937 /*
  938  * Record a select request.
  939  */
  940 void
  941 selrecord(selector, sip)
  942         struct proc *selector;
  943         struct selinfo *sip;
  944 {
  945         struct proc *p;
  946         pid_t mypid;
  947 
  948         mypid = selector->p_pid;
  949         if (sip->si_pid == mypid)
  950                 return;
  951         if (sip->si_pid && (p = pfind(sip->si_pid)) &&
  952             p->p_wchan == (caddr_t)&selwait)
  953                 sip->si_flags |= SI_COLL;
  954         else
  955                 sip->si_pid = mypid;
  956 }
  957 
  958 /*
  959  * Do a wakeup when a selectable event occurs.
  960  */
  961 void
  962 selwakeup(sip)
  963         register struct selinfo *sip;
  964 {
  965         register struct proc *p;
  966         int s;
  967 
  968         if (sip->si_pid == 0)
  969                 return;
  970         if (sip->si_flags & SI_COLL) {
  971                 nselcoll++;
  972                 sip->si_flags &= ~SI_COLL;
  973                 wakeup((caddr_t)&selwait);
  974         }
  975         p = pfind(sip->si_pid);
  976         sip->si_pid = 0;
  977         if (p != NULL) {
  978                 s = splhigh();
  979                 if (p->p_wchan == (caddr_t)&selwait) {
  980                         if (p->p_stat == SSLEEP)
  981                                 setrunnable(p);
  982                         else
  983                                 unsleep(p);
  984                 } else if (p->p_flag & P_SELECT)
  985                         p->p_flag &= ~P_SELECT;
  986                 splx(s);
  987         }
  988 }

Cache object: 7486af39cbe87f04b340855557af8477


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.