Annotation of kernel/bsd/kern/sys_generic.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * Copyright (c) 1982, 1986, 1989, 1993
                     28:  *     The Regents of the University of California.  All rights reserved.
                     29:  * (c) UNIX System Laboratories, Inc.
                     30:  * All or some portions of this file are derived from material licensed
                     31:  * to the University of California by American Telephone and Telegraph
                     32:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     33:  * the permission of UNIX System Laboratories, Inc.
                     34:  *
                     35:  * Redistribution and use in source and binary forms, with or without
                     36:  * modification, are permitted provided that the following conditions
                     37:  * are met:
                     38:  * 1. Redistributions of source code must retain the above copyright
                     39:  *    notice, this list of conditions and the following disclaimer.
                     40:  * 2. Redistributions in binary form must reproduce the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer in the
                     42:  *    documentation and/or other materials provided with the distribution.
                     43:  * 3. All advertising materials mentioning features or use of this software
                     44:  *    must display the following acknowledgement:
                     45:  *     This product includes software developed by the University of
                     46:  *     California, Berkeley and its contributors.
                     47:  * 4. Neither the name of the University nor the names of its contributors
                     48:  *    may be used to endorse or promote products derived from this software
                     49:  *    without specific prior written permission.
                     50:  *
                     51:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     52:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     53:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     54:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     55:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     56:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     57:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     58:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     59:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     60:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     61:  * SUCH DAMAGE.
                     62:  *
                     63:  *     @(#)sys_generic.c       8.9 (Berkeley) 2/14/95
                     64:  */
                     65: 
                     66: #include <sys/param.h>
                     67: #include <sys/systm.h>
                     68: #include <sys/filedesc.h>
                     69: #include <sys/ioctl.h>
                     70: #include <sys/file.h>
                     71: #include <sys/proc.h>
                     72: #include <sys/socketvar.h>
                     73: #include <sys/uio.h>
                     74: #include <sys/kernel.h>
                     75: #include <sys/stat.h>
                     76: #include <sys/malloc.h>
                     77: #if KTRACE
                     78: #include <sys/ktrace.h>
                     79: #endif
                     80: 
                     81: #include <sys/mount.h>
                     82: #include <sys/protosw.h>
                     83: #include <sys/ev.h>
                     84: #include <sys/user.h>
                     85: #include <kern/kdebug.h>
                     86: 
                     87: /*
                     88:  * Read system call.
                     89:  */
                     90: struct read_args {
                     91:        int fd;
                     92:        char *cbuf;
                     93:        u_int nbyte;
                     94: };
                     95: /* ARGSUSED */
                     96: read(p, uap, retval)
                     97:        struct proc *p;
                     98:        register struct read_args *uap;
                     99:        register_t *retval;
                    100: {
                    101:        struct uio auio;
                    102:        struct iovec aiov;
                    103: 
                    104:        aiov.iov_base = (caddr_t)uap->cbuf;
                    105:        aiov.iov_len = uap->nbyte;
                    106:        auio.uio_iov = &aiov;
                    107:        auio.uio_iovcnt = 1;
                    108:        auio.uio_rw = UIO_READ;
                    109:        return (rwuio(p, uap->fd, &auio, UIO_READ, retval));    
                    110: }
                    111: 
                    112: struct readv_args {
                    113:        int fd;
                    114:        struct iovec *iovp;
                    115:        u_int iovcnt;
                    116: };
                    117: readv(p, uap, retval)
                    118:        struct proc *p;
                    119:        register struct readv_args *uap;
                    120:        int *retval;
                    121: {
                    122:        struct uio auio;
                    123:        register struct iovec *iov;
                    124:        int error;
                    125:        struct iovec aiov[UIO_SMALLIOV];
                    126: 
                    127:        if (uap->iovcnt > UIO_SMALLIOV) {
                    128:                if (uap->iovcnt > UIO_MAXIOV)
                    129:                        return (EINVAL);        
                    130:                if ((iov = (struct iovec *)
                    131:                            kalloc(sizeof(struct iovec) * (uap->iovcnt))) == 0)
                    132:                        return (ENOMEM);
                    133:        } else
                    134:                iov = aiov;
                    135:        auio.uio_iov = iov;
                    136:        auio.uio_iovcnt = uap->iovcnt;
                    137:        auio.uio_rw = UIO_READ;
                    138:        error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
                    139:            uap->iovcnt * sizeof (struct iovec));
                    140:        if (!error)
                    141:                error = rwuio(p, uap->fd, &auio, UIO_READ, retval);
                    142:        if (uap->iovcnt > UIO_SMALLIOV)
                    143:                kfree(iov, sizeof(struct iovec)*uap->iovcnt);
                    144:        return (error);
                    145: }
                    146: 
                    147: /*
                    148:  * Write system call
                    149:  */
                    150: struct write_args {
                    151:        int fd;
                    152:        char *cbuf;
                    153:        u_int nbyte;
                    154: };
                    155: write(p, uap, retval)
                    156:        struct proc *p;
                    157:        register struct write_args *uap;
                    158:        int *retval;
                    159: {
                    160:        struct uio auio;
                    161:        struct iovec aiov;
                    162: 
                    163:        aiov.iov_base = uap->cbuf;
                    164:        aiov.iov_len = uap->nbyte;
                    165:        auio.uio_iov = &aiov;
                    166:        auio.uio_iovcnt = 1;
                    167:        auio.uio_rw = UIO_WRITE;
                    168:        return (rwuio(p, uap->fd, &auio, UIO_WRITE, retval));
                    169: }
                    170: 
                    171: struct writev_args {
                    172:        int fd;
                    173:        struct iovec *iovp;
                    174:        u_int iovcnt;
                    175: };
                    176: writev(p, uap, retval)
                    177:        struct proc *p;
                    178:        register struct writev_args *uap;
                    179:        int *retval;
                    180: {
                    181:        struct uio auio;
                    182:        register struct iovec *iov;
                    183:        int error;
                    184:        struct iovec aiov[UIO_SMALLIOV];
                    185: 
                    186:        if (uap->iovcnt > UIO_SMALLIOV) {
                    187:                if (uap->iovcnt > UIO_MAXIOV)
                    188:                        return (EINVAL);        
                    189:                if ((iov = (struct iovec *)
                    190:                            kalloc(sizeof(struct iovec) * (uap->iovcnt))) == 0)
                    191:                        return (ENOMEM);
                    192:        } else
                    193:                iov = aiov;
                    194:        auio.uio_iov = iov;
                    195:        auio.uio_iovcnt = uap->iovcnt;
                    196:        auio.uio_rw = UIO_WRITE;
                    197:        error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
                    198:            uap->iovcnt * sizeof (struct iovec));
                    199:        if (!error)
                    200:                error = rwuio(p, uap->fd, &auio, UIO_WRITE, retval);
                    201:        if (uap->iovcnt > UIO_SMALLIOV)
                    202:                kfree(iov, sizeof(struct iovec)*uap->iovcnt);
                    203:        return (error);
                    204: }
                    205: 
                    206: rwuio(p, fdes, uio, rw, retval)
                    207:        struct proc *p;
                    208:        int fdes;
                    209:        register struct uio *uio;
                    210:        enum uio_rw rw;
                    211:        int *retval;
                    212: {
                    213:        register struct file *fp;
                    214:        register struct iovec *iov;
                    215:        int i, count, flag, error;
                    216: 
                    217:        if (error = fdgetf(p, fdes, &fp))
                    218:                return (error);
                    219: 
                    220:        if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) {
                    221:                return(EBADF);
                    222:        }
                    223:        uio->uio_resid = 0;
                    224:        uio->uio_segflg = UIO_USERSPACE;
                    225:        uio->uio_procp = p;
                    226:        iov = uio->uio_iov;
                    227:        for (i = 0; i < uio->uio_iovcnt; i++) {
                    228:                if (iov->iov_len < 0) {
                    229:                        return(EINVAL);
                    230:                }
                    231:                uio->uio_resid += iov->iov_len;
                    232:                if (uio->uio_resid < 0) {
                    233:                        return(EINVAL);
                    234:                }
                    235:                iov++;
                    236:        }
                    237:        count = uio->uio_resid;
                    238:        if (rw == UIO_READ) {
                    239:                if (error = (*fp->f_ops->fo_read)(fp, uio, fp->f_cred))
                    240:                                if (uio->uio_resid != count && (error == ERESTART ||
                    241:                                        error == EINTR || error == EWOULDBLOCK))
                    242:                                                error = 0;
                    243:        } else {
                    244:                if (error = (*fp->f_ops->fo_write)(fp, uio, fp->f_cred)) {
                    245:                        if (uio->uio_resid != count && (error == ERESTART ||
                    246:                        error == EINTR || error == EWOULDBLOCK))
                    247:                                error = 0;
                    248:                        if (error == EPIPE)
                    249:                                psignal(p, SIGPIPE);
                    250:                }
                    251:        }
                    252:        *retval = count - uio->uio_resid;
                    253:        return(error);
                    254: }
                    255: 
                    256: /*
                    257:  * Ioctl system call
                    258:  */
                    259: struct ioctl_args {
                    260:        int fd;
                    261:        u_long com;
                    262:        caddr_t data;
                    263: };
                    264: /* ARGSUSED */
                    265: ioctl(p, uap, retval)
                    266:        struct proc *p;
                    267:        register struct ioctl_args *uap;
                    268:        register_t *retval;
                    269: {
                    270:        register struct file *fp;
                    271:        register u_long com;
                    272:        register int error;
                    273:        register u_int size;
                    274:        caddr_t data, memp;
                    275:        int tmp;
                    276: #define STK_PARAMS     128
                    277:        char stkbuf[STK_PARAMS];
                    278: 
                    279:        if (error = fdgetf(p, uap->fd, &fp))
                    280:                return (error);
                    281: 
                    282:        if ((fp->f_flag & (FREAD | FWRITE)) == 0)
                    283:                return (EBADF);
                    284:                
                    285:        /*### LD 6/11/97 Hack Alert: this is to get AppleTalk to work
                    286:         * while implementing an ATioctl system call
                    287:         */
                    288: #if NETAT
                    289:        {
                    290:                extern int appletalk_inited;
                    291: 
                    292:                if (appletalk_inited && ((uap->com & 0x0000FFFF) == 0xff99)) {
                    293: #ifdef APPLETALK_DEBUG
                    294:                        kprintf("ioctl: special AppleTalk \n");
                    295: #endif
                    296:                        error = (*fp->f_ops->fo_ioctl)(fp, uap->com, uap->data, p);
                    297:                        return(error);
                    298:                }
                    299:        }
                    300: 
                    301: #endif /* NETAT */
                    302: 
                    303: 
                    304:        switch (com = uap->com) {
                    305:        case FIONCLEX:
                    306:                *fdflags(p, uap->fd) &= ~UF_EXCLOSE;
                    307:                return (0);
                    308:        case FIOCLEX:
                    309:                *fdflags(p, uap->fd) |= UF_EXCLOSE;
                    310:                return (0);
                    311:        }
                    312: 
                    313:        /*
                    314:         * Interpret high order word to find amount of data to be
                    315:         * copied to/from the user's address space.
                    316:         */
                    317:        size = IOCPARM_LEN(com);
                    318:        if (size > IOCPARM_MAX)
                    319:                return (ENOTTY);
                    320:        memp = NULL;
                    321:        if (size > sizeof (stkbuf)) {
                    322:                if ((memp = (caddr_t)kalloc(size)) == 0)
                    323:                        return(ENOMEM);
                    324:                data = memp;
                    325:        } else
                    326:                data = stkbuf;
                    327:        if (com&IOC_IN) {
                    328:                if (size) {
                    329:                        error = copyin(uap->data, data, (u_int)size);
                    330:                        if (error) {
                    331:                                if (memp)
                    332:                                        kfree(memp, size);
                    333:                                return (error);
                    334:                        }
                    335:                } else
                    336:                        *(caddr_t *)data = uap->data;
                    337:        } else if ((com&IOC_OUT) && size)
                    338:                /*
                    339:                 * Zero the buffer so the user always
                    340:                 * gets back something deterministic.
                    341:                 */
                    342:                bzero(data, size);
                    343:        else if (com&IOC_VOID)
                    344:                *(caddr_t *)data = uap->data;
                    345: 
                    346:        switch (com) {
                    347: 
                    348:        case FIONBIO:
                    349:                if (tmp = *(int *)data)
                    350:                        fp->f_flag |= FNONBLOCK;
                    351:                else
                    352:                        fp->f_flag &= ~FNONBLOCK;
                    353:                error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
                    354:                break;
                    355: 
                    356:        case FIOASYNC:
                    357:                if (tmp = *(int *)data)
                    358:                        fp->f_flag |= FASYNC;
                    359:                else
                    360:                        fp->f_flag &= ~FASYNC;
                    361:                error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
                    362:                break;
                    363: 
                    364:        case FIOSETOWN:
                    365:                tmp = *(int *)data;
                    366:                if (fp->f_type == DTYPE_SOCKET) {
                    367:                        ((struct socket *)fp->f_data)->so_pgid = tmp;
                    368:                        error = 0;
                    369:                        break;
                    370:                }
                    371:                if (tmp <= 0) {
                    372:                        tmp = -tmp;
                    373:                } else {
                    374:                        struct proc *p1 = pfind(tmp);
                    375:                        if (p1 == 0) {
                    376:                                error = ESRCH;
                    377:                                break;
                    378:                        }
                    379:                        tmp = p1->p_pgrp->pg_id;
                    380:                }
                    381:                error = (*fp->f_ops->fo_ioctl)
                    382:                        (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
                    383:                break;
                    384: 
                    385:        case FIOGETOWN:
                    386:                if (fp->f_type == DTYPE_SOCKET) {
                    387:                        error = 0;
                    388:                        *(int *)data = ((struct socket *)fp->f_data)->so_pgid;
                    389:                        break;
                    390:                }
                    391:                error = (*fp->f_ops->fo_ioctl)(fp, TIOCGPGRP, data, p);
                    392:                *(int *)data = -*(int *)data;
                    393:                break;
                    394: 
                    395:        default:
                    396:                error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
                    397:                /*
                    398:                 * Copy any data to user, size was
                    399:                 * already set and checked above.
                    400:                 */
                    401:                if (error == 0 && (com&IOC_OUT) && size)
                    402:                        error = copyout(data, uap->data, (u_int)size);
                    403:                break;
                    404:        }
                    405:        if (memp)
                    406:                kfree(memp, size);
                    407:        return (error);
                    408: }
                    409: 
                    410: 
                    411: int    selwait, nselcoll;
                    412: 
                    413: /*
                    414:  * Select system call.
                    415:  */
                    416: struct select_args {
                    417:        u_int nd;
                    418:        fd_set *in;
                    419:        fd_set *ou;
                    420:        fd_set *ex;
                    421:        struct timeval *tv;
                    422: };
                    423: 
                    424: select(p, uap, retval)
                    425:        register struct proc *p;
                    426:        register struct select_args *uap;
                    427:        register_t *retval;
                    428: {
                    429:        fd_set ibits[3], obits[3];
                    430:        struct timeval atv;
                    431:        int s, ncoll, error = 0, timo;
                    432:        u_int ni;
                    433:        struct thread *th;
                    434:        struct uthread  *uth;
                    435: 
                    436:        th = current_thread();
                    437:        uth = th->_uthread;
                    438: 
                    439:        bzero((caddr_t)ibits, sizeof(ibits));
                    440:        bzero((caddr_t)obits, sizeof(obits));
                    441: 
                    442:        if (uap->nd > FD_SETSIZE)
                    443:                return (EINVAL);
                    444:        if (uap->nd > p->p_fd->fd_nfiles) {
                    445:                /* forgiving; slightly wrong */
                    446:                uap->nd = p->p_fd->fd_nfiles;
                    447:        }
                    448:        ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask);
                    449: 
                    450: #define        getbits(name, x) \
                    451:        if (uap->name && (error = copyin((caddr_t)uap->name, \
                    452:            (caddr_t)&ibits[x], ni))) \
                    453:                goto done;
                    454:        getbits(in, 0);
                    455:        getbits(ou, 1);
                    456:        getbits(ex, 2);
                    457: #undef getbits
                    458:        if (uap->tv) {
                    459:                error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
                    460:                        sizeof (atv));
                    461:                if (error)
                    462:                        goto done;
                    463:                if (itimerfix(&atv)) {
                    464:                        error = EINVAL;
                    465:                        goto done;
                    466:                }
                    467:                s = splhigh();
                    468:                timeradd(&atv, &time, &atv);
                    469:                timo = hzto(&atv);
                    470:                splx(s);
                    471:        } else
                    472:                timo = 0;
                    473: retry:
                    474:        ncoll = nselcoll;
                    475:        p->p_flag |= P_SELECT;
                    476:        error = selscan(p, ibits, obits, uap->nd, retval);
                    477:        if (error || *retval)
                    478:                goto done;
                    479:        s = splhigh();
                    480:        /* this should be timercmp(&time, &atv, >=) */
                    481:        if (uap->tv && (time.tv_sec > atv.tv_sec ||
                    482:            time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
                    483:                splx(s);
                    484:                goto done;
                    485:        }
                    486:        /*
                    487:         * To effect a poll, the timeout argument should be
                    488:         * non-nil, pointing to a zero-valued timeval structure.
                    489:         */
                    490:        if (uap->tv && (timo == 0)) {
                    491:                splx(s);
                    492:                goto done;
                    493:        }
                    494:        if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) {
                    495:                splx(s);
                    496:                goto retry;
                    497:        }
                    498:        p->p_flag &= ~P_SELECT;
                    499:        error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
                    500:        splx(s);
                    501:        if (error == 0)
                    502:                goto retry;
                    503: done:
                    504:        p->p_flag &= ~P_SELECT;
                    505:        /* select is not restarted after signals... */
                    506:        if (error == ERESTART)
                    507:                error = EINTR;
                    508:        if (error == EWOULDBLOCK)
                    509:                error = 0;
                    510: #define        putbits(name, x) \
                    511:        if (uap->name && (error2 = copyout((caddr_t)&obits[x], \
                    512:            (caddr_t)uap->name, ni))) \
                    513:                error = error2;
                    514:        if (error == 0) {
                    515:                int error2;
                    516: 
                    517:                putbits(in, 0);
                    518:                putbits(ou, 1);
                    519:                putbits(ex, 2);
                    520: #undef putbits
                    521:        }
                    522:        return (error);
                    523: }
                    524: 
                    525: selscan(p, ibits, obits, nfd, retval)
                    526:        struct proc *p;
                    527:        fd_set *ibits, *obits;
                    528:        int nfd;
                    529:        register_t *retval;
                    530: {
                    531:        register struct filedesc *fdp = p->p_fd;
                    532:        register int msk, i, j, fd;
                    533:        register fd_mask bits;
                    534:        struct file *fp;
                    535:        int n = 0;
                    536:        static int flag[3] = { FREAD, FWRITE, 0 };
                    537: 
                    538:        for (msk = 0; msk < 3; msk++) {
                    539:                for (i = 0; i < nfd; i += NFDBITS) {
                    540:                        bits = ibits[msk].fds_bits[i/NFDBITS];
                    541:                        while ((j = ffs(bits)) && (fd = i + --j) < nfd) {
                    542:                                bits &= ~(1 << j);
                    543:                                fp = fdp->fd_ofiles[fd];
                    544:                                if (fp == NULL || (fdp->fd_ofileflags[fd] &
                    545:                                                                UF_RESERVED))
                    546:                                        return (EBADF);
                    547:                                if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) {
                    548:                                        FD_SET(fd, &obits[msk]);
                    549:                                        n++;
                    550:                                }
                    551:                        }
                    552:                }
                    553:        }
                    554:        *retval = n;
                    555:        return (0);
                    556: }
                    557: 
                    558: /*ARGSUSED*/
                    559: seltrue(dev, flag, p)
                    560:        dev_t dev;
                    561:        int flag;
                    562:        struct proc *p;
                    563: {
                    564: 
                    565:        return (1);
                    566: }
                    567: 
                    568: /*
                    569:  * Record a select request.
                    570:  */
                    571: void
                    572: selrecord(selector, sip)
                    573:        struct proc *selector;
                    574:        struct selinfo *sip;
                    575: {
                    576:        int             oldpri = splhigh();
                    577:        thread_t        my_thread = current_thread();
                    578:        thread_t        selthread;
                    579: 
                    580:        selthread = sip->si_thread;
                    581:        
                    582:        if (selthread == my_thread) {
                    583:                splx(oldpri);
                    584:                return;
                    585:        }
                    586:        
                    587:        if (selthread && selthread->active &&
                    588:            selthread->wait_event == (caddr_t)&selwait) {
                    589:                        sip->si_flags |= SI_COLL;
                    590:                        splx(oldpri);
                    591:        }
                    592:        else {
                    593:                        sip->si_thread = my_thread;
                    594:                        splx(oldpri);
                    595:                        thread_deallocate(selthread);
                    596:                        thread_reference(sip->si_thread);
                    597:        }
                    598: 
                    599:        return;
                    600: }
                    601: 
                    602: void
                    603: selwakeup(sip)
                    604:        register struct selinfo *sip;
                    605: {
                    606:        register thread_t       the_thread = (thread_t)sip->si_thread;
                    607:        int oldpri;
                    608:        
                    609:        if (the_thread == 0)
                    610:                return;
                    611: 
                    612:        if (sip->si_flags & SI_COLL) {
                    613:                nselcoll++;
                    614:                sip->si_flags &= ~SI_COLL;
                    615:                wakeup((caddr_t)&selwait);
                    616:        }
                    617:        
                    618:        oldpri = splhigh();
                    619: 
                    620:        if (the_thread->active) {
                    621:                /* protect p_flag minimally at splsched() */
                    622:                if (the_thread->wait_event == &selwait)
                    623:                        clear_wait(the_thread, THREAD_AWAKENED, TRUE);
                    624:                if (the_thread->task->proc)
                    625:                        the_thread->task->proc->p_flag &= ~P_SELECT;
                    626:        }
                    627:        
                    628:        thread_deallocate_interrupt(the_thread);
                    629:        
                    630:        sip->si_thread = 0;
                    631:        
                    632:        splx(oldpri);
                    633:        
                    634: }
                    635: 
                    636: void selthreadclear(sip)
                    637:        register struct selinfo *sip;
                    638: {
                    639: 
                    640:        if (sip->si_thread)
                    641:                        thread_deallocate_interrupt(sip->si_thread);
                    642: 
                    643: }
                    644: 
                    645: 
                    646: /*
                    647:  * called upon socket close. deque and free all events for
                    648:  * the socket
                    649:  */
                    650: evsofree(struct socket *sp)
                    651: {
                    652:   struct eventqelt *eqp, *next;
                    653: 
                    654:   if (sp == NULL) return;
                    655: 
                    656:   for (eqp = sp->so_evlist.tqh_first; eqp != NULL; eqp = next) {
                    657:     next = eqp->ee_slist.tqe_next;
                    658:     evprocdeque(eqp->ee_proc, eqp); // remove from proc q if there
                    659:     TAILQ_REMOVE(&sp->so_evlist, eqp, ee_slist); // remove from socket q
                    660:     FREE(eqp, M_TEMP);
                    661:   }
                    662: }
                    663: 
                    664: 
                    665: #define DBG_EVENT 0x10
                    666: 
                    667: #define DBG_POST 0x10
                    668: #define DBG_WATCH 0x11
                    669: #define DBG_WAIT 0x12
                    670: #define DBG_MOD 0x13
                    671: #define DBG_EWAKEUP 0x14
                    672: 
                    673: #define DBG_MISC_POST MISCDBG_CODE(DBG_EVENT,DBG_POST)
                    674: #define DBG_MISC_WATCH MISCDBG_CODE(DBG_EVENT,DBG_WATCH)
                    675: #define DBG_MISC_WAIT MISCDBG_CODE(DBG_EVENT,DBG_WAIT)
                    676: #define DBG_MISC_MOD MISCDBG_CODE(DBG_EVENT,DBG_MOD)
                    677: #define DBG_MISC_EWAKEUP MISCDBG_CODE(DBG_EVENT,DBG_EWAKEUP)
                    678: 
                    679: 
                    680: 
                    681: /*
                    682:  * enque this event if it's not already queued. wakeup
                    683:    the proc if we do queue this event to it.
                    684:  */
                    685: evprocenque(struct eventqelt *eqp)
                    686: {
                    687:   struct proc *p;
                    688: 
                    689:   assert(eqp);
                    690:   if (eqp->ee_flags & EV_QUEUED) {
                    691:     return;
                    692:   }
                    693:   eqp->ee_flags |= EV_QUEUED;
                    694:   eqp->ee_eventmask = 0;  // disarm
                    695:   p = eqp->ee_proc;
                    696:   TAILQ_INSERT_TAIL(&p->p_evlist, eqp, ee_plist);
                    697:   KERNEL_DEBUG(DBG_MISC_EWAKEUP,0,0,0,eqp,0);
                    698:   wakeup(&p->p_evlist);
                    699: }
                    700: 
                    701: /*
                    702:  * given either a sockbuf or a socket run down the
                    703:  * event list and queue ready events found
                    704:  */
                    705: postevent(struct socket *sp, struct sockbuf *sb, int event)
                    706: {
                    707:   int mask;
                    708:   struct eventqelt *evq;
                    709: 
                    710:   if (sb) sp = sb->sb_so;
                    711:   if (!sp || sp->so_evlist.tqh_first == NULL) return;
                    712: 
                    713:   KERNEL_DEBUG(DBG_MISC_POST|DBG_FUNC_START, 0,0,0,0,0);
                    714: 
                    715:   for (evq = sp->so_evlist.tqh_first;
                    716:        evq != NULL; evq = evq->ee_slist.tqe_next) {
                    717: 
                    718:     mask = 0;
                    719: 
                    720:     /* ready for reading:
                    721:        - byte cnt >= receive low water mark
                    722:        - read-half of conn closed
                    723:        - conn pending for listening sock
                    724:        - socket error pending
                    725: 
                    726:        ready for writing
                    727:        - byte cnt avail >= send low water mark
                    728:        - write half of conn closed
                    729:        - socket error pending
                    730:        - non-blocking conn completed successfully
                    731: 
                    732:        exception pending
                    733:        - out of band data
                    734:        - sock at out of band mark
                    735: 
                    736:     */
                    737:     switch (event & EV_DMASK) {
                    738: 
                    739:     case EV_RWBYTES:
                    740:     case EV_OOB:
                    741:       if (event & EV_OOB) {
                    742:       if ((evq->ee_eventmask & EV_EX)) {
                    743:        if (sp->so_oobmark || ((sp->so_state & SS_RCVATMARK))) {
                    744:          mask |= EV_EX|EV_OOB;
                    745:        }
                    746:       }
                    747:       }
                    748:       if (event & EV_RWBYTES) {
                    749:       if ((evq->ee_eventmask & EV_RE) && soreadable(sp)) {
                    750:        mask |= EV_RE;
                    751:        evq->ee_req.er_rcnt = sp->so_rcv.sb_cc;
                    752:       }
                    753: 
                    754:       if ((evq->ee_eventmask & EV_WR) && sowriteable(sp)) {
                    755:        mask |= EV_WR;
                    756:        evq->ee_req.er_wcnt = sbspace(&sp->so_snd);
                    757:       }
                    758:       }
                    759:     break;
                    760: 
                    761:     case EV_RCONN:
                    762:       if ((evq->ee_eventmask & EV_RE)) {
                    763:        evq->ee_req.er_rcnt = sp->so_qlen + 1;  // incl this one
                    764:        mask |= EV_RE|EV_RCONN;
                    765:       }
                    766:       break;
                    767: 
                    768:     case EV_WCONN:
                    769:       if ((evq->ee_eventmask & EV_WR)) {
                    770:        mask |= EV_WR|EV_WCONN;
                    771:       }
                    772:       break;
                    773: 
                    774:     case EV_RCLOSED:
                    775:       if ((evq->ee_eventmask & EV_RE)) {
                    776:        mask |= EV_RE|EV_RCLOSED;
                    777:        break;
                    778:       }
                    779: 
                    780:     case EV_WCLOSED:
                    781:       if ((evq->ee_eventmask & EV_WR)) {
                    782:        mask |= EV_WR|EV_WCLOSED;
                    783:        break;
                    784:       }
                    785: 
                    786:     case EV_FIN:
                    787:       if (evq->ee_eventmask & EV_EX) {
                    788:        mask |= EV_EX|EV_FIN;
                    789:        break;
                    790:       }
                    791: 
                    792:     case EV_RESET:
                    793:       if (evq->ee_eventmask & EV_EX) {
                    794:        mask |= EV_EX|EV_RESET;
                    795:        break;
                    796:       }
                    797: 
                    798:     default:
                    799:       return;
                    800:     } /* switch */
                    801: 
                    802:     if (mask) {
                    803:       evq->ee_req.er_eventbits |= mask;
                    804:       evprocenque(evq);
                    805:     }
                    806:   }
                    807:   KERNEL_DEBUG(DBG_MISC_POST|DBG_FUNC_END, 0,0,0,0,0);
                    808: }
                    809: 
                    810: /*
                    811:  * remove and return the first event (eqp=NULL) or a specific
                    812:  * event, or return NULL if no events found
                    813:  */
                    814: struct eventqelt *
                    815: evprocdeque(struct proc *p, struct eventqelt *eqp)
                    816: {
                    817: 
                    818:   
                    819:   if (eqp && ((eqp->ee_flags & EV_QUEUED) == NULL))
                    820:     return(NULL);
                    821:   if (p->p_evlist.tqh_first == NULL)
                    822:     return(NULL);
                    823:   if (eqp == NULL) {  // remove first
                    824:     eqp = p->p_evlist.tqh_first;
                    825:   }
                    826:   TAILQ_REMOVE(&p->p_evlist, eqp, ee_plist);
                    827:   eqp->ee_flags &= ~EV_QUEUED;
                    828:   return(eqp);
                    829: }
                    830: 
                    831: struct evwatch_args {
                    832:   struct eventreq  *u_req;
                    833:   int               u_eventmask;
                    834: };
                    835: 
                    836: 
                    837: /*
                    838:  * watchevent system call. user passes us an event to watch
                    839:  * for. we malloc an event object, initialize it, and queue
                    840:  * it to the open socket. when the event occurs, postevent()
                    841:  * will enque it back to our proc where we can retrieve it
                    842:  * via waitevent().
                    843:  *
                    844:  * should this prevent duplicate events on same socket?
                    845:  */
                    846: int
                    847: watchevent(p, uap, retval)
                    848:      struct proc *p;
                    849:      struct evwatch_args *uap;
                    850:      register_t *retval;
                    851: {
                    852:   struct eventqelt *eqp = (struct eventqelt *)0;
                    853:   struct eventqelt *np;
                    854:   struct eventreq *erp;
                    855:   struct file *fp;
                    856:   struct socket *sp;
                    857:   int error;
                    858: 
                    859:   // get a qelt and fill with users req
                    860:   MALLOC(eqp, struct eventqelt *, sizeof(struct eventqelt), M_TEMP, M_WAITOK);
                    861:   if (!eqp) panic("can't MALLOC eqp");
                    862:   erp = &eqp->ee_req;
                    863:   // get users request pkt
                    864:   if (error = copyin((caddr_t)uap->u_req, (caddr_t)erp,
                    865:                     sizeof(struct eventreq))) {
                    866:     FREE(eqp, M_TEMP);
                    867:     KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
                    868:     return(error);
                    869:   }
                    870:   KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_START, 0,
                    871:               erp->er_handle,uap->u_eventmask,eqp,0);
                    872:   // validate, freeing qelt if errors
                    873:   error = 0;
                    874:   if (erp->er_type != EV_FD) {
                    875:     error = EINVAL;
                    876:   } else  if (erp->er_handle < 0) {
                    877:     error = EBADF;
                    878:   } else  if (erp->er_handle > p->p_fd->fd_nfiles) {
                    879:     error = EBADF;
                    880:   } else if ((fp = *fdfile(p, erp->er_handle)) == NULL) {
                    881:     error = EBADF;
                    882:   } else if (fp->f_type != DTYPE_SOCKET) {
                    883:     error = EINVAL;
                    884:   }
                    885:   if (error) {
                    886:     FREE(eqp,M_TEMP);
                    887:     KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
                    888:     return(error);
                    889:   }
                    890: 
                    891:   erp->er_rcnt = erp->er_wcnt = erp->er_eventbits = 0;
                    892:   eqp->ee_proc = p;
                    893:   eqp->ee_eventmask = uap->u_eventmask & EV_MASK;
                    894:   eqp->ee_flags = 0;
                    895: 
                    896:   sp = (struct socket *)fp->f_data;
                    897:   assert(sp != NULL);
                    898: 
                    899:   // only allow one watch per file per proc
                    900:   for (np = sp->so_evlist.tqh_first; np != NULL; np = np->ee_slist.tqe_next) {
                    901:     if (np->ee_proc == p) {
                    902:       FREE(eqp,M_TEMP);
                    903:       KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
                    904:       return(EINVAL);
                    905:     }
                    906:   }
                    907: 
                    908:   TAILQ_INSERT_TAIL(&sp->so_evlist, eqp, ee_slist);
                    909:   postevent(sp, 0, EV_RWBYTES); // catch existing events
                    910:   KERNEL_DEBUG(DBG_MISC_WATCH|DBG_FUNC_END, 0,0,0,0,0);
                    911:   return(0);
                    912: }
                    913: 
                    914: struct evwait_args {
                    915:   struct eventreq *u_req;
                    916:   struct timeval *tv;
                    917: };
                    918: 
                    919: /*
                    920:  * waitevent system call.
                    921:  * grabs the next waiting event for this proc and returns
                    922:  * it. if no events, user can request to sleep with timeout
                    923:  * or poll mode (tv=NULL);
                    924:  */
                    925: int
                    926: waitevent(p, uap, retval)
                    927:      struct proc *p;
                    928:      struct evwait_args *uap;
                    929:      register_t *retval;
                    930: {
                    931:   int error = 0;
                    932:   struct eventqelt *eqp;
                    933:   int timo;
                    934:   struct timeval atv;
                    935:   int s;
                    936: 
                    937:        if (uap->tv) {
                    938:                error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
                    939:                        sizeof (atv));
                    940:                if (error)
                    941:                        return(error);
                    942:                if (itimerfix(&atv)) {
                    943:                        error = EINVAL;
                    944:                        return(error);
                    945:                }
                    946:                s = splhigh();
                    947:                timeradd(&atv, &time, &atv);
                    948:                timo = hzto(&atv);
                    949:                splx(s);
                    950:        } else
                    951:                timo = 0;
                    952: 
                    953:   KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_START, 0,0,0,0,0);
                    954: 
                    955: retry:
                    956:   s = splhigh();
                    957:   if ((eqp = evprocdeque(p,NULL)) != NULL) {
                    958:     splx(s);
                    959:     error = copyout((caddr_t)&eqp->ee_req, (caddr_t)uap->u_req,
                    960:                    sizeof(struct eventreq));
                    961:     KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_END, 0,
                    962:                 eqp->ee_req.er_handle,eqp->ee_req.er_eventbits,eqp,0);
                    963:     return(error);
                    964:   } else {
                    965:     if (uap->tv && (timo == 0)) {
                    966:         splx(s);
                    967:         *retval = 1;  // poll failed
                    968:        return(error);
                    969:     }
                    970: 
                    971:     KERNEL_DEBUG(DBG_MISC_WAIT, 1,0,0,0,0);
                    972:     error = tsleep(&p->p_evlist, PSOCK | PCATCH, "waitevent", timo);
                    973:     KERNEL_DEBUG(DBG_MISC_WAIT, 0,0,2,p->p_evlist.tqh_first,0);
                    974:     splx(s);
                    975:     if (error == 0)
                    976:       goto retry;
                    977:     if (error == ERESTART)
                    978:       error = EINTR;
                    979:     if (error == EWOULDBLOCK) {
                    980:       *retval = 1;
                    981:       error = 0;
                    982:     }
                    983:   }
                    984:   KERNEL_DEBUG(DBG_MISC_WAIT|DBG_FUNC_END, 0,0,0,0,0);
                    985:   return(error);
                    986: }
                    987: 
                    988: struct modwatch_args {
                    989:   struct eventreq *u_req;
                    990:   int               u_eventmask;
                    991: };
                    992: 
                    993: /*
                    994:  * modwatch system call. user passes in event to modify.
                    995:  * if we find it we reset the event bits and que/deque event
                    996:  * it needed.
                    997:  */
                    998: int
                    999: modwatch(p, uap, retval)
                   1000:      struct proc *p;
                   1001:      struct modwatch_args *uap;
                   1002:      register_t *retval;
                   1003: {
                   1004:   struct eventreq er;
                   1005:   struct eventreq *erp = &er;
                   1006:   struct eventqelt *evq;
                   1007:   int error;
                   1008:   struct file *fp;
                   1009:   struct socket *sp;
                   1010:   int flag;
                   1011: 
                   1012: 
                   1013:   // get users request pkt
                   1014:   if (error = copyin((caddr_t)uap->u_req, (caddr_t)erp,
                   1015:                     sizeof(struct eventreq))) return(error);
                   1016: 
                   1017:   if (erp->er_type != EV_FD) return(EINVAL);
                   1018:   if (erp->er_handle < 0) return(EBADF);
                   1019:   if (erp->er_handle > p->p_fd->fd_nfiles) return(EBADF);
                   1020:   if ((fp = *fdfile(p, erp->er_handle)) == NULL)
                   1021:     return(EBADF);
                   1022:   if (fp->f_type != DTYPE_SOCKET) return(EINVAL); // for now must be sock
                   1023:   sp = (struct socket *)fp->f_data;
                   1024:   assert(sp != NULL);
                   1025: 
                   1026:   // locate event if possible
                   1027:   for (evq = sp->so_evlist.tqh_first;
                   1028:        evq != NULL; evq = evq->ee_slist.tqe_next) {
                   1029:     if (evq->ee_proc == p) break;
                   1030:   }
                   1031:   if (evq == NULL) {
                   1032:     return(EINVAL);
                   1033:   }
                   1034: 
                   1035: 
                   1036:     if (uap->u_eventmask == EV_RM) {
                   1037:     evprocdeque(p, evq);
                   1038:     TAILQ_REMOVE(&sp->so_evlist, evq, ee_slist);
                   1039:     FREE(evq, M_TEMP);
                   1040:     return(0);
                   1041:     }
                   1042: 
                   1043:   switch (uap->u_eventmask & EV_MASK) {
                   1044:  
                   1045:   case 0:
                   1046:     flag = 0;
                   1047:     break;
                   1048: 
                   1049:   case EV_RE:
                   1050:   case EV_WR:
                   1051:   case EV_RE|EV_WR:
                   1052:     flag = EV_RWBYTES;
                   1053:     break;
                   1054: 
                   1055:   case EV_EX:
                   1056:     flag = EV_OOB;
                   1057:     break;
                   1058: 
                   1059:   case EV_EX|EV_RE:
                   1060:   case EV_EX|EV_WR:
                   1061:   case EV_EX|EV_RE|EV_WR:
                   1062:     flag = EV_OOB|EV_RWBYTES;
                   1063:     break;
                   1064: 
                   1065:   default:
                   1066:     return(EINVAL);
                   1067:   }
                   1068: 
                   1069:    evq->ee_eventmask = uap->u_eventmask & EV_MASK;
                   1070:    evprocdeque(p, evq);
                   1071:    evq->ee_req.er_eventbits = 0;
                   1072:    postevent(sp, 0, flag);
                   1073:    return(0);
                   1074: }
                   1075: 
                   1076: 
                   1077: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.