Annotation of researchv10no/sys/io/stream.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * primitives dealing in stream blocks
        !             3:  */
        !             4: 
        !             5: #include "sys/param.h"
        !             6: #include "sys/stream.h"
        !             7: #include "sys/mtpr.h"
        !             8: #include "sys/buf.h"
        !             9: 
        !            10: #define        M_HIPRI 127                     /* for use by putbq */
        !            11: 
        !            12: extern struct block    cblock[];
        !            13: extern struct buf      *cblkbuf[];
        !            14: extern struct queue    queue[];
        !            15: extern int             blkcnt, blkbcnt, queuecnt;
        !            16: struct queue           *qhead;         /* head of queues to run */
        !            17: struct queue           *qtail;         /* last queue */
        !            18: 
        !            19: /*
        !            20:  * blocks are kept in handful of free lists,
        !            21:  * each containing blocks of a particular size.
        !            22:  * there are MAXLEVEL sizes, each SPLITSIZE times bigger than the last.
        !            23:  * the system starts out with blkbcnt blocks of the largest size
        !            24:  * (which are in fact buffers from bio)
        !            25:  * and blkcnt-blkbcnt blocks of the smallest size.
        !            26:  * if there are no blocks of the requested size,
        !            27:  * larger ones are split to make some.
        !            28:  * the smallest blocks (level 0) are a special case:
        !            29:  * the data lives in the block header,
        !            30:  * and there's no point splitting larger blocks to make more
        !            31:  * because there are no headers to use after splitting.
        !            32:  */
        !            33: 
        !            34: #define        MAXLEVEL        6
        !            35: #define        SPLITSIZE       4
        !            36: 
        !            37: int    rbsize[MAXLEVEL] = { 4, 16, 64, 256, 1024, 4096 }; /* real block sizes */
        !            38: int    bsize[MAXLEVEL] = { 4, 16, 64, 256, 256, 256 }; /* size for q limits */
        !            39: struct block *qfreelist[MAXLEVEL];
        !            40: short  blkfree[MAXLEVEL];
        !            41: short  blkall[MAXLEVEL];
        !            42: short  blkmax[MAXLEVEL];
        !            43: 
        !            44: /*
        !            45:  * hooks for debugging
        !            46:  * turn this on only if you need it;
        !            47:  * it's quite slow
        !            48:  */
        !            49: #if STDEBUG
        !            50: 
        !            51: static int qiniting;
        !            52: #define        BADBP(bp)       ((bp)!=&cblock[(bp)-cblock])
        !            53: 
        !            54: static
        !            55: badfreelist(lev)
        !            56:        register lev;
        !            57: {
        !            58:        register i = 0;
        !            59:        register struct block *bp;
        !            60: 
        !            61:        /* look for block that is already on the free list */
        !            62:        for(bp=qfreelist[lev];bp!=0;bp=bp->next)
        !            63:                i++;
        !            64:        if(i!=blkfree[lev]){
        !            65:                printf("blkfree[%d]==%d i==%d\n", lev, blkfree[lev], i);
        !            66:                panic("bad free list 1");
        !            67:        }
        !            68: }
        !            69: 
        !            70: static
        !            71: duplicateblock(lev, bp)
        !            72:        register lev;
        !            73:        register struct block *bp;
        !            74: {
        !            75:        register i = 0;
        !            76:        register struct block *nbp;
        !            77: 
        !            78:        /* look for block that is already on the free list */
        !            79:        for(nbp=qfreelist[lev];nbp!=0;nbp=nbp->next) {
        !            80:                if(nbp==bp)
        !            81:                        panic("duplicate free");
        !            82:                i++;
        !            83:        }
        !            84:        if(i!=blkfree[lev]){
        !            85:                printf("blkfree[%d]==%d i==%d\n", lev, blkfree[lev], i);
        !            86:                panic("bad free list 2");
        !            87:        }
        !            88: }
        !            89: #endif
        !            90: 
        !            91: /*
        !            92:  * more debugging: trace the owner of a block
        !            93:  * not so slow, but very VAX-dependent.
        !            94:  */
        !            95: #if BLKOWNER
        !            96: #define        MAXOWNER        2000    /* this many blocks will be traced */
        !            97: #define        CALLER(x)       *(&x+5) /* x is an int, and is first auto in function */
        !            98: int blkowner[MAXOWNER];
        !            99: #endif
        !           100: 
        !           101: qinit()
        !           102: {
        !           103:        register i;
        !           104:        register struct buf *bp;
        !           105: 
        !           106: #if STDEBUG
        !           107:        qiniting=1;
        !           108: #endif
        !           109:        for (i = 0; i<blkbcnt; i++) {
        !           110:                if ((bp = geteblk()) == NULL)
        !           111:                        break;          /* probably not best */
        !           112:                cblock[i].class = MAXLEVEL-1;
        !           113:                cblock[i].base = (u_char *)&bp->b_un.b_addr[0];
        !           114:                cblock[i].lim = (u_char *)&bp->b_un.b_addr[bp->b_bcount];
        !           115:                cblock[i].rbufix = i;
        !           116:                cblkbuf[i] = bp;
        !           117:                freeb(&cblock[i]);
        !           118:        }
        !           119:        blkall[MAXLEVEL-1] = 0;
        !           120:        for ( ; i<blkcnt; i++) {
        !           121:                cblock[i].class = 0;
        !           122:                cblock[i].base = &cblock[i].data[0];
        !           123:                cblock[i].lim = &cblock[i].data[sizeof(cblock[0].data)];
        !           124:                cblock[i].rbufix = NOBUFIX;
        !           125:                freeb(&cblock[i]);
        !           126:        }
        !           127:        blkall[0] = 0;
        !           128: #if STDEBUG
        !           129:        qiniting=0;
        !           130: #endif
        !           131: }
        !           132: 
        !           133: static bsplit();
        !           134: 
        !           135: struct block *
        !           136: allocb(size)
        !           137: {
        !           138: #if BLKOWNER
        !           139:        int x;
        !           140: #endif
        !           141:        register struct block *bp;
        !           142:        register lev;
        !           143:        register s;
        !           144: 
        !           145:        for (lev = 0; lev < MAXLEVEL; lev++) {
        !           146:                if (size <= rbsize[lev])
        !           147:                        break;
        !           148:        }
        !           149:        if (lev >= MAXLEVEL)
        !           150:                panic("allocb bad size");
        !           151:        s = spl6();
        !           152: #if STDEBUG
        !           153:        badfreelist(lev);
        !           154: #endif
        !           155: 
        !           156:        /* check for free block of right size */
        !           157:        if ((bp = qfreelist[lev]) == NULL) {
        !           158:                bsplit(lev+1);          /*  else try to split larger block */
        !           159:                if ((bp = qfreelist[lev]) == NULL) {
        !           160:                        if (size != QBSIZE) {
        !           161:                                splx(s);
        !           162:                                return (allocb(QBSIZE)); /* last chance */
        !           163:                        }
        !           164:                        panic("allocb no block");
        !           165:                }
        !           166:        }
        !           167:        qfreelist[lev] = bp->next;
        !           168:        blkall[lev]++;
        !           169:        if (blkall[lev] > blkmax[lev])
        !           170:                blkmax[lev] = blkall[lev];
        !           171:        blkfree[lev]--;
        !           172: #if BLKOWNER
        !           173:        if ((x = bp-cblock) < MAXOWNER)
        !           174:                blkowner[x] = CALLER(x);
        !           175: #endif
        !           176:        splx(s);
        !           177:        bp->type = M_DATA;
        !           178:        bp->next = NULL;
        !           179:        bp->rptr = bp->base;
        !           180:        bp->wptr = bp->base;
        !           181:        bp->bufix = bp->rbufix;
        !           182:        bp->class &= ~S_DELIM;
        !           183: #if STDEBUG
        !           184:        if (BADBP(bp))
        !           185:                panic("allocb");
        !           186: #endif
        !           187:        return(bp);
        !           188: }
        !           189: 
        !           190: static
        !           191: bsplit(lev)
        !           192: register lev;
        !           193: {
        !           194:        register struct block *bp, *bp1;
        !           195:        register i, size;
        !           196: 
        !           197:        if (lev>=MAXLEVEL)
        !           198:                return;
        !           199:        if ((bp = qfreelist[lev]) == NULL) {
        !           200:                bsplit(lev+1);
        !           201:                if ((bp = qfreelist[lev]) == NULL)
        !           202:                        return;
        !           203:        }
        !           204:        qfreelist[lev] = bp->next;
        !           205:        blkfree[lev]--;
        !           206:        size = (bp->lim - bp->base)/SPLITSIZE;
        !           207:        lev--;                  /* the blocks we're creating */
        !           208:        for (i=1; i<SPLITSIZE; i++) {
        !           209:                if ((bp1 = qfreelist[0]) == NULL)
        !           210:                        return;
        !           211:                qfreelist[0] = bp1->next;
        !           212:                blkfree[0]--;
        !           213:                bp1->base = bp->base;
        !           214:                bp->base += size;
        !           215:                bp1->lim = bp1->base+size;
        !           216:                bp1->class = lev;
        !           217:                bp1->rbufix = bp->rbufix;
        !           218:                bp1->next = qfreelist[lev];
        !           219:                qfreelist[lev] = bp1;
        !           220:                blkfree[lev]++;
        !           221:        }
        !           222:        bp->class = lev;
        !           223:        bp->next = qfreelist[lev];
        !           224:        qfreelist[lev] = bp;
        !           225:        blkfree[lev]++;
        !           226: }
        !           227: 
        !           228: /*
        !           229:  *  if this is a large block and its data can be squeezed
        !           230:  *  into a smaller block, do it.
        !           231:  */
        !           232: struct block *
        !           233: cramb(bp)
        !           234:        register struct block *bp;
        !           235: {
        !           236:        register struct block *nbp;
        !           237:        register int n;
        !           238: 
        !           239:        n = bp->wptr - bp->rptr;
        !           240:        if((bp->class&CL_MASK) < 3 || n > rbsize[(bp->class&CL_MASK)-1])
        !           241:                return bp;
        !           242:        nbp = allocb(n);
        !           243:        if(nbp==NULL)
        !           244:                return bp;
        !           245:        if(nbp->lim-nbp->wptr < n) {
        !           246:                freeb(nbp);
        !           247:                return bp;
        !           248:        }
        !           249:        bcopy(bp->rptr, nbp->wptr, n);
        !           250:        nbp->wptr += n;
        !           251:        nbp->type = bp->type;
        !           252:        if (bp->class & S_DELIM)
        !           253:                nbp->class |= S_DELIM;
        !           254:        freeb(bp);
        !           255:        return nbp;
        !           256: }
        !           257: 
        !           258: /*
        !           259:  * make a block that points to the same data
        !           260:  * as some existing block
        !           261:  */
        !           262: struct block *
        !           263: dupb(bp)
        !           264: register struct block *bp;
        !           265: {
        !           266: #if BLKOWNER
        !           267:        int x;
        !           268: #endif
        !           269:        register struct block *nbp;
        !           270: 
        !           271:        if ((nbp = allocb(0)) == NULL)
        !           272:                return (NULL);
        !           273:        nbp->type = bp->type;
        !           274:        nbp->rptr = bp->rptr;
        !           275:        nbp->wptr = bp->wptr;
        !           276:        nbp->bufix = bp->bufix;
        !           277:        nbp->class |= bp->class&S_DELIM;
        !           278: #if BLKOWNER
        !           279:        if ((x = nbp-cblock) < MAXOWNER)
        !           280:                blkowner[x] = CALLER(x);
        !           281: #endif
        !           282:        return (nbp);
        !           283: }
        !           284:        
        !           285: freeb(bp)
        !           286: register struct block *bp;
        !           287: {
        !           288:        register s = spl6();
        !           289:        register lev;
        !           290: 
        !           291:        lev = bp->class&CL_MASK;
        !           292: #if STDEBUG
        !           293:        if (BADBP(bp))
        !           294:                panic("freeb");
        !           295:        duplicateblock(lev, bp);
        !           296:        if (blkall[lev] <= 0 && !qiniting)
        !           297:                panic("freeb excess free");
        !           298: #endif
        !           299:        bp->next = qfreelist[lev];
        !           300:        qfreelist[lev] = bp;
        !           301:        blkall[lev]--;
        !           302:        blkfree[lev]++;
        !           303:        splx(s);
        !           304: }
        !           305: 
        !           306: struct block *
        !           307: getq(q)
        !           308: register struct queue *q;
        !           309: {
        !           310: #if BLKOWNER
        !           311:        int x;
        !           312: #endif
        !           313:        register struct block *bp;
        !           314:        register s = spl6();
        !           315: 
        !           316:        if ((bp = q->first) == NULL) {
        !           317:                if ((q->flag&QENAB) == 0)
        !           318:                        q->flag |= QWANTR;
        !           319:        } else {
        !           320:                if ((q->first = bp->next) == NULL)
        !           321:                        q->last = NULL;
        !           322:                q->count -= bsize[bp->class&CL_MASK];
        !           323:                if (q->count < q->qinfo->limit)
        !           324:                        q->flag &= ~QFULL;
        !           325:                q->flag &= ~QWANTR;
        !           326: #if BLKOWNER
        !           327:                if ((x = bp-cblock) < MAXOWNER)
        !           328:                        blkowner[x] = CALLER(x);
        !           329: #endif
        !           330:        }
        !           331:        if (q->count<=q->qinfo->lolimit && q->flag&QWANTW && OTHERQ(q)->next) {
        !           332:                register struct queue *bq = backq(q);
        !           333:                if (bq->qinfo->srvp)
        !           334:                        qenable(bq);
        !           335:                q->flag &= ~QWANTW;
        !           336:        }
        !           337:        splx(s);
        !           338: #if STDEBUG
        !           339:        if(bp && BADBP(bp))
        !           340:                panic("getq");
        !           341: #endif
        !           342:        return(bp);
        !           343: }
        !           344: 
        !           345: putq(q, bp)
        !           346: register struct queue *q;
        !           347: register struct block *bp;
        !           348: {
        !           349:        int s;
        !           350: 
        !           351: #if STDEBUG
        !           352:        if (BADBP(bp))
        !           353:                panic("putq");
        !           354: #endif
        !           355:        if (bp->type==M_FLUSH)
        !           356:                flushq(q, 0);
        !           357:        s = spl6();
        !           358:        if (q->first==NULL) {                   /* empty, just tack on */
        !           359:                q->first = bp;
        !           360:                q->last = bp;
        !           361:                bp->next = NULL;
        !           362:        } else if (bp->type<QPCTL || q->last->type>=QPCTL) {    /* put at end */
        !           363:                register struct block *lastp = q->last;
        !           364:                register n = bp->wptr - bp->rptr;
        !           365:                if (bp->type==M_DATA && lastp->type==M_DATA
        !           366:                 && (lastp->class&S_DELIM)==0
        !           367:                 && n <= lastp->lim-lastp->wptr && lastp->wptr>=lastp->base) {
        !           368:                        bcopy(bp->rptr, lastp->wptr, n);
        !           369:                        lastp->wptr += n;
        !           370:                        if (bp->class&S_DELIM)
        !           371:                                lastp->class |= S_DELIM;
        !           372:                        freeb(bp);
        !           373:                        bp = NULL;
        !           374:                } else {
        !           375:                        lastp->next = bp;
        !           376:                        q->last = bp;
        !           377:                        bp->next = NULL;
        !           378:                }
        !           379:        } else {                                /* pri, put after any others */
        !           380:                register struct block *nbp = q->first;
        !           381:                if (nbp->type < QPCTL) {
        !           382:                        bp->next = q->first;
        !           383:                        q->first = bp;
        !           384:                } else {
        !           385:                        while (nbp->next->type>=QPCTL)
        !           386:                                nbp = nbp->next;
        !           387:                        bp->next = nbp->next;
        !           388:                        nbp->next = bp;
        !           389:                }
        !           390:        }
        !           391:        if (bp) {
        !           392:                q->count += bsize[bp->class&CL_MASK];
        !           393:                if (bp->type >= QPCTL && bp->type!= M_HIPRI)
        !           394:                        q->flag |= QWANTR;
        !           395:        }
        !           396:        if (q->count >= q->qinfo->limit)
        !           397:                q->flag |= QFULL|QWANTW;
        !           398:        if ((q->flag & (QWANTR|QENAB|QNOENB)) == QWANTR && q->qinfo->srvp)
        !           399:                qenable(q);
        !           400:        splx(s);
        !           401: }
        !           402: 
        !           403: /*
        !           404:  * Put stuff back at beginning of Q
        !           405:  * (but after any priority msgs)
        !           406:  */
        !           407: putbq(q, bp)
        !           408: register struct queue *q;
        !           409: register struct block *bp;
        !           410: {
        !           411:        register savetype = bp->type;
        !           412:        register s = spl6();
        !           413: 
        !           414:        bp->type = M_HIPRI;             /* fake priority, to force to start */
        !           415:        putq(q, bp);
        !           416:        bp->type = savetype;
        !           417:        splx(s);
        !           418: }
        !           419: 
        !           420: /*
        !           421:  * empty a queue.  Leave any non-data messages, unless flag is 1.
        !           422:  */
        !           423: flushq(q, flag)
        !           424: register struct queue *q;
        !           425: {
        !           426:        register struct block *bp, *nbp;
        !           427:        register s = spl6();
        !           428: 
        !           429:        bp = q->first;
        !           430:        q->first = NULL;
        !           431:        if (q->last)
        !           432:                q->last->next = NULL;
        !           433:        q->last = NULL;
        !           434:        q->count = 0;
        !           435:        q->flag &= ~QFULL;
        !           436:        while (bp) {
        !           437:                nbp = bp->next;
        !           438:                if (bp->type != M_DATA && bp->type != M_DELIM
        !           439:                 && bp->type != M_CTL && bp->type != M_DELAY
        !           440:                 && bp->type != M_FLUSH && !flag)
        !           441:                        putq(q, bp);
        !           442:                else {
        !           443:                        if (bp->type == M_PASS)
        !           444:                                printf("flushing PASS %x\n",*(int *)(bp->rptr));
        !           445:                        freeb(bp);
        !           446:                }
        !           447:                bp = nbp;
        !           448:        }
        !           449:        if (q->flag&QWANTW && OTHERQ(q)->next) {
        !           450:                q->flag &= ~QWANTW;
        !           451:                qenable(backq(q));
        !           452:        }
        !           453:        splx(s);
        !           454: }
        !           455: 
        !           456: /*
        !           457:  * allocate a pair of queues
        !           458:  */
        !           459: struct queue *
        !           460: allocq()
        !           461: {
        !           462:        register struct queue *qp;
        !           463:        static struct queue zeroR =
        !           464:          { NULL,NULL,NULL,NULL,NULL,NULL,0,QUSE|QREADR};
        !           465:        static struct queue zeroW =
        !           466:          { NULL,NULL,NULL,NULL,NULL,NULL,0,QUSE};
        !           467: 
        !           468:        for (qp = queue; qp < &queue[queuecnt]; qp += 2) {
        !           469:                if ((qp->flag & QUSE) == 0) {
        !           470:                        *qp = zeroR;
        !           471:                        *WR(qp) = zeroW;
        !           472:                        return(qp);
        !           473:                }
        !           474:        }
        !           475:        return(NULL);
        !           476: }
        !           477: 
        !           478: /*
        !           479:  * put routine that shouldn't be called
        !           480:  */
        !           481: noput(q, c)
        !           482: struct queue *q;
        !           483: {
        !           484:        panic("noput");
        !           485: }
        !           486: 
        !           487: /*
        !           488:  * Put one data char on a queue, using f
        !           489:  */
        !           490: putd(f, q, c)
        !           491: int (*f)();
        !           492: register struct queue *q;
        !           493: {
        !           494:        register struct block *bp;
        !           495:        register s = spl6();
        !           496: 
        !           497:        if (f==putq && (bp = q->last) && bp->type==M_DATA && bp->wptr<bp->lim
        !           498:         && (bp->class&S_DELIM)==0) {
        !           499:                *bp->wptr++ = c;
        !           500:                splx(s);
        !           501:         } else {
        !           502:                splx(s);
        !           503:                if ((bp = allocb(16)) == NULL)
        !           504:                        return(0);
        !           505:                *bp->wptr++ = c;
        !           506:                (*f)(q, bp);
        !           507:        }
        !           508:        return(1);
        !           509: }
        !           510: 
        !           511: /*
        !           512:  * Put a block of type c on queue
        !           513:  */
        !           514: putctl(q, c)
        !           515: struct queue *q;
        !           516: {
        !           517:        register struct block *bp;
        !           518: 
        !           519:        if ((bp = allocb(0)) == NULL)
        !           520:                return(0);
        !           521:        bp->type = c;
        !           522:        (*q->qinfo->putp)(q, bp);
        !           523:        return(1);
        !           524: }
        !           525: 
        !           526: /*
        !           527:  * Put a block of type c, delimited, on queue
        !           528:  */
        !           529: putctld(q, c)
        !           530: struct queue *q;
        !           531: {
        !           532:        register struct block *bp;
        !           533: 
        !           534:        if ((bp = allocb(0)) == NULL)
        !           535:                return(0);
        !           536:        bp->type = c;
        !           537:        bp->class |= S_DELIM;
        !           538:        (*q->qinfo->putp)(q, bp);
        !           539:        return(1);
        !           540: }
        !           541: 
        !           542: /*
        !           543:  * Block of type c, with one byte of data
        !           544:  */
        !           545: putctl1(q, c, p)
        !           546: struct queue *q;
        !           547: {
        !           548:        register struct block *bp;
        !           549: 
        !           550:        if ((bp = allocb(1)) == NULL)
        !           551:                return(0);
        !           552:        bp->type = c;
        !           553:        *bp->wptr++ = p;
        !           554:        (*q->qinfo->putp)(q, bp);
        !           555:        return(1);
        !           556: }
        !           557: 
        !           558: /*
        !           559:  * Block of type c, delimited, with one byte of data
        !           560:  */
        !           561: putctl1d(q, c, p)
        !           562: struct queue *q;
        !           563: {
        !           564:        register struct block *bp;
        !           565: 
        !           566:        if ((bp = allocb(1)) == NULL)
        !           567:                return(0);
        !           568:        bp->type = c;
        !           569:        bp->class |= S_DELIM;
        !           570:        *bp->wptr++ = p;
        !           571:        (*q->qinfo->putp)(q, bp);
        !           572:        return(1);
        !           573: }
        !           574: 
        !           575: /*
        !           576:  * block with two parameters
        !           577:  */
        !           578: putctl2(q, c, p1, p2)
        !           579: struct queue *q;
        !           580: {
        !           581:        register struct block *bp;
        !           582: 
        !           583:        if ((bp = allocb(2)) == NULL)
        !           584:                return(0);
        !           585:        bp->type = c;
        !           586:        *bp->wptr++ = p1;
        !           587:        *bp->wptr++ = p2;
        !           588:        (*q->qinfo->putp)(q, bp);
        !           589:        return(1);
        !           590: }
        !           591: 
        !           592: /*
        !           593:  * put control record, using putq instead of queue's putp
        !           594:  */
        !           595: qpctl(q, d)
        !           596: register struct queue *q;
        !           597: {
        !           598:        register struct block *bp = allocb(1);
        !           599: 
        !           600:        if (bp) {
        !           601:                bp->type = d;
        !           602:                putq(q, bp);
        !           603:        }
        !           604: }
        !           605: 
        !           606: qpctl1(q, c, d)
        !           607: register struct queue *q;
        !           608: {
        !           609:        register struct block *bp = allocb(1);
        !           610: 
        !           611:        if (bp) {
        !           612:                bp->type = c;
        !           613:                *bp->wptr++ = d;
        !           614:                putq(q, bp);
        !           615:        }
        !           616: }
        !           617: 
        !           618: qpctld(q, d)
        !           619: register struct queue *q;
        !           620: {
        !           621:        register struct block *bp = allocb(1);
        !           622: 
        !           623:        if (bp) {
        !           624:                bp->type = d;
        !           625:                bp->class |= S_DELIM;
        !           626:                putq(q, bp);
        !           627:        }
        !           628: }
        !           629: 
        !           630: /*
        !           631:  * Copy a literal record onto queue
        !           632:  */
        !           633: putcpy(q, cp, n)
        !           634: register struct queue *q;
        !           635: register char *cp;
        !           636: {
        !           637:        register struct block *bp;
        !           638:        register nm;
        !           639: 
        !           640:        while (n) {
        !           641:                if ((bp = allocb(n)) == NULL)   /* sorry */
        !           642:                        return;
        !           643:                bp->type = M_DATA;
        !           644:                nm = bp->lim - bp->wptr;
        !           645:                if (nm > n)
        !           646:                        nm = n;
        !           647:                bcopy(cp, bp->wptr, nm);
        !           648:                cp += nm;
        !           649:                bp->wptr += nm;
        !           650:                n -= nm;
        !           651:                (*q->qinfo->putp)(q, bp);
        !           652:        }
        !           653: }
        !           654: 
        !           655: /*
        !           656:  * return the queue upstream from this one
        !           657:  */
        !           658: struct queue *
        !           659: backq(q)
        !           660: register struct queue *q;
        !           661: {
        !           662:        q = OTHERQ(q);
        !           663:        if (q->next) {
        !           664:                q = q->next;
        !           665:                return(OTHERQ(q));
        !           666:        }
        !           667:        q = OTHERQ(q);
        !           668:        printf("backq called with no back (Q %x)\n", q);
        !           669:        panic("backq");
        !           670:        return(NULL);
        !           671: }
        !           672: 
        !           673: /*
        !           674:  * Send a block back up the queue in reverse from this
        !           675:  * one (e.g. to respond to ioctls)
        !           676:  */
        !           677: qreply(q, bp)
        !           678: register struct queue *q;
        !           679: struct block *bp;
        !           680: {
        !           681:        q = OTHERQ(q);
        !           682:        (*q->next->qinfo->putp)(q->next, bp);
        !           683: }
        !           684: 
        !           685: /*
        !           686:  * Enable a queue: put it on list of those whose srvp's are
        !           687:  * ready to run.
        !           688:  */
        !           689: qenable(q)
        !           690: register struct queue *q;
        !           691: {
        !           692:        register s;
        !           693: 
        !           694:        s = spl6();
        !           695:        if (q->flag & QENAB) {
        !           696:                splx(s);
        !           697:                return;
        !           698:        }
        !           699:        if (q->qinfo->srvp==NULL) {
        !           700:                splx(s);
        !           701:                return;
        !           702:        }
        !           703:        q->flag |= QENAB;
        !           704:        q->link = NULL;
        !           705:        if (qhead==NULL)
        !           706:                qhead = q;
        !           707:        else
        !           708:                qtail->link = q;
        !           709:        qtail = q;
        !           710:        setqsched();
        !           711:        splx(s);
        !           712: }
        !           713: 
        !           714: /*
        !           715:  * Run the srvp's of each enabled queue
        !           716:  *     -- Should not be reentered
        !           717:  */
        !           718: queuerun()
        !           719: {
        !           720:        register struct queue *q;
        !           721:        register s;
        !           722:        extern int queueflag;
        !           723:        extern char *panicstr;
        !           724: 
        !           725:        if (panicstr)
        !           726:                return;         /* to minimize destruction */
        !           727:        s = spl6();
        !           728:        queueflag++;
        !           729:        while (q = qhead) {
        !           730:                if ((qhead = q->link) == NULL)
        !           731:                        qtail = NULL;
        !           732:                q->flag &= ~QENAB;
        !           733:                splx(s);
        !           734:                if (q->qinfo->srvp != NULL)
        !           735:                        (*q->qinfo->srvp)(q);
        !           736:                else
        !           737:                        printf("Q %x run with no srvp\n", q);
        !           738:                spl6();
        !           739:        }
        !           740:        queueflag--;
        !           741:        splx(s);
        !           742: }

unix.superglobalmegacorp.com

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