[BACK]Return to sys_pipe.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/sys_pipe.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: sys_pipe.c,v 1.52 2007/08/07 11:30:53 millert Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 1996 John S. Dyson
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice immediately at the beginning of the file, without modification,
                     12:  *    this list of conditions, and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Absolutely no warranty of function or purpose is made by the author
                     17:  *    John S. Dyson.
                     18:  * 4. Modifications may be freely made to this file if the above conditions
                     19:  *    are met.
                     20:  */
                     21:
                     22: /*
                     23:  * This file contains a high-performance replacement for the socket-based
                     24:  * pipes scheme originally used in FreeBSD/4.4Lite.  It does not support
                     25:  * all features of sockets, but does do everything that pipes normally
                     26:  * do.
                     27:  */
                     28:
                     29: #include <sys/param.h>
                     30: #include <sys/systm.h>
                     31: #include <sys/proc.h>
                     32: #include <sys/file.h>
                     33: #include <sys/filedesc.h>
                     34: #include <sys/pool.h>
                     35: #include <sys/ioctl.h>
                     36: #include <sys/stat.h>
                     37: #include <sys/signalvar.h>
                     38: #include <sys/mount.h>
                     39: #include <sys/syscallargs.h>
                     40: #include <sys/event.h>
                     41: #include <sys/lock.h>
                     42: #include <sys/poll.h>
                     43:
                     44: #include <uvm/uvm_extern.h>
                     45:
                     46: #include <sys/pipe.h>
                     47:
                     48: /*
                     49:  * interfaces to the outside world
                     50:  */
                     51: int    pipe_read(struct file *, off_t *, struct uio *, struct ucred *);
                     52: int    pipe_write(struct file *, off_t *, struct uio *, struct ucred *);
                     53: int    pipe_close(struct file *, struct proc *);
                     54: int    pipe_poll(struct file *, int events, struct proc *);
                     55: int    pipe_kqfilter(struct file *fp, struct knote *kn);
                     56: int    pipe_ioctl(struct file *, u_long, caddr_t, struct proc *);
                     57: int    pipe_stat(struct file *fp, struct stat *ub, struct proc *p);
                     58:
                     59: static struct fileops pipeops = {
                     60:        pipe_read, pipe_write, pipe_ioctl, pipe_poll, pipe_kqfilter,
                     61:        pipe_stat, pipe_close
                     62: };
                     63:
                     64: void   filt_pipedetach(struct knote *kn);
                     65: int    filt_piperead(struct knote *kn, long hint);
                     66: int    filt_pipewrite(struct knote *kn, long hint);
                     67:
                     68: struct filterops pipe_rfiltops =
                     69:        { 1, NULL, filt_pipedetach, filt_piperead };
                     70: struct filterops pipe_wfiltops =
                     71:        { 1, NULL, filt_pipedetach, filt_pipewrite };
                     72:
                     73: /*
                     74:  * Default pipe buffer size(s), this can be kind-of large now because pipe
                     75:  * space is pageable.  The pipe code will try to maintain locality of
                     76:  * reference for performance reasons, so small amounts of outstanding I/O
                     77:  * will not wipe the cache.
                     78:  */
                     79: #define MINPIPESIZE (PIPE_SIZE/3)
                     80:
                     81: /*
                     82:  * Limit the number of "big" pipes
                     83:  */
                     84: #define LIMITBIGPIPES  32
                     85: int nbigpipe;
                     86: static int amountpipekva;
                     87:
                     88: struct pool pipe_pool;
                     89:
                     90: void   pipeclose(struct pipe *);
                     91: void   pipe_free_kmem(struct pipe *);
                     92: int    pipe_create(struct pipe *);
                     93: static __inline int pipelock(struct pipe *);
                     94: static __inline void pipeunlock(struct pipe *);
                     95: static __inline void pipeselwakeup(struct pipe *);
                     96: int    pipespace(struct pipe *, u_int);
                     97:
                     98: /*
                     99:  * The pipe system call for the DTYPE_PIPE type of pipes
                    100:  */
                    101:
                    102: /* ARGSUSED */
                    103: int
                    104: sys_opipe(struct proc *p, void *v, register_t *retval)
                    105: {
                    106:        struct filedesc *fdp = p->p_fd;
                    107:        struct file *rf, *wf;
                    108:        struct pipe *rpipe, *wpipe;
                    109:        int fd, error;
                    110:
                    111:        fdplock(fdp);
                    112:
                    113:        rpipe = pool_get(&pipe_pool, PR_WAITOK);
                    114:        error = pipe_create(rpipe);
                    115:        if (error != 0)
                    116:                goto free1;
                    117:        wpipe = pool_get(&pipe_pool, PR_WAITOK);
                    118:        error = pipe_create(wpipe);
                    119:        if (error != 0)
                    120:                goto free2;
                    121:
                    122:        error = falloc(p, &rf, &fd);
                    123:        if (error != 0)
                    124:                goto free2;
                    125:        rf->f_flag = FREAD | FWRITE;
                    126:        rf->f_type = DTYPE_PIPE;
                    127:        rf->f_data = rpipe;
                    128:        rf->f_ops = &pipeops;
                    129:        retval[0] = fd;
                    130:
                    131:        error = falloc(p, &wf, &fd);
                    132:        if (error != 0)
                    133:                goto free3;
                    134:        wf->f_flag = FREAD | FWRITE;
                    135:        wf->f_type = DTYPE_PIPE;
                    136:        wf->f_data = wpipe;
                    137:        wf->f_ops = &pipeops;
                    138:        retval[1] = fd;
                    139:
                    140:        rpipe->pipe_peer = wpipe;
                    141:        wpipe->pipe_peer = rpipe;
                    142:
                    143:        FILE_SET_MATURE(rf);
                    144:        FILE_SET_MATURE(wf);
                    145:
                    146:        fdpunlock(fdp);
                    147:        return (0);
                    148:
                    149: free3:
                    150:        fdremove(fdp, retval[0]);
                    151:        closef(rf, p);
                    152:        rpipe = NULL;
                    153: free2:
                    154:        (void)pipeclose(wpipe);
                    155: free1:
                    156:        if (rpipe != NULL)
                    157:                (void)pipeclose(rpipe);
                    158:        fdpunlock(fdp);
                    159:        return (error);
                    160: }
                    161:
                    162: /*
                    163:  * Allocate kva for pipe circular buffer, the space is pageable.
                    164:  * This routine will 'realloc' the size of a pipe safely, if it fails
                    165:  * it will retain the old buffer.
                    166:  * If it fails it will return ENOMEM.
                    167:  */
                    168: int
                    169: pipespace(struct pipe *cpipe, u_int size)
                    170: {
                    171:        caddr_t buffer;
                    172:
                    173:        buffer = (caddr_t)uvm_km_valloc(kernel_map, size);
                    174:        if (buffer == NULL) {
                    175:                return (ENOMEM);
                    176:        }
                    177:
                    178:        /* free old resources if we are resizing */
                    179:        pipe_free_kmem(cpipe);
                    180:        cpipe->pipe_buffer.buffer = buffer;
                    181:        cpipe->pipe_buffer.size = size;
                    182:        cpipe->pipe_buffer.in = 0;
                    183:        cpipe->pipe_buffer.out = 0;
                    184:        cpipe->pipe_buffer.cnt = 0;
                    185:
                    186:        amountpipekva += cpipe->pipe_buffer.size;
                    187:
                    188:        return (0);
                    189: }
                    190:
                    191: /*
                    192:  * initialize and allocate VM and memory for pipe
                    193:  */
                    194: int
                    195: pipe_create(struct pipe *cpipe)
                    196: {
                    197:        int error;
                    198:
                    199:        /* so pipe_free_kmem() doesn't follow junk pointer */
                    200:        cpipe->pipe_buffer.buffer = NULL;
                    201:        /*
                    202:         * protect so pipeclose() doesn't follow a junk pointer
                    203:         * if pipespace() fails.
                    204:         */
                    205:        bzero(&cpipe->pipe_sel, sizeof cpipe->pipe_sel);
                    206:        cpipe->pipe_state = 0;
                    207:        cpipe->pipe_peer = NULL;
                    208:        cpipe->pipe_busy = 0;
                    209:
                    210:        error = pipespace(cpipe, PIPE_SIZE);
                    211:        if (error != 0)
                    212:                return (error);
                    213:
                    214:        nanotime(&cpipe->pipe_ctime);
                    215:        cpipe->pipe_atime = cpipe->pipe_ctime;
                    216:        cpipe->pipe_mtime = cpipe->pipe_ctime;
                    217:        cpipe->pipe_pgid = NO_PID;
                    218:
                    219:        return (0);
                    220: }
                    221:
                    222:
                    223: /*
                    224:  * lock a pipe for I/O, blocking other access
                    225:  */
                    226: static __inline int
                    227: pipelock(struct pipe *cpipe)
                    228: {
                    229:        int error;
                    230:        while (cpipe->pipe_state & PIPE_LOCK) {
                    231:                cpipe->pipe_state |= PIPE_LWANT;
                    232:                if ((error = tsleep(cpipe, PRIBIO|PCATCH, "pipelk", 0)))
                    233:                        return error;
                    234:        }
                    235:        cpipe->pipe_state |= PIPE_LOCK;
                    236:        return 0;
                    237: }
                    238:
                    239: /*
                    240:  * unlock a pipe I/O lock
                    241:  */
                    242: static __inline void
                    243: pipeunlock(struct pipe *cpipe)
                    244: {
                    245:        cpipe->pipe_state &= ~PIPE_LOCK;
                    246:        if (cpipe->pipe_state & PIPE_LWANT) {
                    247:                cpipe->pipe_state &= ~PIPE_LWANT;
                    248:                wakeup(cpipe);
                    249:        }
                    250: }
                    251:
                    252: static __inline void
                    253: pipeselwakeup(struct pipe *cpipe)
                    254: {
                    255:        if (cpipe->pipe_state & PIPE_SEL) {
                    256:                cpipe->pipe_state &= ~PIPE_SEL;
                    257:                selwakeup(&cpipe->pipe_sel);
                    258:        }
                    259:        if ((cpipe->pipe_state & PIPE_ASYNC) && cpipe->pipe_pgid != NO_PID)
                    260:                gsignal(cpipe->pipe_pgid, SIGIO);
                    261:        KNOTE(&cpipe->pipe_sel.si_note, 0);
                    262: }
                    263:
                    264: /* ARGSUSED */
                    265: int
                    266: pipe_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
                    267: {
                    268:        struct pipe *rpipe = (struct pipe *) fp->f_data;
                    269:        int error;
                    270:        int nread = 0;
                    271:        int size;
                    272:
                    273:        error = pipelock(rpipe);
                    274:        if (error)
                    275:                return (error);
                    276:
                    277:        ++rpipe->pipe_busy;
                    278:
                    279:        while (uio->uio_resid) {
                    280:                /*
                    281:                 * normal pipe buffer receive
                    282:                 */
                    283:                if (rpipe->pipe_buffer.cnt > 0) {
                    284:                        size = rpipe->pipe_buffer.size - rpipe->pipe_buffer.out;
                    285:                        if (size > rpipe->pipe_buffer.cnt)
                    286:                                size = rpipe->pipe_buffer.cnt;
                    287:                        if (size > uio->uio_resid)
                    288:                                size = uio->uio_resid;
                    289:                        error = uiomove(&rpipe->pipe_buffer.buffer[rpipe->pipe_buffer.out],
                    290:                                        size, uio);
                    291:                        if (error) {
                    292:                                break;
                    293:                        }
                    294:                        rpipe->pipe_buffer.out += size;
                    295:                        if (rpipe->pipe_buffer.out >= rpipe->pipe_buffer.size)
                    296:                                rpipe->pipe_buffer.out = 0;
                    297:
                    298:                        rpipe->pipe_buffer.cnt -= size;
                    299:                        /*
                    300:                         * If there is no more to read in the pipe, reset
                    301:                         * its pointers to the beginning.  This improves
                    302:                         * cache hit stats.
                    303:                         */
                    304:                        if (rpipe->pipe_buffer.cnt == 0) {
                    305:                                rpipe->pipe_buffer.in = 0;
                    306:                                rpipe->pipe_buffer.out = 0;
                    307:                        }
                    308:                        nread += size;
                    309:                } else {
                    310:                        /*
                    311:                         * detect EOF condition
                    312:                         * read returns 0 on EOF, no need to set error
                    313:                         */
                    314:                        if (rpipe->pipe_state & PIPE_EOF)
                    315:                                break;
                    316:
                    317:                        /*
                    318:                         * If the "write-side" has been blocked, wake it up now.
                    319:                         */
                    320:                        if (rpipe->pipe_state & PIPE_WANTW) {
                    321:                                rpipe->pipe_state &= ~PIPE_WANTW;
                    322:                                wakeup(rpipe);
                    323:                        }
                    324:
                    325:                        /*
                    326:                         * Break if some data was read.
                    327:                         */
                    328:                        if (nread > 0)
                    329:                                break;
                    330:
                    331:                        /*
                    332:                         * Unlock the pipe buffer for our remaining processing.
                    333:                         * We will either break out with an error or we will
                    334:                         * sleep and relock to loop.
                    335:                         */
                    336:                        pipeunlock(rpipe);
                    337:
                    338:                        /*
                    339:                         * Handle non-blocking mode operation or
                    340:                         * wait for more data.
                    341:                         */
                    342:                        if (fp->f_flag & FNONBLOCK) {
                    343:                                error = EAGAIN;
                    344:                        } else {
                    345:                                rpipe->pipe_state |= PIPE_WANTR;
                    346:                                if ((error = tsleep(rpipe, PRIBIO|PCATCH, "piperd", 0)) == 0)
                    347:                                        error = pipelock(rpipe);
                    348:                        }
                    349:                        if (error)
                    350:                                goto unlocked_error;
                    351:                }
                    352:        }
                    353:        pipeunlock(rpipe);
                    354:
                    355:        if (error == 0)
                    356:                nanotime(&rpipe->pipe_atime);
                    357: unlocked_error:
                    358:        --rpipe->pipe_busy;
                    359:
                    360:        /*
                    361:         * PIPE_WANT processing only makes sense if pipe_busy is 0.
                    362:         */
                    363:        if ((rpipe->pipe_busy == 0) && (rpipe->pipe_state & PIPE_WANT)) {
                    364:                rpipe->pipe_state &= ~(PIPE_WANT|PIPE_WANTW);
                    365:                wakeup(rpipe);
                    366:        } else if (rpipe->pipe_buffer.cnt < MINPIPESIZE) {
                    367:                /*
                    368:                 * Handle write blocking hysteresis.
                    369:                 */
                    370:                if (rpipe->pipe_state & PIPE_WANTW) {
                    371:                        rpipe->pipe_state &= ~PIPE_WANTW;
                    372:                        wakeup(rpipe);
                    373:                }
                    374:        }
                    375:
                    376:        if ((rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt) >= PIPE_BUF)
                    377:                pipeselwakeup(rpipe);
                    378:
                    379:        return (error);
                    380: }
                    381:
                    382: int
                    383: pipe_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
                    384: {
                    385:        int error = 0;
                    386:        int orig_resid;
                    387:
                    388:        struct pipe *wpipe, *rpipe;
                    389:
                    390:        rpipe = (struct pipe *) fp->f_data;
                    391:        wpipe = rpipe->pipe_peer;
                    392:
                    393:        /*
                    394:         * detect loss of pipe read side, issue SIGPIPE if lost.
                    395:         */
                    396:        if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
                    397:                return (EPIPE);
                    398:        }
                    399:        ++wpipe->pipe_busy;
                    400:
                    401:        /*
                    402:         * If it is advantageous to resize the pipe buffer, do
                    403:         * so.
                    404:         */
                    405:        if ((uio->uio_resid > PIPE_SIZE) &&
                    406:            (nbigpipe < LIMITBIGPIPES) &&
                    407:            (wpipe->pipe_buffer.size <= PIPE_SIZE) &&
                    408:            (wpipe->pipe_buffer.cnt == 0)) {
                    409:
                    410:                if ((error = pipelock(wpipe)) == 0) {
                    411:                        if (pipespace(wpipe, BIG_PIPE_SIZE) == 0)
                    412:                                nbigpipe++;
                    413:                        pipeunlock(wpipe);
                    414:                }
                    415:        }
                    416:
                    417:        /*
                    418:         * If an early error occured unbusy and return, waking up any pending
                    419:         * readers.
                    420:         */
                    421:        if (error) {
                    422:                --wpipe->pipe_busy;
                    423:                if ((wpipe->pipe_busy == 0) &&
                    424:                    (wpipe->pipe_state & PIPE_WANT)) {
                    425:                        wpipe->pipe_state &= ~(PIPE_WANT | PIPE_WANTR);
                    426:                        wakeup(wpipe);
                    427:                }
                    428:                return (error);
                    429:        }
                    430:
                    431:        orig_resid = uio->uio_resid;
                    432:
                    433:        while (uio->uio_resid) {
                    434:                int space;
                    435:
                    436: retrywrite:
                    437:                if (wpipe->pipe_state & PIPE_EOF) {
                    438:                        error = EPIPE;
                    439:                        break;
                    440:                }
                    441:
                    442:                space = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt;
                    443:
                    444:                /* Writes of size <= PIPE_BUF must be atomic. */
                    445:                if ((space < uio->uio_resid) && (orig_resid <= PIPE_BUF))
                    446:                        space = 0;
                    447:
                    448:                if (space > 0) {
                    449:                        if ((error = pipelock(wpipe)) == 0) {
                    450:                                int size;       /* Transfer size */
                    451:                                int segsize;    /* first segment to transfer */
                    452:
                    453:                                /*
                    454:                                 * If a process blocked in uiomove, our
                    455:                                 * value for space might be bad.
                    456:                                 *
                    457:                                 * XXX will we be ok if the reader has gone
                    458:                                 * away here?
                    459:                                 */
                    460:                                if (space > wpipe->pipe_buffer.size -
                    461:                                    wpipe->pipe_buffer.cnt) {
                    462:                                        pipeunlock(wpipe);
                    463:                                        goto retrywrite;
                    464:                                }
                    465:
                    466:                                /*
                    467:                                 * Transfer size is minimum of uio transfer
                    468:                                 * and free space in pipe buffer.
                    469:                                 */
                    470:                                if (space > uio->uio_resid)
                    471:                                        size = uio->uio_resid;
                    472:                                else
                    473:                                        size = space;
                    474:                                /*
                    475:                                 * First segment to transfer is minimum of
                    476:                                 * transfer size and contiguous space in
                    477:                                 * pipe buffer.  If first segment to transfer
                    478:                                 * is less than the transfer size, we've got
                    479:                                 * a wraparound in the buffer.
                    480:                                 */
                    481:                                segsize = wpipe->pipe_buffer.size -
                    482:                                        wpipe->pipe_buffer.in;
                    483:                                if (segsize > size)
                    484:                                        segsize = size;
                    485:
                    486:                                /* Transfer first segment */
                    487:
                    488:                                error = uiomove(&wpipe->pipe_buffer.buffer[wpipe->pipe_buffer.in],
                    489:                                                segsize, uio);
                    490:
                    491:                                if (error == 0 && segsize < size) {
                    492:                                        /*
                    493:                                         * Transfer remaining part now, to
                    494:                                         * support atomic writes.  Wraparound
                    495:                                         * happened.
                    496:                                         */
                    497: #ifdef DIAGNOSTIC
                    498:                                        if (wpipe->pipe_buffer.in + segsize !=
                    499:                                            wpipe->pipe_buffer.size)
                    500:                                                panic("Expected pipe buffer wraparound disappeared");
                    501: #endif
                    502:
                    503:                                        error = uiomove(&wpipe->pipe_buffer.buffer[0],
                    504:                                                        size - segsize, uio);
                    505:                                }
                    506:                                if (error == 0) {
                    507:                                        wpipe->pipe_buffer.in += size;
                    508:                                        if (wpipe->pipe_buffer.in >=
                    509:                                            wpipe->pipe_buffer.size) {
                    510: #ifdef DIAGNOSTIC
                    511:                                                if (wpipe->pipe_buffer.in != size - segsize + wpipe->pipe_buffer.size)
                    512:                                                        panic("Expected wraparound bad");
                    513: #endif
                    514:                                                wpipe->pipe_buffer.in = size - segsize;
                    515:                                        }
                    516:
                    517:                                        wpipe->pipe_buffer.cnt += size;
                    518: #ifdef DIAGNOSTIC
                    519:                                        if (wpipe->pipe_buffer.cnt > wpipe->pipe_buffer.size)
                    520:                                                panic("Pipe buffer overflow");
                    521: #endif
                    522:                                }
                    523:                                pipeunlock(wpipe);
                    524:                        }
                    525:                        if (error)
                    526:                                break;
                    527:                } else {
                    528:                        /*
                    529:                         * If the "read-side" has been blocked, wake it up now.
                    530:                         */
                    531:                        if (wpipe->pipe_state & PIPE_WANTR) {
                    532:                                wpipe->pipe_state &= ~PIPE_WANTR;
                    533:                                wakeup(wpipe);
                    534:                        }
                    535:
                    536:                        /*
                    537:                         * don't block on non-blocking I/O
                    538:                         */
                    539:                        if (fp->f_flag & FNONBLOCK) {
                    540:                                error = EAGAIN;
                    541:                                break;
                    542:                        }
                    543:
                    544:                        /*
                    545:                         * We have no more space and have something to offer,
                    546:                         * wake up select/poll.
                    547:                         */
                    548:                        pipeselwakeup(wpipe);
                    549:
                    550:                        wpipe->pipe_state |= PIPE_WANTW;
                    551:                        error = tsleep(wpipe, (PRIBIO + 1)|PCATCH,
                    552:                            "pipewr", 0);
                    553:                        if (error)
                    554:                                break;
                    555:                        /*
                    556:                         * If read side wants to go away, we just issue a
                    557:                         * signal to ourselves.
                    558:                         */
                    559:                        if (wpipe->pipe_state & PIPE_EOF) {
                    560:                                error = EPIPE;
                    561:                                break;
                    562:                        }
                    563:                }
                    564:        }
                    565:
                    566:        --wpipe->pipe_busy;
                    567:
                    568:        if ((wpipe->pipe_busy == 0) && (wpipe->pipe_state & PIPE_WANT)) {
                    569:                wpipe->pipe_state &= ~(PIPE_WANT | PIPE_WANTR);
                    570:                wakeup(wpipe);
                    571:        } else if (wpipe->pipe_buffer.cnt > 0) {
                    572:                /*
                    573:                 * If we have put any characters in the buffer, we wake up
                    574:                 * the reader.
                    575:                 */
                    576:                if (wpipe->pipe_state & PIPE_WANTR) {
                    577:                        wpipe->pipe_state &= ~PIPE_WANTR;
                    578:                        wakeup(wpipe);
                    579:                }
                    580:        }
                    581:
                    582:        /*
                    583:         * Don't return EPIPE if I/O was successful
                    584:         */
                    585:        if ((wpipe->pipe_buffer.cnt == 0) &&
                    586:            (uio->uio_resid == 0) &&
                    587:            (error == EPIPE)) {
                    588:                error = 0;
                    589:        }
                    590:
                    591:        if (error == 0)
                    592:                nanotime(&wpipe->pipe_mtime);
                    593:        /*
                    594:         * We have something to offer, wake up select/poll.
                    595:         */
                    596:        if (wpipe->pipe_buffer.cnt)
                    597:                pipeselwakeup(wpipe);
                    598:
                    599:        return (error);
                    600: }
                    601:
                    602: /*
                    603:  * we implement a very minimal set of ioctls for compatibility with sockets.
                    604:  */
                    605: int
                    606: pipe_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
                    607: {
                    608:        struct pipe *mpipe = (struct pipe *)fp->f_data;
                    609:
                    610:        switch (cmd) {
                    611:
                    612:        case FIONBIO:
                    613:                return (0);
                    614:
                    615:        case FIOASYNC:
                    616:                if (*(int *)data) {
                    617:                        mpipe->pipe_state |= PIPE_ASYNC;
                    618:                } else {
                    619:                        mpipe->pipe_state &= ~PIPE_ASYNC;
                    620:                }
                    621:                return (0);
                    622:
                    623:        case FIONREAD:
                    624:                *(int *)data = mpipe->pipe_buffer.cnt;
                    625:                return (0);
                    626:
                    627:        case SIOCSPGRP:
                    628:                mpipe->pipe_pgid = *(int *)data;
                    629:                return (0);
                    630:
                    631:        case SIOCGPGRP:
                    632:                *(int *)data = mpipe->pipe_pgid;
                    633:                return (0);
                    634:
                    635:        }
                    636:        return (ENOTTY);
                    637: }
                    638:
                    639: int
                    640: pipe_poll(struct file *fp, int events, struct proc *p)
                    641: {
                    642:        struct pipe *rpipe = (struct pipe *)fp->f_data;
                    643:        struct pipe *wpipe;
                    644:        int revents = 0;
                    645:
                    646:        wpipe = rpipe->pipe_peer;
                    647:        if (events & (POLLIN | POLLRDNORM)) {
                    648:                if ((rpipe->pipe_buffer.cnt > 0) ||
                    649:                    (rpipe->pipe_state & PIPE_EOF))
                    650:                        revents |= events & (POLLIN | POLLRDNORM);
                    651:        }
                    652:
                    653:        /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */
                    654:        if ((rpipe->pipe_state & PIPE_EOF) ||
                    655:            (wpipe == NULL) ||
                    656:            (wpipe->pipe_state & PIPE_EOF))
                    657:                revents |= POLLHUP;
                    658:        else if (events & (POLLOUT | POLLWRNORM)) {
                    659:                if ((wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF)
                    660:                        revents |= events & (POLLOUT | POLLWRNORM);
                    661:        }
                    662:
                    663:        if (revents == 0) {
                    664:                if (events & (POLLIN | POLLRDNORM)) {
                    665:                        selrecord(p, &rpipe->pipe_sel);
                    666:                        rpipe->pipe_state |= PIPE_SEL;
                    667:                }
                    668:                if (events & (POLLOUT | POLLWRNORM)) {
                    669:                        selrecord(p, &wpipe->pipe_sel);
                    670:                        wpipe->pipe_state |= PIPE_SEL;
                    671:                }
                    672:        }
                    673:        return (revents);
                    674: }
                    675:
                    676: int
                    677: pipe_stat(struct file *fp, struct stat *ub, struct proc *p)
                    678: {
                    679:        struct pipe *pipe = (struct pipe *)fp->f_data;
                    680:
                    681:        bzero(ub, sizeof(*ub));
                    682:        ub->st_mode = S_IFIFO;
                    683:        ub->st_blksize = pipe->pipe_buffer.size;
                    684:        ub->st_size = pipe->pipe_buffer.cnt;
                    685:        ub->st_blocks = (ub->st_size + ub->st_blksize - 1) / ub->st_blksize;
                    686:        ub->st_atimespec = pipe->pipe_atime;
                    687:        ub->st_mtimespec = pipe->pipe_mtime;
                    688:        ub->st_ctimespec = pipe->pipe_ctime;
                    689:        ub->st_uid = fp->f_cred->cr_uid;
                    690:        ub->st_gid = fp->f_cred->cr_gid;
                    691:        /*
                    692:         * Left as 0: st_dev, st_ino, st_nlink, st_rdev, st_flags, st_gen.
                    693:         * XXX (st_dev, st_ino) should be unique.
                    694:         */
                    695:        return (0);
                    696: }
                    697:
                    698: /* ARGSUSED */
                    699: int
                    700: pipe_close(struct file *fp, struct proc *p)
                    701: {
                    702:        struct pipe *cpipe = (struct pipe *)fp->f_data;
                    703:
                    704:        fp->f_ops = NULL;
                    705:        fp->f_data = NULL;
                    706:        pipeclose(cpipe);
                    707:        return (0);
                    708: }
                    709:
                    710: void
                    711: pipe_free_kmem(struct pipe *cpipe)
                    712: {
                    713:        if (cpipe->pipe_buffer.buffer != NULL) {
                    714:                if (cpipe->pipe_buffer.size > PIPE_SIZE)
                    715:                        --nbigpipe;
                    716:                amountpipekva -= cpipe->pipe_buffer.size;
                    717:                uvm_km_free(kernel_map, (vaddr_t)cpipe->pipe_buffer.buffer,
                    718:                    cpipe->pipe_buffer.size);
                    719:                cpipe->pipe_buffer.buffer = NULL;
                    720:        }
                    721: }
                    722:
                    723: /*
                    724:  * shutdown the pipe
                    725:  */
                    726: void
                    727: pipeclose(struct pipe *cpipe)
                    728: {
                    729:        struct pipe *ppipe;
                    730:        if (cpipe) {
                    731:
                    732:                pipeselwakeup(cpipe);
                    733:
                    734:                /*
                    735:                 * If the other side is blocked, wake it up saying that
                    736:                 * we want to close it down.
                    737:                 */
                    738:                cpipe->pipe_state |= PIPE_EOF;
                    739:                while (cpipe->pipe_busy) {
                    740:                        wakeup(cpipe);
                    741:                        cpipe->pipe_state |= PIPE_WANT;
                    742:                        tsleep(cpipe, PRIBIO, "pipecl", 0);
                    743:                }
                    744:
                    745:                /*
                    746:                 * Disconnect from peer
                    747:                 */
                    748:                if ((ppipe = cpipe->pipe_peer) != NULL) {
                    749:                        pipeselwakeup(ppipe);
                    750:
                    751:                        ppipe->pipe_state |= PIPE_EOF;
                    752:                        wakeup(ppipe);
                    753:                        KNOTE(&ppipe->pipe_sel.si_note, 0);
                    754:                        ppipe->pipe_peer = NULL;
                    755:                }
                    756:
                    757:                /*
                    758:                 * free resources
                    759:                 */
                    760:                pipe_free_kmem(cpipe);
                    761:                pool_put(&pipe_pool, cpipe);
                    762:        }
                    763: }
                    764:
                    765: int
                    766: pipe_kqfilter(struct file *fp, struct knote *kn)
                    767: {
                    768:        struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
                    769:        struct pipe *wpipe = rpipe->pipe_peer;
                    770:
                    771:        switch (kn->kn_filter) {
                    772:        case EVFILT_READ:
                    773:                kn->kn_fop = &pipe_rfiltops;
                    774:                SLIST_INSERT_HEAD(&rpipe->pipe_sel.si_note, kn, kn_selnext);
                    775:                break;
                    776:        case EVFILT_WRITE:
                    777:                if (wpipe == NULL)
                    778:                        /* other end of pipe has been closed */
                    779:                        return (1);
                    780:                kn->kn_fop = &pipe_wfiltops;
                    781:                SLIST_INSERT_HEAD(&wpipe->pipe_sel.si_note, kn, kn_selnext);
                    782:                break;
                    783:        default:
                    784:                return (1);
                    785:        }
                    786:
                    787:        return (0);
                    788: }
                    789:
                    790: void
                    791: filt_pipedetach(struct knote *kn)
                    792: {
                    793:        struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
                    794:        struct pipe *wpipe = rpipe->pipe_peer;
                    795:
                    796:        switch (kn->kn_filter) {
                    797:        case EVFILT_READ:
                    798:                SLIST_REMOVE(&rpipe->pipe_sel.si_note, kn, knote, kn_selnext);
                    799:                break;
                    800:        case EVFILT_WRITE:
                    801:                if (wpipe == NULL)
                    802:                        return;
                    803:                SLIST_REMOVE(&wpipe->pipe_sel.si_note, kn, knote, kn_selnext);
                    804:                break;
                    805:        }
                    806: }
                    807:
                    808: /*ARGSUSED*/
                    809: int
                    810: filt_piperead(struct knote *kn, long hint)
                    811: {
                    812:        struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
                    813:        struct pipe *wpipe = rpipe->pipe_peer;
                    814:
                    815:        kn->kn_data = rpipe->pipe_buffer.cnt;
                    816:
                    817:        if ((rpipe->pipe_state & PIPE_EOF) ||
                    818:            (wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
                    819:                kn->kn_flags |= EV_EOF;
                    820:                return (1);
                    821:        }
                    822:        return (kn->kn_data > 0);
                    823: }
                    824:
                    825: /*ARGSUSED*/
                    826: int
                    827: filt_pipewrite(struct knote *kn, long hint)
                    828: {
                    829:        struct pipe *rpipe = (struct pipe *)kn->kn_fp->f_data;
                    830:        struct pipe *wpipe = rpipe->pipe_peer;
                    831:
                    832:        if ((wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
                    833:                kn->kn_data = 0;
                    834:                kn->kn_flags |= EV_EOF;
                    835:                return (1);
                    836:        }
                    837:        kn->kn_data = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt;
                    838:
                    839:        return (kn->kn_data >= PIPE_BUF);
                    840: }
                    841:
                    842: void
                    843: pipe_init(void)
                    844: {
                    845:        pool_init(&pipe_pool, sizeof(struct pipe), 0, 0, 0, "pipepl",
                    846:            &pool_allocator_nointr);
                    847: }
                    848:

CVSweb