Annotation of researchv10no/sys/io/stream.c, revision 1.1.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.