Annotation of coherent/b/kernel/coh.386/pipe.c, revision 1.1

1.1     ! root        1: /* $Header: /src386/kernel/coh.386/RCS/pipe.c,v 1.9 93/04/16 06:49:10 bin Exp Locker: bin $ */
        !             2: /* (lgl-
        !             3:  *     The information contained herein is a trade secret of Mark Williams
        !             4:  *     Company, and  is confidential information.  It is provided  under a
        !             5:  *     license agreement,  and may be  copied or disclosed  only under the
        !             6:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
        !             7:  *     material without the express written authorization of Mark Williams
        !             8:  *     Company or persuant to the license agreement is unlawful.
        !             9:  *
        !            10:  *     COHERENT Version 2.3.37
        !            11:  *     Copyright (c) 1982, 1983, 1984.
        !            12:  *     An unpublished work by Mark Williams Company, Chicago.
        !            13:  *     All rights reserved.
        !            14:  -lgl) */
        !            15: /*
        !            16:  * Coherent.
        !            17:  * Pipes.
        !            18:  *
        !            19:  * $Log:       pipe.c,v $
        !            20:  * Revision 1.9  93/04/16  06:49:10  bin
        !            21:  * Hal: kernel 76 update
        !            22:  * 
        !            23:  * Revision 1.7  93/04/14  10:06:40  root
        !            24:  * r75
        !            25:  * 
        !            26:  * Revision 1.2  92/01/06  11:59:52  hal
        !            27:  * Compile with cc.mwc.
        !            28:  * 
        !            29:  * Revision 1.1        88/03/24  16:14:07      src
        !            30:  * Initial revision
        !            31:  * 
        !            32:  * 86/11/19    Allan Cornish           /usr/src/sys/coh/pipe.c
        !            33:  * Added check for non-blocking read and write if (io_flag & IPNDLY) set.
        !            34:  * Eliminated use of i_a inode field since now included in inode macros.
        !            35:  */
        !            36: #include <sys/coherent.h>
        !            37: #include <errno.h>
        !            38: #include <sys/filsys.h>
        !            39: #include <sys/ino.h>
        !            40: #include <sys/inode.h>
        !            41: #include <sys/io.h>
        !            42: #include <sys/proc.h>
        !            43: #include <sys/sched.h>
        !            44: #include <signal.h>
        !            45: 
        !            46: /*
        !            47:  *  These are nothing more than random different values at this point!
        !            48:  *  Historically, these were bit's or'ed into ip->i_flag, no more!
        !            49:  */
        !            50: 
        !            51: #define        IFWFR   1                       /* Sleeping Waiting for a Reader */
        !            52: #define        IFWFW   2                       /* Sleeping Waiting for a Writer */
        !            53: 
        !            54: 
        !            55: /*
        !            56:  *  pmake(mode)  --  called from the upipe() system call in sys3.c
        !            57:  *
        !            58:  *  Creates and returns a locked pipe inode with the given mode on
        !            59:  *  the pipedev.
        !            60:  */
        !            61: 
        !            62: INODE *
        !            63: pmake(mode)
        !            64: {
        !            65:        register INODE *ip;
        !            66: 
        !            67:        if ((ip=ialloc(pipedev, IFPIPE|mode)) != NULL)
        !            68:                pclear(ip);
        !            69:        pdump("M", ip, mode);
        !            70:        return(ip);
        !            71: }
        !            72: 
        !            73: pclear(ip)
        !            74: register INODE *ip;
        !            75: {
        !            76:        ip->i_pnc =
        !            77:        ip->i_prx =
        !            78:        ip->i_pwx =
        !            79:        ip->i_par =
        !            80:        ip->i_paw =
        !            81:        ip->i_psr =
        !            82:        ip->i_psw = 0;
        !            83:        ip->i_iev.e_pnext =
        !            84:        ip->i_iev.e_dnext =
        !            85:        ip->i_iev.e_dlast =
        !            86:        ip->i_iev.e_procp =
        !            87:        ip->i_oev.e_pnext =
        !            88:        ip->i_oev.e_dnext =
        !            89:        ip->i_oev.e_dlast =
        !            90:        ip->i_oev.e_procp = NULL;
        !            91: }
        !            92: 
        !            93: /*
        !            94:  *  popen(ip, mode)  --  Opens a pipe inode, with the given mode.
        !            95:  *                      Note:  The inode is locked upon entry.
        !            96:  *
        !            97:  *  This routine follows the requirements concerning opening pipes.
        !            98:  *  Specifically, if opening readonly without O_NDELAY, then block
        !            99:  *  until we have a writer.  If opening readonly with O_NDELAY, then
        !           100:  *  return opened, no blocking.  If opening writeonly without O_NDELAY,
        !           101:  *  then block until we have a reader.  If opening writeonly with
        !           102:  *  O_NDELAY, then return an error, and set u.u_errno to ENXIO.
        !           103:  *  Beware of subtle race conditions!  Also notice, I followed hal's
        !           104:  *  style of no internal returns in a function.
        !           105:  *
        !           106:  *  Note: these pipe routines maintain the pipe counter variables:
        !           107:  *       ip->i_par:  Number of Awake readers
        !           108:  *       ip->i_paw:  Number of Awake writers
        !           109:  *       ip->i_psr:  Number of Sleeping readers
        !           110:  *       ip->i_psw:  Number of Sleeping writers
        !           111:  */
        !           112: 
        !           113: popen(ip, mode)
        !           114: register INODE *ip;
        !           115: {
        !           116:        pdump("OA", ip, mode);
        !           117:        switch ( mode&(IPR|IPW) ) {
        !           118:        case IPR:
        !           119:                ++ip->i_par;
        !           120:                while ( !ip->i_paw && !ip->i_psw ) {
        !           121:                        if ( mode & IPNDLY )
        !           122:                                break;
        !           123:                        else {
        !           124:                                if ( psleep(ip, IFWFW) < 0 ) {
        !           125:                                        --ip->i_par;
        !           126:                                        goto popen_done;
        !           127:                                }
        !           128:                                if ( ip->i_pnc != 0 )
        !           129:                                        break;
        !           130:                        }
        !           131:                }
        !           132:                pwake(ip, IFWFR);
        !           133:                break;
        !           134:        case IPW:
        !           135:                ++ip->i_paw;
        !           136:                if ( !ip->i_par && !ip->i_psr ) {
        !           137:                        if ( mode & IPNDLY ) {
        !           138:                                u.u_error = ENXIO;
        !           139:                                --ip->i_paw;
        !           140:                                goto popen_done;
        !           141:                        } else {
        !           142:                                if ( psleep(ip, IFWFR) < 0 ) {
        !           143:                                        --ip->i_paw;
        !           144:                                        goto popen_done;
        !           145:                                }
        !           146:                        }
        !           147:                }
        !           148:                pwake(ip, IFWFW);
        !           149:                break;
        !           150:        case IPR|IPW:
        !           151:                ++ip->i_par;
        !           152:                ++ip->i_paw;
        !           153:                pwake(ip, IFWFW);
        !           154:                pwake(ip, IFWFR);
        !           155:                break;
        !           156:        }
        !           157: 
        !           158: popen_done:
        !           159:        pdump("OZ", ip, mode);
        !           160:        return;
        !           161: }
        !           162: 
        !           163: 
        !           164: /*
        !           165:  *  pclose(ip, mode)  --  Opens a pipe inode, with the given mode.
        !           166:  *                       Note:  The inode is locked upon entry.
        !           167:  *
        !           168:  *  This routine closes the given INODE with the given mode.  We
        !           169:  *  must have the mode correct to maintain counters properly.
        !           170:  *  Good thing that mode cannot be changed by fcntl()!
        !           171:  */
        !           172: 
        !           173: pclose(ip, mode)
        !           174: register INODE *ip;
        !           175: {
        !           176:        pdump("CA", ip, mode);
        !           177:        pwake(ip, IFWFR);
        !           178:        pwake(ip, IFWFW);
        !           179:        if ( mode & IPR )
        !           180:                if ( --ip->i_par < 0 )
        !           181:                        panic("Out of sync IPR in pclose");
        !           182:        if ( mode & IPW )
        !           183:                if ( --ip->i_paw < 0 )
        !           184:                        panic("Out of sync IPW in pclose");
        !           185: 
        !           186:        if ( !ip->i_paw && !ip->i_psw && !ip->i_par && !ip->i_psr )
        !           187:                pclear(ip);
        !           188:        pdump("CZ", ip, mode);
        !           189: }
        !           190: 
        !           191: 
        !           192: /*
        !           193:  *  pread(ip, iop)  --  Reads from a pipe inode, accoring to the IO info.
        !           194:  *                     Note:  The inode is locked upon entry.
        !           195:  *
        !           196:  *  This routine follows the requirements concerning reading from pipes.
        !           197:  *  Specifically, if there is no data in the pipe, then the read will
        !           198:  *  block waiting for data, unless you have IONDLY set in which case
        !           199:  *  it will simply return zero.  Notice, the traditional value returned
        !           200:  *  from uread() is the number of characters actually read.  This is
        !           201:  *  nothing more that iop->io_ioc on entry minus iop->io_ioc on exit.
        !           202:  *  This routine also works with the ring buffer in the inode maintained
        !           203:  *  by the variables ip->i_pnc:  Number of Characters in pipe.
        !           204:  *                  ip->i_prx:  Offset in pipe to begin reading.
        !           205:  *                  ip->i_pwx:  Offset in pipe to begin writing.
        !           206:  *  Notice: we do not unlock the inode when we call fread(), this is to
        !           207:  *  guarantee that we read all that is available even if we go to sleep.
        !           208:  *  Subtle race condition?  I don't think so, since if we go to sleep
        !           209:  *  in fread(), it's wrt a resource unrelated to this particular INODE.
        !           210:  */
        !           211: 
        !           212: pread(ip, iop)
        !           213: register INODE *ip;
        !           214: register IO *iop;
        !           215: {
        !           216:        register unsigned n;
        !           217:        register unsigned ioc;
        !           218: 
        !           219:        pdump("R", ip, 0);
        !           220:        while (ip->i_pnc == 0) {
        !           221:                if ( iop->io_flag & IONDLY )
        !           222:                        goto pread_done;
        !           223:                if ( !ip->i_paw && !ip->i_psw )
        !           224:                        goto pread_done;
        !           225:                if ( psleep(ip, IFWFW) < 0 )
        !           226:                        goto pread_done;
        !           227:        }
        !           228: 
        !           229:        ioc = iop->io_ioc;
        !           230:        while ( !u.u_error && (ioc > 0) && (ip->i_pnc > 0) ) {
        !           231:                if ( (n = (PIPSIZE-ip->i_prx)) > ioc )
        !           232:                        n = ioc;
        !           233:                if ( n > ip->i_pnc )
        !           234:                        n = ip->i_pnc;
        !           235:                iop->io_ioc = n;
        !           236:                iop->io_seek = ip->i_prx;
        !           237:                fread(ip, iop);
        !           238:                n -= iop->io_ioc;
        !           239:                if ( (ip->i_prx+=n) == PIPSIZE )
        !           240:                        ip->i_prx = 0;
        !           241:                if ( (ip->i_pnc-=n) == 0 ) {
        !           242:                        ip->i_prx =
        !           243:                        ip->i_pwx = 0;
        !           244:                }
        !           245:                ioc -= n;
        !           246:        }
        !           247:        iop->io_ioc = ioc;
        !           248: 
        !           249:        if ( ip->i_pnc < PIPSIZE )
        !           250:                pwake(ip, IFWFR);
        !           251: 
        !           252: pread_done:
        !           253:        return;
        !           254: }
        !           255: 
        !           256: 
        !           257: /*
        !           258:  *  pwrite(ip, iop)  --  Writes to a pipe inode, accoring to the IO info.
        !           259:  *                      Note:  The inode is locked upon entry.
        !           260:  *
        !           261:  *  This routine follows the requirements concerning writing to pipes.
        !           262:  *  Specifically, if the pipe is full, then the write will block waiting
        !           263:  *  for data to be consumed, unless you have IONDLY set in which case
        !           264:  *  it will simply return zero.  Notice, the traditional value returned
        !           265:  *  from uwrite() is the number of characters actually written.  This is
        !           266:  *  nothing more that iop->io_ioc on entry minus iop->io_ioc on exit.
        !           267:  *  In other words, iop->io_ioc had better be zero on exit.  The possibility
        !           268:  *  does exist if the number of characters to be written is larger than
        !           269:  *  PIPSIZE, and thus we do not guarantee atomic writes, that while the
        !           270:  *  process is sleeping waiting for a reader to consume data, that the
        !           271:  *  process will be woken from sleeping by a SIGNAL, thus causing a partial
        !           272:  *  write.  The return value will be the actual number of character written.
        !           273:  *  This routine also works with the ring buffer in the inode maintained
        !           274:  *  by the variables ip->i_pnc:  Number of Characters in pipe.
        !           275:  *                  ip->i_prx:  Offset in pipe to begin reading.
        !           276:  *                  ip->i_pwx:  Offset in pipe to begin writing.
        !           277:  *  Notice: we do not unlock the inode when we call fwrite(), this is to
        !           278:  *  guarantee that we have an atomic write for all writes of size less
        !           279:  *  than PIPSIZE, even if we go to sleep in the fwrite().  Subtle race
        !           280:  *  condition?  I don't think so, since if we go to sleep in fwrite(),
        !           281:  *  it's wrt a resource unrelated to this particular INODE.
        !           282:  */
        !           283: 
        !           284: pwrite(ip, iop)
        !           285: register INODE *ip;
        !           286: register IO *iop;
        !           287: {
        !           288:        register unsigned n;
        !           289:        register unsigned ioc;
        !           290: 
        !           291:        pdump("W", ip, 0);
        !           292:        ioc = iop->io_ioc;
        !           293:        while ( !u.u_error && (ioc > 0) ) {
        !           294:                if ( !ip->i_par && !ip->i_psr ) {
        !           295:                        u.u_error = EPIPE;
        !           296:                        sendsig(SIGPIPE, SELF);
        !           297:                        goto pwrite_done;
        !           298:                }
        !           299:                if ( (n = (PIPSIZE-ip->i_pwx)) > ioc )
        !           300:                        n = ioc;
        !           301:                if ( n > (PIPSIZE-ip->i_pnc) )
        !           302:                        n = PIPSIZE - ip->i_pnc;
        !           303:                if ( (n == 0) || ((ioc <= PIPSIZE) && (n != ioc)) ) {
        !           304:                        if ( iop->io_flag & IONDLY )
        !           305:                                goto pwrite_done;
        !           306:                        if ( psleep(ip, IFWFR) < 0 )
        !           307:                                goto pwrite_done;
        !           308:                        continue;
        !           309:                }
        !           310:                iop->io_ioc = n;
        !           311:                iop->io_seek = ip->i_pwx;
        !           312:                fwrite(ip, iop);
        !           313:                n -= iop->io_ioc;
        !           314:                if ( (ip->i_pwx+=n) == PIPSIZE )
        !           315:                        ip->i_pwx = 0;
        !           316:                ip->i_pnc += n;
        !           317:                ioc -= n;
        !           318: 
        !           319:                if ( ip->i_pnc > 0 )
        !           320:                        pwake(ip, IFWFW);
        !           321:        }
        !           322: pwrite_done:
        !           323:        iop->io_ioc = ioc;
        !           324: }
        !           325: 
        !           326: 
        !           327: /*
        !           328:  *  psleep(ip, who)  --  go to sleep either waiting for a reader if (who==IFWFR)
        !           329:  *                      or waiting for a writer if (who==IFWFW).
        !           330:  *  Returns:  0  if woke up ok
        !           331:  *          -1  if woke up by signal (e.g. SIGALRM, SIGKILL, etc.)
        !           332:  */
        !           333: 
        !           334: psleep(ip, who)
        !           335: register INODE *ip;
        !           336: {
        !           337:        pdump("SA", ip, 0);
        !           338:        iunlock(ip);
        !           339:        switch ( who ) {
        !           340:        case IFWFW:
        !           341:                --ip->i_par;  ++ip->i_psr;
        !           342:                x_sleep((char *)&ip->i_psw, primed, slpriSigCatch, "pipe wx");
        !           343:                ++ip->i_par;  --ip->i_psr;
        !           344:                break;
        !           345:        case IFWFR:
        !           346:                --ip->i_paw;  ++ip->i_psw;
        !           347:                x_sleep((char *)&ip->i_psr, primed, slpriSigCatch, "pipe rx");
        !           348:                ++ip->i_paw;  --ip->i_psw;
        !           349:                break;
        !           350:        default:
        !           351:                panic("psleep() internal error");
        !           352:        }
        !           353:        ilock(ip);
        !           354:        pdump("SZ", ip, 0);
        !           355:        if ( SELF->p_ssig && nondsig() ) {
        !           356:                u.u_error = EINTR;
        !           357:                return -1;
        !           358:        }
        !           359:        return(0);
        !           360: }
        !           361: 
        !           362: 
        !           363: /*
        !           364:  *  pwake(ip, who)  --  wake up processes which are waiting for a reader if
        !           365:  *                     (who==IFWFR) or waiting for a writer if (who==IFWFW).
        !           366:  */
        !           367: 
        !           368: pwake(ip, who)
        !           369: register INODE *ip;
        !           370: {
        !           371:        pdump("KA", ip, 0);
        !           372:        switch ( who ) {
        !           373:        case IFWFW:
        !           374:                if ( ip->i_psr )
        !           375:                        wakeup((char *)&ip->i_psw);
        !           376:                if ( ip->i_pnc > 0 )
        !           377:                        pollwake(&ip->i_iev);
        !           378:                break;
        !           379:        case IFWFR:
        !           380:                if ( ip->i_psw )
        !           381:                        wakeup((char *)&ip->i_psr);
        !           382:                if ( (ip->i_pnc<PIPSIZE) && (ip->i_par || ip->i_psr) )
        !           383:                        pollwake(&ip->i_oev);
        !           384:                break;
        !           385:        default:
        !           386:                panic("pwake() internal error");
        !           387:        }
        !           388:        pdump("KZ", ip, 0);
        !           389: }
        !           390: 
        !           391: 
        !           392: /*
        !           393:  *  ppoll(ip, ev)  --  Poll the given pipe inode.
        !           394:  *  INODE *ip  --  The inode in question.
        !           395:  *  int ev     --  The event bit field.
        !           396:  *  int msec   --  Number of msecs to wait.
        !           397:  *  Returns or'ed bits according to the following rules:
        !           398:  *  POLLIN:  indicates input is available for reading, notice it is possible
        !           399:  *          to read even if there are no more writers anywhere!
        !           400:  *  POLLOUT: indicates room in pipe for new output, notice it is not possible
        !           401:  *          to write unless there is a reader attached!
        !           402:  *
        !           403:  *  No priority polls are supported.
        !           404:  */
        !           405: 
        !           406: ppoll(ip, ev, msec)
        !           407: register INODE *ip;
        !           408: int ev, msec;
        !           409: {
        !           410:        register int rval = 0;
        !           411: 
        !           412:        if ( ev & POLLIN ) {
        !           413:                if ( ip->i_pnc > 0 )
        !           414:                        rval |= POLLIN;
        !           415:                else if ( msec != 0 )
        !           416:                        pollopen(&ip->i_iev);
        !           417:        }
        !           418:        if ( ev & POLLOUT ) {
        !           419:                if ( (ip->i_pnc<PIPSIZE) && (ip->i_par || ip->i_psr) )
        !           420:                        rval |= POLLOUT;
        !           421:                else if ( msec != 0 )
        !           422:                        pollopen(&ip->i_oev);
        !           423:        }
        !           424:        return( rval );
        !           425: }
        !           426: 
        !           427: /*
        !           428:  *  pdump(loc, ip, mode)  --  A kernel debugging output line.
        !           429:  *  char *loc  --  prefix of line (two characters indicating where we are)
        !           430:  *  INODE *ip  --  The inode information to dump
        !           431:  *  int mode   --  The mode of the IO call, i.e. IPW, IPR, IPNDLY, ...
        !           432:  */
        !           433: 
        !           434: #if 1
        !           435: pdump()
        !           436: {}
        !           437: #else
        !           438: pdump(loc, ip, mode)
        !           439: char *loc;
        !           440: register INODE *ip;
        !           441: int mode;
        !           442: {
        !           443:        printf("%s ip=%x mde=%x nlk=%x rf=%x nc=%x rx=%x wx=%x",
        !           444:                loc, ip, mode, ip->i_nlink, ip->i_refc,
        !           445:                ip->i_pnc, ip->i_prx, ip->i_pwx);
        !           446: 
        !           447:        printf(" ar=%x aw=%x sr=%x sw=%x f=%x\n",
        !           448:                ip->i_par, ip->i_paw, ip->i_psr, ip->i_psw, ip->i_flag);
        !           449: }
        !           450: #endif

unix.superglobalmegacorp.com

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