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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
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: src/sys/kern/sys_generic.c,v 1.20.2.1 1999/09/05 08:15:17 peter Exp $
   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/ioctl.h>
   49 #include <sys/file.h>
   50 #include <sys/proc.h>
   51 #include <sys/stat.h>
   52 #include <sys/signalvar.h>
   53 #include <sys/socket.h>
   54 #include <sys/socketvar.h>
   55 #include <sys/uio.h>
   56 #include <sys/kernel.h>
   57 #include <sys/stat.h>
   58 #include <sys/malloc.h>
   59 #ifdef KTRACE
   60 #include <sys/ktrace.h>
   61 #endif
   62 #include <vm/vm.h>
   63 
   64 static int      selscan __P((struct proc *, fd_mask **, fd_mask **, int, int *));
   65 
   66 /*
   67  * Read system call.
   68  */
   69 #ifndef _SYS_SYSPROTO_H_
   70 struct read_args {
   71         int     fd;
   72         char    *buf;
   73         u_int   nbyte;
   74 };
   75 #endif
   76 /* ARGSUSED */
   77 int
   78 read(p, uap, retval)
   79         struct proc *p;
   80         register struct read_args *uap;
   81         int *retval;
   82 {
   83         register struct file *fp;
   84         register struct filedesc *fdp = p->p_fd;
   85         struct uio auio;
   86         struct iovec aiov;
   87         long cnt, error = 0;
   88 #ifdef KTRACE
   89         struct iovec ktriov;
   90 #endif
   91 
   92         if (((u_int)uap->fd) >= fdp->fd_nfiles ||
   93             (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
   94             (fp->f_flag & FREAD) == 0)
   95                 return (EBADF);
   96         aiov.iov_base = (caddr_t)uap->buf;
   97         aiov.iov_len = uap->nbyte;
   98         auio.uio_iov = &aiov;
   99         auio.uio_iovcnt = 1;
  100 
  101         auio.uio_resid = uap->nbyte;
  102         if (auio.uio_resid < 0)
  103                 return (EINVAL);
  104 
  105         auio.uio_rw = UIO_READ;
  106         auio.uio_segflg = UIO_USERSPACE;
  107         auio.uio_procp = p;
  108 #ifdef KTRACE
  109         /*
  110          * if tracing, save a copy of iovec
  111          */
  112         if (KTRPOINT(p, KTR_GENIO))
  113                 ktriov = aiov;
  114 #endif
  115         cnt = uap->nbyte;
  116         if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)))
  117                 if (auio.uio_resid != cnt && (error == ERESTART ||
  118                     error == EINTR || error == EWOULDBLOCK))
  119                         error = 0;
  120         cnt -= auio.uio_resid;
  121 #ifdef KTRACE
  122         if (KTRPOINT(p, KTR_GENIO) && error == 0)
  123                 ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktriov, cnt, error);
  124 #endif
  125         *retval = cnt;
  126         return (error);
  127 }
  128 
  129 /*
  130  * Scatter read system call.
  131  */
  132 #ifndef _SYS_SYSPROTO_H_
  133 struct readv_args {
  134         int     fd;
  135         struct  iovec *iovp;
  136         u_int   iovcnt;
  137 };
  138 #endif
  139 int
  140 readv(p, uap, retval)
  141         struct proc *p;
  142         register struct readv_args *uap;
  143         int *retval;
  144 {
  145         register struct file *fp;
  146         register struct filedesc *fdp = p->p_fd;
  147         struct uio auio;
  148         register struct iovec *iov;
  149         struct iovec *needfree;
  150         struct iovec aiov[UIO_SMALLIOV];
  151         long i, cnt, error = 0;
  152         u_int iovlen;
  153 #ifdef KTRACE
  154         struct iovec *ktriov = NULL;
  155 #endif
  156 
  157         if (((u_int)uap->fd) >= fdp->fd_nfiles ||
  158             (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
  159             (fp->f_flag & FREAD) == 0)
  160                 return (EBADF);
  161         /* note: can't use iovlen until iovcnt is validated */
  162         iovlen = uap->iovcnt * sizeof (struct iovec);
  163         if (uap->iovcnt > UIO_SMALLIOV) {
  164                 if (uap->iovcnt > UIO_MAXIOV)
  165                         return (EINVAL);
  166                 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
  167                 needfree = iov;
  168         } else {
  169                 iov = aiov;
  170                 needfree = NULL;
  171         }
  172         auio.uio_iov = iov;
  173         auio.uio_iovcnt = uap->iovcnt;
  174         auio.uio_rw = UIO_READ;
  175         auio.uio_segflg = UIO_USERSPACE;
  176         auio.uio_procp = p;
  177         if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
  178                 goto done;
  179         auio.uio_resid = 0;
  180         for (i = 0; i < uap->iovcnt; i++) {
  181                 auio.uio_resid += iov->iov_len;
  182                 if (auio.uio_resid < 0) {
  183                         error = EINVAL;
  184                         goto done;
  185                 }
  186                 iov++;
  187         }
  188 #ifdef KTRACE
  189         /*
  190          * if tracing, save a copy of iovec
  191          */
  192         if (KTRPOINT(p, KTR_GENIO))  {
  193                 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
  194                 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
  195         }
  196 #endif
  197         cnt = auio.uio_resid;
  198         if ((error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)))
  199                 if (auio.uio_resid != cnt && (error == ERESTART ||
  200                     error == EINTR || error == EWOULDBLOCK))
  201                         error = 0;
  202         cnt -= auio.uio_resid;
  203 #ifdef KTRACE
  204         if (ktriov != NULL) {
  205                 if (error == 0)
  206                         ktrgenio(p->p_tracep, uap->fd, UIO_READ, ktriov,
  207                             cnt, error);
  208                 FREE(ktriov, M_TEMP);
  209         }
  210 #endif
  211         *retval = cnt;
  212 done:
  213         if (needfree)
  214                 FREE(needfree, M_IOV);
  215         return (error);
  216 }
  217 
  218 /*
  219  * Write system call
  220  */
  221 #ifndef _SYS_SYSPROTO_H_
  222 struct write_args {
  223         int     fd;
  224         char    *buf;
  225         u_int   nbyte;
  226 };
  227 #endif
  228 int
  229 write(p, uap, retval)
  230         struct proc *p;
  231         register struct write_args *uap;
  232         int *retval;
  233 {
  234         register struct file *fp;
  235         register struct filedesc *fdp = p->p_fd;
  236         struct uio auio;
  237         struct iovec aiov;
  238         long cnt, error = 0;
  239 #ifdef KTRACE
  240         struct iovec ktriov;
  241 #endif
  242 
  243         if (((u_int)uap->fd) >= fdp->fd_nfiles ||
  244             (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
  245             (fp->f_flag & FWRITE) == 0)
  246                 return (EBADF);
  247         aiov.iov_base = (caddr_t)uap->buf;
  248         aiov.iov_len = uap->nbyte;
  249         auio.uio_iov = &aiov;
  250         auio.uio_iovcnt = 1;
  251         auio.uio_resid = uap->nbyte;
  252         auio.uio_rw = UIO_WRITE;
  253         auio.uio_segflg = UIO_USERSPACE;
  254         auio.uio_procp = p;
  255 #ifdef KTRACE
  256         /*
  257          * if tracing, save a copy of iovec
  258          */
  259         if (KTRPOINT(p, KTR_GENIO))
  260                 ktriov = aiov;
  261 #endif
  262         cnt = uap->nbyte;
  263         if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred))) {
  264                 if (auio.uio_resid != cnt && (error == ERESTART ||
  265                     error == EINTR || error == EWOULDBLOCK))
  266                         error = 0;
  267                 if (error == EPIPE)
  268                         psignal(p, SIGPIPE);
  269         }
  270         cnt -= auio.uio_resid;
  271 #ifdef KTRACE
  272         if (KTRPOINT(p, KTR_GENIO) && error == 0)
  273                 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE,
  274                     &ktriov, cnt, error);
  275 #endif
  276         *retval = cnt;
  277         return (error);
  278 }
  279 
  280 /*
  281  * Gather write system call
  282  */
  283 #ifndef _SYS_SYSPROTO_H_
  284 struct writev_args {
  285         int     fd;
  286         struct  iovec *iovp;
  287         u_int   iovcnt;
  288 };
  289 #endif
  290 int
  291 writev(p, uap, retval)
  292         struct proc *p;
  293         register struct writev_args *uap;
  294         int *retval;
  295 {
  296         register struct file *fp;
  297         register struct filedesc *fdp = p->p_fd;
  298         struct uio auio;
  299         register struct iovec *iov;
  300         struct iovec *needfree;
  301         struct iovec aiov[UIO_SMALLIOV];
  302         long i, cnt, error = 0;
  303         u_int iovlen;
  304 #ifdef KTRACE
  305         struct iovec *ktriov = NULL;
  306 #endif
  307 
  308         if (((u_int)uap->fd) >= fdp->fd_nfiles ||
  309             (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
  310             (fp->f_flag & FWRITE) == 0)
  311                 return (EBADF);
  312         /* note: can't use iovlen until iovcnt is validated */
  313         iovlen = uap->iovcnt * sizeof (struct iovec);
  314         if (uap->iovcnt > UIO_SMALLIOV) {
  315                 if (uap->iovcnt > UIO_MAXIOV)
  316                         return (EINVAL);
  317                 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
  318                 needfree = iov;
  319         } else {
  320                 iov = aiov;
  321                 needfree = NULL;
  322         }
  323         auio.uio_iov = iov;
  324         auio.uio_iovcnt = uap->iovcnt;
  325         auio.uio_rw = UIO_WRITE;
  326         auio.uio_segflg = UIO_USERSPACE;
  327         auio.uio_procp = p;
  328         if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
  329                 goto done;
  330         auio.uio_resid = 0;
  331         for (i = 0; i < uap->iovcnt; i++) {
  332                 auio.uio_resid += iov->iov_len;
  333                 if (auio.uio_resid < 0) {
  334                         error = EINVAL;
  335                         goto done;
  336                 }
  337                 iov++;
  338         }
  339 #ifdef KTRACE
  340         /*
  341          * if tracing, save a copy of iovec
  342          */
  343         if (KTRPOINT(p, KTR_GENIO))  {
  344                 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
  345                 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
  346         }
  347 #endif
  348         cnt = auio.uio_resid;
  349         if ((error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred))) {
  350                 if (auio.uio_resid != cnt && (error == ERESTART ||
  351                     error == EINTR || error == EWOULDBLOCK))
  352                         error = 0;
  353                 if (error == EPIPE)
  354                         psignal(p, SIGPIPE);
  355         }
  356         cnt -= auio.uio_resid;
  357 #ifdef KTRACE
  358         if (ktriov != NULL) {
  359                 if (error == 0)
  360                         ktrgenio(p->p_tracep, uap->fd, UIO_WRITE,
  361                                 ktriov, cnt, error);
  362                 FREE(ktriov, M_TEMP);
  363         }
  364 #endif
  365         *retval = cnt;
  366 done:
  367         if (needfree)
  368                 FREE(needfree, M_IOV);
  369         return (error);
  370 }
  371 
  372 /*
  373  * Ioctl system call
  374  */
  375 #ifndef _SYS_SYSPROTO_H_
  376 struct ioctl_args {
  377         int     fd;
  378         int     com;
  379         caddr_t data;
  380 };
  381 #endif
  382 /* ARGSUSED */
  383 int
  384 ioctl(p, uap, retval)
  385         struct proc *p;
  386         register struct ioctl_args *uap;
  387         int *retval;
  388 {
  389         register struct file *fp;
  390         register struct filedesc *fdp;
  391         register int com, error;
  392         register u_int size;
  393         caddr_t data, memp;
  394         int tmp;
  395 #define STK_PARAMS      128
  396         char stkbuf[STK_PARAMS];
  397 
  398         fdp = p->p_fd;
  399         if ((u_int)uap->fd >= fdp->fd_nfiles ||
  400             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
  401                 return (EBADF);
  402 
  403         if ((fp->f_flag & (FREAD | FWRITE)) == 0)
  404                 return (EBADF);
  405 
  406         switch (com = uap->com) {
  407         case FIONCLEX:
  408                 fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE;
  409                 return (0);
  410         case FIOCLEX:
  411                 fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE;
  412                 return (0);
  413         }
  414 
  415         /*
  416          * Interpret high order word to find amount of data to be
  417          * copied to/from the user's address space.
  418          */
  419         size = IOCPARM_LEN(com);
  420         if (size > IOCPARM_MAX)
  421                 return (ENOTTY);
  422         memp = NULL;
  423         if (size > sizeof (stkbuf)) {
  424                 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
  425                 data = memp;
  426         } else
  427                 data = stkbuf;
  428         if (com&IOC_IN) {
  429                 if (size) {
  430                         error = copyin(uap->data, data, (u_int)size);
  431                         if (error) {
  432                                 if (memp)
  433                                         free(memp, M_IOCTLOPS);
  434                                 return (error);
  435                         }
  436                 } else
  437                         *(caddr_t *)data = uap->data;
  438         } else if ((com&IOC_OUT) && size)
  439                 /*
  440                  * Zero the buffer so the user always
  441                  * gets back something deterministic.
  442                  */
  443                 bzero(data, size);
  444         else if (com&IOC_VOID)
  445                 *(caddr_t *)data = uap->data;
  446 
  447         switch (com) {
  448 
  449         case FIONBIO:
  450                 if ((tmp = *(int *)data))
  451                         fp->f_flag |= FNONBLOCK;
  452                 else
  453                         fp->f_flag &= ~FNONBLOCK;
  454                 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
  455                 break;
  456 
  457         case FIOASYNC:
  458                 if ((tmp = *(int *)data))
  459                         fp->f_flag |= FASYNC;
  460                 else
  461                         fp->f_flag &= ~FASYNC;
  462                 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
  463                 break;
  464 
  465         case FIOSETOWN:
  466                 tmp = *(int *)data;
  467                 if (fp->f_type == DTYPE_SOCKET) {
  468                         ((struct socket *)fp->f_data)->so_pgid = tmp;
  469                         error = 0;
  470                         break;
  471                 }
  472                 if (tmp <= 0) {
  473                         tmp = -tmp;
  474                 } else {
  475                         struct proc *p1 = pfind(tmp);
  476                         if (p1 == 0) {
  477                                 error = ESRCH;
  478                                 break;
  479                         }
  480                         tmp = p1->p_pgrp->pg_id;
  481                 }
  482                 error = (*fp->f_ops->fo_ioctl)
  483                         (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
  484                 break;
  485 
  486         case FIOGETOWN:
  487                 if (fp->f_type == DTYPE_SOCKET) {
  488                         error = 0;
  489                         *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
  490                         break;
  491                 }
  492                 error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p);
  493                 *(int *)data = -*(int *)data;
  494                 break;
  495 
  496         default:
  497                 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
  498                 /*
  499                  * Copy any data to user, size was
  500                  * already set and checked above.
  501                  */
  502                 if (error == 0 && (com&IOC_OUT) && size)
  503                         error = copyout(data, uap->data, (u_int)size);
  504                 break;
  505         }
  506         if (memp)
  507                 free(memp, M_IOCTLOPS);
  508         return (error);
  509 }
  510 
  511 static int      nselcoll;
  512 int     selwait;
  513 
  514 /*
  515  * Select system call.
  516  */
  517 #ifndef _SYS_SYSPROTO_H_
  518 struct select_args {
  519         int     nd;
  520         fd_set  *in, *ou, *ex;
  521         struct  timeval *tv;
  522 };
  523 #endif
  524 int
  525 select(p, uap, retval)
  526         register struct proc *p;
  527         register struct select_args *uap;
  528         int *retval;
  529 {
  530         fd_mask *ibits[3], *obits[3];
  531         struct timeval atv;
  532         int s, ncoll, error = 0, timo, i;
  533         u_int ni;
  534 
  535         if (uap->nd < 0)
  536                 return (EINVAL);
  537 
  538         if (uap->nd > p->p_fd->fd_nfiles)
  539                 uap->nd = p->p_fd->fd_nfiles;   /* forgiving; slightly wrong */
  540 
  541         /* The amount of space we need to allocate */
  542         ni = howmany(roundup2 (uap->nd, FD_SETSIZE), NFDBITS) *
  543                 sizeof(fd_mask);
  544 
  545         if (ni > p->p_selbits_size) {
  546                 if (p->p_selbits_size)
  547                         free (p->p_selbits, M_SELECT);
  548 
  549                 while (p->p_selbits_size < ni)
  550                         p->p_selbits_size += 32; /* Increase by 256 bits */
  551 
  552                 p->p_selbits = malloc(p->p_selbits_size * 6, M_SELECT,
  553                         M_WAITOK);
  554         }
  555         for (i = 0; i < 3; i++) {
  556                 ibits[i] = (fd_mask *)(p->p_selbits + i * p->p_selbits_size);
  557                 obits[i] = (fd_mask *)(p->p_selbits + (i + 3) *
  558                         p->p_selbits_size);
  559         }
  560 
  561         /*
  562          * This buffer is usually very small therefore it's probably faster
  563          * to just zero it, rather than calculate what needs to be zeroed.
  564          */
  565         bzero (p->p_selbits, p->p_selbits_size * 6);
  566 
  567         /* The amount of space we need to copyin/copyout */
  568         ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
  569 
  570 #define getbits(name, x) \
  571         if (uap->name && \
  572             (error = copyin((caddr_t)uap->name, (caddr_t)ibits[x], ni))) \
  573                 goto done;
  574         getbits(in, 0);
  575         getbits(ou, 1);
  576         getbits(ex, 2);
  577 #undef  getbits
  578 
  579         if (uap->tv) {
  580                 error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
  581                         sizeof (atv));
  582                 if (error)
  583                         goto done;
  584                 if (itimerfix(&atv)) {
  585                         error = EINVAL;
  586                         goto done;
  587                 }
  588                 s = splclock();
  589                 timevaladd(&atv, (struct timeval *)&time);
  590                 timo = hzto(&atv);
  591                 /*
  592                  * Avoid inadvertently sleeping forever.
  593                  */
  594                 if (timo == 0)
  595                         timo = 1;
  596                 splx(s);
  597         } else
  598                 timo = 0;
  599 retry:
  600         ncoll = nselcoll;
  601         p->p_flag |= P_SELECT;
  602         error = selscan(p, ibits, obits, uap->nd, retval);
  603         if (error || *retval)
  604                 goto done;
  605         s = splhigh();
  606         /* this should be timercmp(&time, &atv, >=) */
  607         if (uap->tv && (time.tv_sec > atv.tv_sec ||
  608             (time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec))) {
  609                 splx(s);
  610                 goto done;
  611         }
  612         if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
  613                 splx(s);
  614                 goto retry;
  615         }
  616         p->p_flag &= ~P_SELECT;
  617         error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
  618         splx(s);
  619         if (error == 0)
  620                 goto retry;
  621 done:
  622         p->p_flag &= ~P_SELECT;
  623         /* select is not restarted after signals... */
  624         if (error == ERESTART)
  625                 error = EINTR;
  626         if (error == EWOULDBLOCK)
  627                 error = 0;
  628 #define putbits(name, x) \
  629         if (uap->name && \
  630             (error2 = copyout((caddr_t)obits[x], (caddr_t)uap->name, ni))) \
  631                 error = error2;
  632         if (error == 0) {
  633                 int error2;
  634 
  635                 putbits(in, 0);
  636                 putbits(ou, 1);
  637                 putbits(ex, 2);
  638 #undef putbits
  639         }
  640         return (error);
  641 }
  642 
  643 static int
  644 selscan(p, ibits, obits, nfd, retval)
  645         struct proc *p;
  646         fd_mask **ibits, **obits;
  647         int nfd, *retval;
  648 {
  649         register struct filedesc *fdp = p->p_fd;
  650         register int msk, i, j, fd;
  651         register fd_mask bits;
  652         struct file *fp;
  653         int n = 0;
  654         static int flag[3] = { FREAD, FWRITE, 0 };
  655 
  656         for (msk = 0; msk < 3; msk++) {
  657                 for (i = 0; i < nfd; i += NFDBITS) {
  658                         bits = ibits[msk][i/NFDBITS];
  659                         while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
  660                                 bits &= ~(1 << j);
  661                                 fp = fdp->fd_ofiles[fd];
  662                                 if (fp == NULL)
  663                                         return (EBADF);
  664                                 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
  665                                         obits[msk][(fd)/NFDBITS] |= 
  666                                                 (1 << ((fd) % NFDBITS));
  667                                         n++;
  668                                 }
  669                         }
  670                 }
  671         }
  672         *retval = n;
  673         return (0);
  674 }
  675 
  676 /*ARGSUSED*/
  677 int
  678 seltrue(dev, flag, p)
  679         dev_t dev;
  680         int flag;
  681         struct proc *p;
  682 {
  683 
  684         return (1);
  685 }
  686 
  687 /*
  688  * Record a select request.
  689  */
  690 void
  691 selrecord(selector, sip)
  692         struct proc *selector;
  693         struct selinfo *sip;
  694 {
  695         struct proc *p;
  696         pid_t mypid;
  697 
  698         mypid = selector->p_pid;
  699         if (sip->si_pid == mypid)
  700                 return;
  701         if (sip->si_pid && (p = pfind(sip->si_pid)) &&
  702             p->p_wchan == (caddr_t)&selwait)
  703                 sip->si_flags |= SI_COLL;
  704         else
  705                 sip->si_pid = mypid;
  706 }
  707 
  708 /*
  709  * Do a wakeup when a selectable event occurs.
  710  */
  711 void
  712 selwakeup(sip)
  713         register struct selinfo *sip;
  714 {
  715         register struct proc *p;
  716         int s;
  717 
  718         if (sip->si_pid == 0)
  719                 return;
  720         if (sip->si_flags & SI_COLL) {
  721                 nselcoll++;
  722                 sip->si_flags &= ~SI_COLL;
  723                 wakeup((caddr_t)&selwait);
  724         }
  725         p = pfind(sip->si_pid);
  726         sip->si_pid = 0;
  727         if (p != NULL) {
  728                 s = splhigh();
  729                 if (p->p_wchan == (caddr_t)&selwait) {
  730                         if (p->p_stat == SSLEEP)
  731                                 setrunnable(p);
  732                         else
  733                                 unsleep(p);
  734                 } else if (p->p_flag & P_SELECT)
  735                         p->p_flag &= ~P_SELECT;
  736                 splx(s);
  737         }
  738 }

Cache object: 7fac0287b46279201bc704e03851c2b8


[ 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.