| plan 9 kernel history: overview | file list | diff list |
2001/0203/port/qio.c (diff list | history)
| 1993/0526/sys/src/9/port/qio.c:142,156 – 1993/0527/sys/src/9/port/qio.c:142,159 (short | long) | ||
| 1993/0526 | cl = &arena.alloc[pow]; lock(cl); p = cl->first; | |
| 1993/0527 | if(p == 0){ unlock(cl); return 0; | |
| 1993/0526 | } | |
| 1993/0527 | cl->have--; cl->first = p->next; | |
| 1993/0526 | unlock(cl); b = (Block *)p; b->base = (uchar*)(b+1); b->wp = b->rp = b->base; b->lim = b->base + (1<<pow) - sizeof(Block); | |
| 1993/0527 | b->flag = 0; | |
| 1993/0526 | return b; } panic("iallocb %d\n", size); | |
| 1993/0526/sys/src/9/port/qio.c:186,191 – 1993/0527/sys/src/9/port/qio.c:189,195 | ||
| 1993/0526 | b->base = (uchar*)(b+1); b->rp = b->wp = b->base; b->lim = b->base + size; | |
| 1993/0527 | b->flag = 0; | |
| 1993/0526 | return b; } | |
| 1993/0526/sys/src/9/port/qio.c:200,206 – 1993/0527/sys/src/9/port/qio.c:204,212 | ||
| 1993/0526 | Block *b; int n; | |
| 1993/0527 | /* sync with qwrite */ | |
| 1993/0526 | lock(q); | |
| 1993/0527 | ||
| 1993/0526 | b = q->bfirst; if(b == 0){ q->state |= Qstarve; | |
| 1993/0526/sys/src/9/port/qio.c:211,217 – 1993/0527/sys/src/9/port/qio.c:217,223 | ||
| 1993/0526 | if(n < len) len = n; memmove(p, b->rp, len); | |
| 1993/0527 | if((q->state & Qmsg) || len == n) | |
| 1993/0526 | q->bfirst = b->next; else b->rp += len; | |
| 1993/0526/sys/src/9/port/qio.c:223,229 – 1993/0527/sys/src/9/port/qio.c:229,235 | ||
| 1993/0526 | unlock(q); | |
| 1993/0527 | if((q->state & Qmsg) || len == n) | |
| 1993/0526 | ifree(b); return len; | |
| 1993/0526/sys/src/9/port/qio.c:235,252 – 1993/0527/sys/src/9/port/qio.c:241,261 | ||
| 1993/0526 | Block *b; int n; | |
| 1993/0527 | /* sync with qread */ | |
| 1993/0526 | lock(q); | |
| 1993/0527 | ||
| 1993/0526 | b = q->rfirst; if(b){ /* hand to waiting receiver */ | |
| 1993/0527 | q->rfirst = b->next; unlock(q); | |
| 1993/0526 | n = b->lim - b->wp; if(n < len) len = n; memmove(b->wp, p, len); b->wp += len; | |
| 1993/0527 | b->flag |= Bfilled; | |
| 1993/0526 | wakeup(&b->r); | |
| 1993/0526/sys/src/9/port/qio.c:258,266 – 1993/0527/sys/src/9/port/qio.c:267,276 | ||
| 1993/0526 | /* save in buffer */ b = q->bfirst; | |
| 1993/0527 | if((q->state & Qmsg) == 0 && b && b->lim - b->wp <= len){ | |
| 1993/0526 | memmove(b->wp, p, len); b->wp += len; | |
| 1993/0527 | b->flag |= Bfilled; | |
| 1993/0526 | } else { b = iallocb(len); if(b == 0){ | |
| 1993/0526/sys/src/9/port/qio.c:267,274 – 1993/0527/sys/src/9/port/qio.c:277,285 | ||
| 1993/0526 | unlock(q); return -1; } | |
| 1993/0527 | memmove(b->wp, p, len); | |
| 1993/0526 | b->wp += len; | |
| 1993/0527 | b->flag |= Bfilled; | |
| 1993/0526 | if(q->bfirst) q->blast->next = b; else | |
| 1993/0526/sys/src/9/port/qio.c:277,282 – 1993/0527/sys/src/9/port/qio.c:288,294 | ||
| 1993/0526 | } q->len += len; unlock(q); | |
| 1993/0527 | ||
| 1993/0526 | return len; } | |
| 1993/0526/sys/src/9/port/qio.c:285,298 – 1993/0527/sys/src/9/port/qio.c:297,309 | ||
| 1993/0526 | { int n, sofar; | |
| 1993/0527 | sofar = 0; do { n = qproduce0(q, p + sofar, len - sofar); | |
| 1993/0526 | if(n < 0) break; | |
| 1993/0527 | sofar += n; } while(sofar < len && (q->state & Qmsg) == 0); | |
| 1993/0526 | return sofar; } | |
| 1993/0526/sys/src/9/port/qio.c:315,344 – 1993/0527/sys/src/9/port/qio.c:326,385 | ||
| 1993/0526 | return q; } | |
| 1993/0527 | ulong qrtoomany; ulong qrtoofew; | |
| 1993/0526 | static int bfilled(void *a) { Block *b = a; | |
| 1993/0527 | return b->flag & Bfilled; | |
| 1993/0526 | } long qread(Queue *q, char *p, int len) { | |
| 1993/0527 | Block *b, *bb, **l; | |
| 1993/0526 | int x, n; qlock(&q->rlock); | |
| 1993/0527 | b = 0; if(waserror()){ qunlock(&q->rlock); if(b) free(b); nexterror(); } | |
| 1993/0526 |
| |
| 1993/0527 | /* * If there are no buffered blocks, allocate a block * for the qproducer/qwrite to fill. This is * optimistic and and we will * sometimes be wrong: after locking we may either * have to throw away or allocate one. * * We hope to replace the allocb with a kmap later on. */ retry: if(q->bfirst == 0) b = allocb(len); | |
| 1993/0526 | ||
| 1993/0527 | /* sync with qwrite/qproduce */ | |
| 1993/0526 | x = splhi(); lock(q); | |
| 1993/0527 | ||
| 1993/0526 | bb = q->bfirst; if(bb == 0){ | |
| 1993/0527 | if(b == 0){ /* we guessed wrong, drop the locks and try again */ unlock(q); splx(x); qrtoofew++; goto retry; } /* add ourselves to the list of readers */ | |
| 1993/0526 | if(q->rfirst) q->rlast->next = b; else | |
| 1993/0526/sys/src/9/port/qio.c:347,356 – 1993/0527/sys/src/9/port/qio.c:388,420 | ||
| 1993/0526 | unlock(q); splx(x); qunlock(&q->rlock); | |
| 1993/0527 | poperror(); if(waserror()){ /* on error, unlink us from the chain */ x = splhi(); lock(q); l = &q->rfirst; for(bb = q->rfirst; bb; bb = bb->next){ if(b == bb){ *l = bb->next; break; } else l = &bb->next; } unlock(q); splx(x); free(b); nexterror(); } /* wait for the producer */ | |
| 1993/0526 | sleep(&b->r, bfilled, b); n = BLEN(b); memmove(p, b->rp, n); | |
| 1993/0527 | poperror(); | |
| 1993/0526 | free(b); | |
| 1993/0527 | ||
| 1993/0526 | return n; } | |
| 1993/0526/sys/src/9/port/qio.c:362,372 – 1993/0527/sys/src/9/port/qio.c:426,438 | ||
| 1993/0526 | q->len -= n; unlock(q); splx(x); | |
| 1993/0527 | /* do this outside of the lock(q)! */ | |
| 1993/0526 | memmove(p, bb->rp, n); bb->rp += n; | |
| 1993/0527 | /* free it or put it back on the queue */ if(bb->rp >= bb->wp || (q->state&Qmsg)) | |
| 1993/0526 | free(bb); else { x = splhi(); | |
| 1993/0526/sys/src/9/port/qio.c:376,428 – 1993/0527/sys/src/9/port/qio.c:442,504 | ||
| 1993/0526 | unlock(q); splx(x); } | |
| 1993/0527 | poperror(); | |
| 1993/0526 | qunlock(&q->rlock); | |
| 1993/0527 | if(b){ qrtoomany++; free(b); } | |
| 1993/0526 | return n; } | |
| 1993/0527 | ulong qwtoomany; ulong qwtoofew; | |
| 1993/0526 |
| |
| 1993/0527 | qwrite0(Queue *q, char *p, int len, Block *b) | |
| 1993/0526 | { | |
| 1993/0527 | Block *bb; int x, n, sofar; | |
| 1993/0526 |
| |
| 1993/0527 | /* sync with qconsume/qread */ | |
| 1993/0526 | x = splhi(); lock(q); | |
| 1993/0527 | sofar = 0; while(bb = q->rfirst){ | |
| 1993/0526 | /* hand to waiting receiver */ | |
| 1993/0527 | n = bb->lim - bb->wp; if(n > len-sofar) n = len - sofar; memmove(bb->wp, p+sofar, n); bb->wp += n; bb->flag |= Bfilled; | |
| 1993/0526 | wakeup(&bb->r); | |
| 1993/0527 | sofar += n; if(sofar == len){ if(b){ free(b); /* we were wrong to allocate */ qwtoomany++; } return len; } | |
| 1993/0526 | } | |
| 1993/0527 | /* buffer what ever is left */ if(b == 0){ /* we should have alloc'd, return to qwrite and have it do it */ unlock(q); splx(x); qwtoofew++; return sofar; } b->rp += sofar; | |
| 1993/0526 | x = splhi(); lock(q); | |
| 1993/0526/sys/src/9/port/qio.c:442,452 – 1993/0527/sys/src/9/port/qio.c:518,552 | ||
| 1993/0526 | return len; } | |
| 1993/0527 | static int qnotfull(void *a) { Queue *q = a; return q->len < q->limit; } | |
| 1993/0526 | long qwrite(Queue *q, char *p, int len) { | |
| 1993/0527 | int n, i; Block *b; | |
| 1993/0526 | ||
| 1993/0527 | /* * If there are no readers, grab a buffer and copy * into it before locking anything down. This * provides the highest concurrency but we will * sometimes be wrong: after locking we may either * have to throw away or allocate one. */ if(q->rfirst == 0){ b = allocb(len); memmove(b->wp, p, len); b->wp += len; } else b = 0; /* ensure atomic writes */ | |
| 1993/0526 | qlock(&q->wlock); if(waserror()){ qunlock(&q->wlock); | |
| 1993/0526/sys/src/9/port/qio.c:453,469 – 1993/0527/sys/src/9/port/qio.c:553,573 | ||
| 1993/0526 | nexterror(); } | |
| 1993/0527 | /* flow control */ sleep(&q->r, qnotfull, q); n = qwrite0(q, p, len, b); if(n != len){ /* no readers and we need a buffer */ i = len - n; b = allocb(i); memmove(b->wp, p + n, i); b->wp += n; n += qwrite0(q, p + n, i, b); | |
| 1993/0526 | } | |
| 1993/0527 | poperror(); return n; | |
| 1993/0526 | } | |
| 1993/0527/sys/src/9/port/qio.c:150,159 – 1993/0528/sys/src/9/port/qio.c:150,159 (short | long) | ||
| 1993/0527 | cl->first = p->next; | |
| 1993/0526 | unlock(cl); b = (Block *)p; | |
| 1993/0528 | memset(b, 0, sizeof(Block)); | |
| 1993/0526 | b->base = (uchar*)(b+1); b->wp = b->rp = b->base; b->lim = b->base + (1<<pow) - sizeof(Block); | |
| 1993/0527 |
| |
| 1993/0526 | return b; } panic("iallocb %d\n", size); | |
| 1993/0527/sys/src/9/port/qio.c:186,191 – 1993/0528/sys/src/9/port/qio.c:186,192 | ||
| 1993/0526 | if(b == 0) exhausted("Blocks"); | |
| 1993/0528 | memset(b, 0, sizeof(Block)); | |
| 1993/0526 | b->base = (uchar*)(b+1); b->rp = b->wp = b->base; b->lim = b->base + size; | |
| 1993/0527/sys/src/9/port/qio.c:202,208 – 1993/0528/sys/src/9/port/qio.c:203,209 | ||
| 1993/0526 | qconsume(Queue *q, uchar *p, int len) { Block *b; | |
| 1993/0528 | int n, dowakeup; | |
| 1993/0526 | ||
| 1993/0527 | /* sync with qwrite */ | |
| 1993/0526 | lock(q); | |
| 1993/0527/sys/src/9/port/qio.c:213,218 – 1993/0528/sys/src/9/port/qio.c:214,220 | ||
| 1993/0526 | unlock(q); return -1; } | |
| 1993/0528 | ||
| 1993/0526 | n = BLEN(b); if(n < len) len = n; | |
| 1993/0527/sys/src/9/port/qio.c:223,234 – 1993/0528/sys/src/9/port/qio.c:225,243 | ||
| 1993/0526 | b->rp += len; q->len -= len; | |
| 1993/0528 | /* if writer flow controlled, restart */ if((q->state & Qflow) && q->len < q->limit/2){ q->state &= ~Qflow; dowakeup = 1; } else dowakeup = 0; | |
| 1993/0526 | unlock(q); | |
| 1993/0528 | if(dowakeup) wakeup(&q->wr); /* discard the block if we're done with it */ | |
| 1993/0527 | if((q->state & Qmsg) || len == n) | |
| 1993/0526 | ifree(b); | |
| 1993/0527/sys/src/9/port/qio.c:235,264 – 1993/0528/sys/src/9/port/qio.c:244,258 | ||
| 1993/0526 | return len; } | |
| 1993/0528 | int qproduce(Queue *q, uchar *p, int len) | |
| 1993/0526 | { Block *b; | |
| 1993/0528 | int dowakeup; | |
| 1993/0526 | ||
| 1993/0527 | /* sync with qread */ | |
| 1993/0526 | lock(q); | |
| 1993/0527 | ||
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0527/sys/src/9/port/qio.c:279,285 – 1993/0528/sys/src/9/port/qio.c:273,278 | ||
| 1993/0526 | } | |
| 1993/0527 | memmove(b->wp, p, len); | |
| 1993/0526 | b->wp += len; | |
| 1993/0527 |
| |
| 1993/0526 | if(q->bfirst) q->blast->next = b; else | |
| 1993/0527/sys/src/9/port/qio.c:287,312 – 1993/0528/sys/src/9/port/qio.c:280,298 | ||
| 1993/0526 | q->blast = b; } q->len += len; | |
| 1993/0528 | if(q->state & Qstarve){ q->state &= ~Qstarve; dowakeup = 1; } else dowakeup = 0; | |
| 1993/0526 | unlock(q); | |
| 1993/0527 | ||
| 1993/0528 | if(dowakeup) wakeup(&q->rr); | |
| 1993/0526 | return len; } | |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0527/sys/src/9/port/qio.c:317,323 – 1993/0528/sys/src/9/port/qio.c:303,311 | ||
| 1993/0526 | q = malloc(sizeof(Queue)); if(q == 0) | |
| 1993/0528 | return 0; memset(q, 0, sizeof(Queue)); | |
| 1993/0526 | q->limit = limit; q->kick = kick; q->arg = arg; | |
| 1993/0527/sys/src/9/port/qio.c:326,573 – 1993/0528/sys/src/9/port/qio.c:314,520 | ||
| 1993/0526 | return q; } | |
| 1993/0527 |
| |
| 1993/0526 | static int | |
| 1993/0528 | notempty(void *a) | |
| 1993/0526 | { | |
| 1993/0528 | Queue *q = a; | |
| 1993/0526 | ||
| 1993/0527 |
| |
| 1993/0528 | return q->bfirst != 0; | |
| 1993/0526 | } | |
| 1993/0528 | /* * read a queue. if no data is queued, post a Block * and wait on its Rendez. */ | |
| 1993/0526 | long qread(Queue *q, char *p, int len) { | |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0528 | Block *b; int x, n, dowakeup; | |
| 1993/0526 | qlock(&q->rlock); | |
| 1993/0527 |
| |
| 1993/0526 | ||
| 1993/0527 |
| |
| 1993/0528 | /* wait for data */ for(;;){ /* sync with qwrite/qproduce */ x = splhi(); lock(q); | |
| 1993/0526 | ||
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0527 | ||
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0528 | if(q->state & Qclosed){ | |
| 1993/0527 | unlock(q); splx(x); | |
| 1993/0528 | return 0; | |
| 1993/0527 | } | |
| 1993/0526 |
| |
| 1993/0528 | b = q->bfirst; if(b) break; q->state |= Qstarve; | |
| 1993/0526 | unlock(q); splx(x); | |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0527 | ||
| 1993/0526 |
| |
| 1993/0528 | sleep(&q->rr, notempty, q); | |
| 1993/0526 | } | |
| 1993/0528 | /* remove a buffered block */ q->bfirst = b->next; n = BLEN(b); | |
| 1993/0526 | q->len -= n; | |
| 1993/0528 | /* if writer flow controlled, restart */ if((q->state & Qflow) && q->len < q->limit/2){ q->state &= ~Qflow; dowakeup = 1; } else dowakeup = 0; | |
| 1993/0526 | unlock(q); splx(x); | |
| 1993/0527 | /* do this outside of the lock(q)! */ | |
| 1993/0526 |
| |
| 1993/0528 | if(n > len) n = len; memmove(p, b->rp, n); b->rp += n; | |
| 1993/0526 | ||
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0528 | /* free it or put it what's left on the queue */ if(b->rp >= b->wp || (q->state&Qmsg)) free(b); | |
| 1993/0526 | else { x = splhi(); lock(q); | |
| 1993/0528 | b->next = q->bfirst; q->bfirst = b; q->len += BLEN(b); | |
| 1993/0526 | unlock(q); splx(x); } | |
| 1993/0527 | ||
| 1993/0528 | /* wakeup flow controlled writers (with a bit of histeresis) */ if(dowakeup) wakeup(&q->wr); | |
| 1993/0527 | poperror(); | |
| 1993/0526 | qunlock(&q->rlock); | |
| 1993/0527 |
| |
| 1993/0526 | return n; } | |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0528 | static int qnotfull(void *a) | |
| 1993/0526 | { | |
| 1993/0527 |
| |
| 1993/0528 | Queue *q = a; | |
| 1993/0526 | ||
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0528 | return q->len < q->limit; } | |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0528 | /* * write to a queue. if no reader blocks are posted * queue the data. */ long qwrite(Queue *q, char *p, int len) { int x, dowakeup; Block *b; | |
| 1993/0526 | ||
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0528 | b = allocb(len); memmove(b->wp, p, len); b->wp += len; | |
| 1993/0526 | ||
| 1993/0527 |
| |
| 1993/0528 | /* flow control */ while(!qnotfull(q)){ qlock(&q->wlock); q->state |= Qflow; sleep(&q->wr, qnotfull, q); qunlock(&q->wlock); | |
| 1993/0526 | } | |
| 1993/0527 |
| |
| 1993/0528 | x = splhi(); lock(q); if(q->state & Qclosed){ | |
| 1993/0527 | unlock(q); splx(x); | |
| 1993/0528 | error(Ehungup); | |
| 1993/0527 | } | |
| 1993/0526 |
| |
| 1993/0528 | b->next = q->bfirst; q->bfirst = b; | |
| 1993/0526 | q->len += len; | |
| 1993/0528 | if(q->state & Qstarve){ | |
| 1993/0526 | q->state &= ~Qstarve; | |
| 1993/0528 | dowakeup = 1; } else dowakeup = 0; | |
| 1993/0526 | unlock(q); splx(x); | |
| 1993/0528 | if(dowakeup) wakeup(&q->rr); | |
| 1993/0526 | return len; } | |
| 1993/0527 |
| |
| 1993/0528 | /* * Mark a queue as closed. No further IO is permitted. * All blocks are released. */ void qclose(Queue *q) | |
| 1993/0527 | { | |
| 1993/0528 | int x; Block *b, *bfirst; | |
| 1993/0527 |
| |
| 1993/0528 | /* mark it */ x = splhi(); lock(q); q->state |= Qclosed; bfirst = q->bfirst; q->bfirst = 0; unlock(q); splx(x); | |
| 1993/0527 | ||
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0526 | ||
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0528 | /* free queued blocks */ while(b = bfirst){ bfirst = b->next; free(b); | |
| 1993/0526 | } | |
| 1993/0527 |
| |
| 1993/0528 | /* wake up readers/writers */ wakeup(&q->rr); wakeup(&q->wr); } | |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0528 | /* * Mark a queue as closed. Wakeup any readers. Don't remove queued * blocks. */ void qhangup(Queue *q) { int x; | |
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0528 | /* mark it */ x = splhi(); lock(q); q->state |= Qclosed; unlock(q); splx(x); | |
| 1993/0527 |
| |
| 1993/0528 | /* wake up readers/writers */ wakeup(&q->rr); wakeup(&q->wr); } /* * mark a queue as no longer hung up */ void qreopen(Queue *q) { q->state &= ~Qclosed; | |
| 1993/0526 | } | |
| 1993/0528/sys/src/9/port/qio.c:5,10 – 1993/0530/sys/src/9/port/qio.c:5,13 (short | long) | ||
| 1993/0526 | #include "fns.h" #include "../port/error.h" | |
| 1993/0530 | /* * interrupt level memory allocation */ | |
| 1993/0526 | typedef struct Chunk Chunk; typedef struct Chunkl Chunkl; typedef struct Arena Arena; | |
| 1993/0528/sys/src/9/port/qio.c:39,44 – 1993/0530/sys/src/9/port/qio.c:42,97 | ||
| 1993/0526 | static Arena arena; /* | |
| 1993/0530 | * IO queues */ typedef struct Block Block; typedef struct Queue Queue; struct Block { Block *next; uchar *rp; /* first unconsumed byte */ uchar *wp; /* first empty byte */ uchar *lim; /* 1 past the end of the buffer */ uchar *base; /* start of the buffer */ uchar flag; }; #define BLEN(b) ((b)->wp - (b)->rp) struct Queue { Lock; Block *bfirst; /* buffer */ Block *blast; int len; /* bytes in queue */ int limit; /* max bytes in queue */ int state; void (*kick)(void*); /* restart output */ void *arg; /* argument to kick */ QLock rlock; /* mutex for reading processes */ Rendez rr; /* process waiting to read */ QLock wlock; /* mutex for writing processes */ Rendez wr; /* process waiting to write */ }; enum { /* Block.flag */ Bfilled=1, /* block filled */ /* Queue.state */ Qstarve= (1<<0), /* consumer starved */ Qmsg= (1<<1), /* message stream */ Qclosed= (1<<2), Qflow= (1<<3), }; /* | |
| 1993/0526 | * Manage interrupt level memory allocation. */ static void | |
| 1993/0528/sys/src/9/port/qio.c:297,303 – 1993/0530/sys/src/9/port/qio.c:350,356 | ||
| 1993/0526 | * called by non-interrupt code */ Queue* | |
| 1993/0530 | qopen(int limit, int msg, void (*kick)(void*), void *arg) | |
| 1993/0526 | { Queue *q; | |
| 1993/0528/sys/src/9/port/qio.c:309,315 – 1993/0530/sys/src/9/port/qio.c:362,368 | ||
| 1993/0526 | q->limit = limit; q->kick = kick; q->arg = arg; | |
| 1993/0530 | q->state = msg ? Qmsg : 0; | |
| 1993/0526 | return q; } | |
| 1993/0528/sys/src/9/port/qio.c:517,520 – 1993/0530/sys/src/9/port/qio.c:570,582 | ||
| 1993/0528 | qreopen(Queue *q) { q->state &= ~Qclosed; | |
| 1993/0530 | } /* * return bytes queued */ int qlen(Queue *q) { return q->len; | |
| 1993/0526 | } | |
| 1993/0530/sys/src/9/port/qio.c:253,262 – 1993/0601/sys/src/9/port/qio.c:253,263 (short | long) | ||
| 1993/0526 | * set, any bytes left in a block afer a consume are discarded. */ int | |
| 1993/0601 | qconsume(Queue *q, void *vp, int len) | |
| 1993/0526 | { Block *b; | |
| 1993/0528 | int n, dowakeup; | |
| 1993/0601 | uchar *p = vp; | |
| 1993/0526 | ||
| 1993/0527 | /* sync with qwrite */ | |
| 1993/0526 | lock(q); | |
| 1993/0530/sys/src/9/port/qio.c:298,307 – 1993/0601/sys/src/9/port/qio.c:299,309 | ||
| 1993/0526 | } | |
| 1993/0528 | int | |
| 1993/0601 | qproduce(Queue *q, void *vp, int len) | |
| 1993/0526 | { Block *b; | |
| 1993/0528 | int dowakeup; | |
| 1993/0601 | uchar *p = vp; | |
| 1993/0526 | ||
| 1993/0527 | /* sync with qread */ | |
| 1993/0526 | lock(q); | |
| 1993/0530/sys/src/9/port/qio.c:340,347 – 1993/0601/sys/src/9/port/qio.c:342,352 | ||
| 1993/0528 | dowakeup = 0; | |
| 1993/0526 | unlock(q); | |
| 1993/0527 | ||
| 1993/0528 |
| |
| 1993/0601 | if(dowakeup){ if(q->kick) (*q->kick)(q->arg); | |
| 1993/0528 | wakeup(&q->rr); | |
| 1993/0601 | } | |
| 1993/0528 | ||
| 1993/0526 | return len; } | |
| 1993/0530/sys/src/9/port/qio.c:363,368 – 1993/0601/sys/src/9/port/qio.c:368,374 | ||
| 1993/0526 | q->kick = kick; q->arg = arg; | |
| 1993/0530 | q->state = msg ? Qmsg : 0; | |
| 1993/0601 | q->state |= Qstarve; | |
| 1993/0526 | return q; } | |
| 1993/0530/sys/src/9/port/qio.c:380,389 – 1993/0601/sys/src/9/port/qio.c:386,396 | ||
| 1993/0528 | * and wait on its Rendez. */ | |
| 1993/0526 | long | |
| 1993/0601 | qread(Queue *q, void *vp, int len) | |
| 1993/0526 | { | |
| 1993/0528 | Block *b; int x, n, dowakeup; | |
| 1993/0601 | uchar *p = vp; | |
| 1993/0526 | qlock(&q->rlock); | |
| 1993/0527 | if(waserror()){ | |
| 1993/0530/sys/src/9/port/qio.c:467,476 – 1993/0601/sys/src/9/port/qio.c:474,484 | ||
| 1993/0528 | * queue the data. */ long | |
| 1993/0601 | qwrite(Queue *q, void *vp, int len, int nowait) | |
| 1993/0528 | { int x, dowakeup; Block *b; | |
| 1993/0601 | uchar *p = vp; | |
| 1993/0526 | ||
| 1993/0528 | b = allocb(len); memmove(b->wp, p, len); | |
| 1993/0530/sys/src/9/port/qio.c:478,483 – 1993/0601/sys/src/9/port/qio.c:486,493 | ||
| 1993/0526 | ||
| 1993/0528 | /* flow control */ while(!qnotfull(q)){ | |
| 1993/0601 | if(nowait) return len; | |
| 1993/0528 | qlock(&q->wlock); q->state |= Qflow; sleep(&q->wr, qnotfull, q); | |
| 1993/0530/sys/src/9/port/qio.c:493,500 – 1993/0601/sys/src/9/port/qio.c:503,513 | ||
| 1993/0528 | error(Ehungup); | |
| 1993/0527 | } | |
| 1993/0526 | ||
| 1993/0528 |
| |
| 1993/0601 | if(q->bfirst) q->blast->next = b; else q->bfirst = b; q->blast = b; | |
| 1993/0526 | q->len += len; | |
| 1993/0528 | if(q->state & Qstarve){ | |
| 1993/0530/sys/src/9/port/qio.c:506,513 – 1993/0601/sys/src/9/port/qio.c:519,529 | ||
| 1993/0526 | unlock(q); splx(x); | |
| 1993/0528 |
| |
| 1993/0601 | if(dowakeup){ if(q->kick) (*q->kick)(q->arg); | |
| 1993/0528 | wakeup(&q->rr); | |
| 1993/0601 | } | |
| 1993/0528 | ||
| 1993/0526 | return len; } | |
| 1993/0530/sys/src/9/port/qio.c:570,575 – 1993/0601/sys/src/9/port/qio.c:586,592 | ||
| 1993/0528 | qreopen(Queue *q) { q->state &= ~Qclosed; | |
| 1993/0601 | q->state |= Qstarve; | |
| 1993/0530 | } /* | |
| 1993/0530/sys/src/9/port/qio.c:579,582 – 1993/0601/sys/src/9/port/qio.c:596,608 | ||
| 1993/0530 | qlen(Queue *q) { return q->len; | |
| 1993/0601 | } /* * return true if we can read without blocking */ int qcanread(Queue *q) { return q->bfirst!=0; | |
| 1993/0526 | } | |
| 1993/0601/sys/src/9/port/qio.c:178,184 – 1993/0725/sys/src/9/port/qio.c:178,184 (short | long) | ||
| 1993/0526 | } /* start garbage collector */ | |
| 1993/0725 | kproc("ialloc", iallockproc, 0); | |
| 1993/0526 | } Block* | |
| 1993/0601/sys/src/9/port/qio.c:407,412 – 1993/0725/sys/src/9/port/qio.c:407,413 | ||
| 1993/0528 | if(q->state & Qclosed){ | |
| 1993/0527 | unlock(q); splx(x); | |
| 1993/0725 | print("Qclosed %lux\n", q); | |
| 1993/0528 | return 0; | |
| 1993/0527 | } | |
| 1993/0601/sys/src/9/port/qio.c:439,445 – 1993/0725/sys/src/9/port/qio.c:440,446 | ||
| 1993/0528 | memmove(p, b->rp, n); b->rp += n; | |
| 1993/0526 | ||
| 1993/0528 |
| |
| 1993/0725 | /* free it or put what's left on the queue */ | |
| 1993/0528 | if(b->rp >= b->wp || (q->state&Qmsg)) free(b); | |
| 1993/0526 | else { | |
| 1993/0725/sys/src/9/port/qio.c:407,413 – 1993/0727/sys/src/9/port/qio.c:407,412 (short | long) | ||
| 1993/0528 | if(q->state & Qclosed){ | |
| 1993/0527 | unlock(q); splx(x); | |
| 1993/0725 |
| |
| 1993/0528 | return 0; | |
| 1993/0527 | } | |
| 1993/0727/sys/src/9/port/qio.c:404,409 – 1993/0728/sys/src/9/port/qio.c:404,413 (short | long) | ||
| 1993/0528 | x = splhi(); lock(q); | |
| 1993/0526 | ||
| 1993/0728 | b = q->bfirst; if(b) break; | |
| 1993/0528 | if(q->state & Qclosed){ | |
| 1993/0527 | unlock(q); splx(x); | |
| 1993/0727/sys/src/9/port/qio.c:410,418 – 1993/0728/sys/src/9/port/qio.c:414,419 | ||
| 1993/0528 | return 0; | |
| 1993/0527 | } | |
| 1993/0528 |
| |
| 1993/0526 | unlock(q); splx(x); | |
| 1993/0728/sys/src/9/port/qio.c:115,123 – 1993/0804/sys/src/9/port/qio.c:115,124 (short | long) | ||
| 1993/0526 | unlock(cl); splx(x); | |
| 1993/0804 | while(first != 0) { | |
| 1993/0526 | p = first->next; free(first); | |
| 1993/0804 | first = p; | |
| 1993/0526 | } } | |
| 1993/0728/sys/src/9/port/qio.c:146,155 – 1993/0804/sys/src/9/port/qio.c:147,158 | ||
| 1993/0526 | first = 0; l = &first; | |
| 1993/0804 | i = cl->goal - cl->have; for(x = i; x > 0; x--){ | |
| 1993/0526 | p = malloc(1<<pow); if(p == 0) break; | |
| 1993/0804 | ||
| 1993/0526 | *l = p; l = &p->next; } | |
| 1993/0728/sys/src/9/port/qio.c:190,196 – 1993/0804/sys/src/9/port/qio.c:193,199 | ||
| 1993/0526 | Block *b; size += sizeof(Block); | |
| 1993/0804 | for(pow = Minpow; pow <= Maxpow; pow++){ | |
| 1993/0526 | if(size <= (1<<pow)){ cl = &arena.alloc[pow]; lock(cl); | |
| 1993/0728/sys/src/9/port/qio.c:205,214 – 1993/0804/sys/src/9/port/qio.c:208,220 | ||
| 1993/0526 | b = (Block *)p; | |
| 1993/0528 | memset(b, 0, sizeof(Block)); | |
| 1993/0526 | b->base = (uchar*)(b+1); | |
| 1993/0804 | b->wp = b->base; b->rp = b->base; | |
| 1993/0526 | b->lim = b->base + (1<<pow) - sizeof(Block); return b; } | |
| 1993/0804 | } | |
| 1993/0526 | panic("iallocb %d\n", size); return 0; /* not reached */ } | |
| 1993/0728/sys/src/9/port/qio.c:239,247 – 1993/0804/sys/src/9/port/qio.c:245,253 | ||
| 1993/0526 | if(b == 0) exhausted("Blocks"); | |
| 1993/0528 |
| |
| 1993/0526 | b->base = (uchar*)(b+1); | |
| 1993/0804 | b->rp = b->base; b->wp = b->base; | |
| 1993/0526 | b->lim = b->base + size; | |
| 1993/0527 | b->flag = 0; | |
| 1993/0526 | ||
| 1993/0728/sys/src/9/port/qio.c:549,557 – 1993/0804/sys/src/9/port/qio.c:555,564 | ||
| 1993/0528 | splx(x); | |
| 1993/0527 | ||
| 1993/0528 | /* free queued blocks */ | |
| 1993/0804 | while(bfirst){ b = bfirst->next; free(bfirst); bfirst = b; | |
| 1993/0526 | } | |
| 1993/0528 | /* wake up readers/writers */ | |
| 1993/0804/sys/src/9/port/qio.c:91,96 – 1993/0811/sys/src/9/port/qio.c:91,106 (short | long) | ||
| 1993/0530 | Qflow= (1<<3), }; | |
| 1993/0811 | void poison(Block *b) { b->next = (void*)0xdeadbabe; b->rp = (void*)0xdeadbabe; b->wp = (void*)0xdeadbabe; b->lim = (void*)0xdeadbabe; b->base = (void*)0xdeadbabe; } | |
| 1993/0530 | /* | |
| 1993/0526 | * Manage interrupt level memory allocation. */ | |
| 1993/0804/sys/src/9/port/qio.c:298,306 – 1993/0811/sys/src/9/port/qio.c:308,317 | ||
| 1993/0528 | wakeup(&q->wr); /* discard the block if we're done with it */ | |
| 1993/0527 |
| |
| 1993/0811 | if((q->state & Qmsg) || len == n) { poison(b); | |
| 1993/0526 | ifree(b); | |
| 1993/0811 | } | |
| 1993/0526 | return len; } | |
| 1993/0804/sys/src/9/port/qio.c:447,454 – 1993/0811/sys/src/9/port/qio.c:458,467 | ||
| 1993/0528 | b->rp += n; | |
| 1993/0526 | ||
| 1993/0725 | /* free it or put what's left on the queue */ | |
| 1993/0528 |
| |
| 1993/0811 | if(b->rp >= b->wp || (q->state&Qmsg)) { poison(b); | |
| 1993/0528 | free(b); | |
| 1993/0811 | } | |
| 1993/0526 | else { x = splhi(); lock(q); | |
| 1993/0804/sys/src/9/port/qio.c:557,562 – 1993/0811/sys/src/9/port/qio.c:570,576 | ||
| 1993/0528 | /* free queued blocks */ | |
| 1993/0804 | while(bfirst){ b = bfirst->next; | |
| 1993/0811 | poison(bfirst); | |
| 1993/0804 | free(bfirst); bfirst = b; | |
| 1993/0526 | } | |
| 1993/0811/sys/src/9/port/qio.c:30,35 – 1993/0819/sys/src/9/port/qio.c:30,36 (short | long) | ||
| 1993/0526 | int have; int goal; int hist; | |
| 1993/0819 | int wanted; | |
| 1993/0526 | }; struct Arena | |
| 1993/0811/sys/src/9/port/qio.c:141,148 – 1993/0819/sys/src/9/port/qio.c:142,149 | ||
| 1993/0526 | * start giving blocks back to the general pool */ if(cl->have >= cl->goal){ | |
| 1993/0819 | cl->hist = ((cl->hist<<1) | 1) & 0xffff; if(cl->hist == 0xffff && cl->goal > 32) | |
| 1993/0526 | cl->goal--; continue; } else | |
| 1993/0811/sys/src/9/port/qio.c:149,159 – 1993/0819/sys/src/9/port/qio.c:150,165 | ||
| 1993/0526 | cl->hist <<= 1; /* | |
| 1993/0819 | * increase goal if we've been drained. | |
| 1993/0526 | */ | |
| 1993/0819 | if(cl->have == 0){ i = cl->goal>>2; if(cl->wanted > i) cl->goal += cl->wanted; else cl->goal += i; cl->wanted = 0; } | |
| 1993/0526 | first = 0; l = &first; | |
| 1993/0811/sys/src/9/port/qio.c:166,171 – 1993/0819/sys/src/9/port/qio.c:172,178 | ||
| 1993/0526 | *l = p; l = &p->next; } | |
| 1993/0819 | i -= x; | |
| 1993/0526 | if(first){ x = splhi(); lock(cl); | |
| 1993/0811/sys/src/9/port/qio.c:194,199 – 1993/0819/sys/src/9/port/qio.c:201,220 | ||
| 1993/0725 | kproc("ialloc", iallockproc, 0); | |
| 1993/0526 | } | |
| 1993/0819 | void ixsummary(void) { int pow; Chunkl *cl; print("size have/goal\n"); for(pow = Minpow; pow <= Maxpow; pow++){ cl = &arena.alloc[pow]; print("%d %d/%d\n", 1<<pow, cl->have, cl->goal); } print("\n"); } | |
| 1993/0526 | Block* iallocb(int size) { | |
| 1993/0811/sys/src/9/port/qio.c:209,215 – 1993/0819/sys/src/9/port/qio.c:230,238 | ||
| 1993/0526 | lock(cl); p = cl->first; | |
| 1993/0527 | if(p == 0){ | |
| 1993/0819 | cl->wanted++; | |
| 1993/0527 | unlock(cl); | |
| 1993/0819 | wakeup(&arena.r); | |
| 1993/0527 | return 0; | |
| 1993/0526 | } | |
| 1993/0527 | cl->have--; | |
| 1993/0819/sys/src/9/port/qio.c:70,75 – 1993/0908/sys/src/9/port/qio.c:70,76 (short | long) | ||
| 1993/0530 | int len; /* bytes in queue */ int limit; /* max bytes in queue */ int state; | |
| 1993/0908 | int eof; /* number of eofs read by user */ | |
| 1993/0530 | void (*kick)(void*); /* restart output */ void *arg; /* argument to kick */ | |
| 1993/0819/sys/src/9/port/qio.c:409,414 – 1993/0908/sys/src/9/port/qio.c:410,416 | ||
| 1993/0526 | q->arg = arg; | |
| 1993/0530 | q->state = msg ? Qmsg : 0; | |
| 1993/0601 | q->state |= Qstarve; | |
| 1993/0908 | q->eof = 0; | |
| 1993/0526 | return q; } | |
| 1993/0819/sys/src/9/port/qio.c:451,456 – 1993/0908/sys/src/9/port/qio.c:453,462 | ||
| 1993/0528 | if(q->state & Qclosed){ | |
| 1993/0527 | unlock(q); splx(x); | |
| 1993/0908 | poperror(); qunlock(&q->rlock); if(++q->eof > 3) error(Ehungup); | |
| 1993/0528 | return 0; | |
| 1993/0527 | } | |
| 1993/0819/sys/src/9/port/qio.c:632,637 – 1993/0908/sys/src/9/port/qio.c:638,644 | ||
| 1993/0528 | { q->state &= ~Qclosed; | |
| 1993/0601 | q->state |= Qstarve; | |
| 1993/0908 | q->eof = 0; | |
| 1993/0530 | } /* | |
| 1993/0908/sys/src/9/port/qio.c:154,162 – 1993/1102/sys/src/9/port/qio.c:154,162 (short | long) | ||
| 1993/0819 | * increase goal if we've been drained. | |
| 1993/0526 | */ | |
| 1993/0819 | if(cl->have == 0){ | |
| 1993/1102 | i = cl->goal>>1; | |
| 1993/0819 | if(cl->wanted > i) | |
| 1993/1102 | cl->goal += 2*cl->wanted; | |
| 1993/0819 | else cl->goal += i; cl->wanted = 0; | |
| 1993/0908/sys/src/9/port/qio.c:195,201 – 1993/1102/sys/src/9/port/qio.c:195,201 | ||
| 1993/0526 | for(pow = Minpow; pow <= Maxpow; pow++){ cl = &arena.alloc[pow]; | |
| 1993/1102 | cl->goal = Maxpow-pow + 16; | |
| 1993/0526 | } /* start garbage collector */ | |
| 1993/1102/sys/src/9/port/qio.c:365,371 – 1993/1103/sys/src/9/port/qio.c:365,371 (short | long) | ||
| 1993/0526 | b = iallocb(len); if(b == 0){ unlock(q); | |
| 1993/1103 | return -2; | |
| 1993/0526 | } | |
| 1993/0527 | memmove(b->wp, p, len); | |
| 1993/0526 | b->wp += len; | |
| 1993/1103/sys/src/9/port/qio.c:538,546 – 1993/1227/sys/src/9/port/qio.c:538,551 (short | long) | ||
| 1993/0601 | if(nowait) return len; | |
| 1993/0528 | qlock(&q->wlock); | |
| 1993/1227 | if(waserror()) { qunlock(&q->wlock); nexterror(); } | |
| 1993/0528 | q->state |= Qflow; sleep(&q->wr, qnotfull, q); qunlock(&q->wlock); | |
| 1993/1227 | poperror(); | |
| 1993/0526 | } | |
| 1993/0528 | x = splhi(); | |
| 1993/1227/sys/src/9/port/qio.c:79,84 – 1994/0208/sys/src/9/port/qio.c:79,87 (short | long) | ||
| 1993/0530 | Rendez rr; /* process waiting to read */ QLock wlock; /* mutex for writing processes */ Rendez wr; /* process waiting to write */ | |
| 1994/0208 | uchar *syncbuf; /* synchronous IO buffer */ int synclen; /* syncbuf length */ | |
| 1993/0530 | }; enum | |
| 1993/1227/sys/src/9/port/qio.c:188,204 – 1994/0208/sys/src/9/port/qio.c:191,220 | ||
| 1993/0526 | } void | |
| 1994/0208 | qinit(void) | |
| 1993/0526 | { int pow; Chunkl *cl; | |
| 1994/0208 | Chunk *p; | |
| 1993/0526 | ||
| 1994/0208 | /* start with a bunch of initial blocks */ | |
| 1993/0526 | for(pow = Minpow; pow <= Maxpow; pow++){ cl = &arena.alloc[pow]; | |
| 1993/1102 |
| |
| 1994/0208 | cl->goal = Maxpow-pow + 32; cl->first = 0; for(; cl->have < cl->goal; cl->have++){ p = malloc(1<<pow); p->next = cl->first; cl->first = p; } | |
| 1993/0526 | } | |
| 1994/0208 | } void iallocinit(void) { /* start garbage collector/creator */ | |
| 1993/0725 | kproc("ialloc", iallockproc, 0); | |
| 1993/0526 | } | |
| 1993/1227/sys/src/9/port/qio.c:216,230 – 1994/0208/sys/src/9/port/qio.c:232,250 | ||
| 1993/0819 | print("\n"); } | |
| 1994/0208 | /* * interrupt time allocation (round data base address to 64 bit boundary) */ | |
| 1993/0526 | Block* iallocb(int size) { int pow; | |
| 1994/0208 | ulong addr; | |
| 1993/0526 | Chunkl *cl; Chunk *p; Block *b; | |
| 1994/0208 | size += sizeof(Block) + 7; | |
| 1993/0804 | for(pow = Minpow; pow <= Maxpow; pow++){ | |
| 1993/0526 | if(size <= (1<<pow)){ cl = &arena.alloc[pow]; | |
| 1993/1227/sys/src/9/port/qio.c:239,250 – 1994/0208/sys/src/9/port/qio.c:259,273 | ||
| 1993/0527 | cl->have--; cl->first = p->next; | |
| 1993/0526 | unlock(cl); | |
| 1994/0208 | ||
| 1993/0526 | b = (Block *)p; | |
| 1993/0528 | memset(b, 0, sizeof(Block)); | |
| 1993/0526 |
| |
| 1994/0208 | addr = (ulong)b; addr = (addr + sizeof(Block) + 7) & ~7; b->base = (uchar*)addr; | |
| 1993/0804 | b->wp = b->base; b->rp = b->base; | |
| 1993/0526 |
| |
| 1994/0208 | b->lim = ((uchar*)b) + (1<<pow); | |
| 1993/0526 | return b; } | |
| 1993/0804 | } | |
| 1993/1227/sys/src/9/port/qio.c:268,288 – 1994/0208/sys/src/9/port/qio.c:291,315 | ||
| 1993/0526 | } /* | |
| 1994/0208 | * allocate queues and blocks (round data base address to 64 bit boundary) | |
| 1993/0526 | */ Block* allocb(int size) { Block *b; | |
| 1994/0208 | ulong addr; | |
| 1993/0526 |
| |
| 1994/0208 | size += sizeof(Block) + 7; b = malloc(size); | |
| 1993/0526 | if(b == 0) exhausted("Blocks"); | |
| 1994/0208 | addr = (ulong)b; addr = (addr + sizeof(Block) + 7) & ~7; b->base = (uchar*)addr; | |
| 1993/0804 | b->rp = b->base; b->wp = b->base; | |
| 1993/0526 |
| |
| 1994/0208 | b->lim = ((uchar*)b) + size; | |
| 1993/0527 | b->flag = 0; | |
| 1993/0526 | return b; | |
| 1993/1227/sys/src/9/port/qio.c:343,354 – 1994/0208/sys/src/9/port/qio.c:370,401 | ||
| 1993/0601 | qproduce(Queue *q, void *vp, int len) | |
| 1993/0526 | { Block *b; | |
| 1993/0528 |
| |
| 1994/0208 | int i, dowakeup; | |
| 1993/0601 | uchar *p = vp; | |
| 1993/0526 | ||
| 1993/0527 | /* sync with qread */ | |
| 1994/0208 | dowakeup = 0; | |
| 1993/0526 | lock(q); | |
| 1993/0527 | ||
| 1994/0208 | if(q->syncbuf){ /* synchronous communications, just copy into buffer */ if(len < q->synclen) q->synclen = len; i = q->synclen; memmove(q->syncbuf, p, i); q->syncbuf = 0; /* tell reader buffer is full */ len -= i; if(len <= 0 || (q->state & Qmsg)){ unlock(q); wakeup(&q->rr); return i; } /* queue anything that's left */ dowakeup = 1; p += i; } | |
| 1993/0526 | /* no waiting receivers, room in buffer? */ if(q->len >= q->limit){ unlock(q); | |
| 1993/1227/sys/src/9/port/qio.c:379,386 – 1994/0208/sys/src/9/port/qio.c:426,432 | ||
| 1993/0528 | if(q->state & Qstarve){ q->state &= ~Qstarve; dowakeup = 1; | |
| 1994/0208 | } | |
| 1993/0526 | unlock(q); | |
| 1993/0527 | ||
| 1993/0601 | if(dowakeup){ | |
| 1993/1227/sys/src/9/port/qio.c:416,421 – 1994/0208/sys/src/9/port/qio.c:462,475 | ||
| 1993/0526 | } static int | |
| 1994/0208 | filled(void *a) { Queue *q = a; return q->syncbuf == 0; } static int | |
| 1993/0528 | notempty(void *a) | |
| 1993/0526 | { | |
| 1993/0528 | Queue *q = a; | |
| 1993/1227/sys/src/9/port/qio.c:436,441 – 1994/0208/sys/src/9/port/qio.c:490,505 | ||
| 1993/0526 | qlock(&q->rlock); | |
| 1993/0527 | if(waserror()){ | |
| 1994/0208 | /* can't let go if the buffer is in use */ if(q->syncbuf){ qlock(&q->wlock); x = splhi(); lock(q); q->syncbuf = 0; unlock(q); splx(x); qunlock(&q->wlock); } | |
| 1993/0527 | qunlock(&q->rlock); nexterror(); } | |
| 1993/1227/sys/src/9/port/qio.c:460,469 – 1994/0208/sys/src/9/port/qio.c:524,546 | ||
| 1993/0528 | return 0; | |
| 1993/0527 | } | |
| 1993/0528 |
| |
| 1993/0526 |
| |
| 1993/0528 |
| |
| 1994/0208 | if(globalmem(vp)){ /* just let the writer fill the buffer directly */ q->synclen = len; q->syncbuf = vp; unlock(q); splx(x); sleep(&q->rr, filled, q); len = q->synclen; poperror(); qunlock(&q->rlock); return len; } else { q->state |= Qstarve; unlock(q); splx(x); sleep(&q->rr, notempty, q); } | |
| 1993/0526 | } | |
| 1993/0528 | /* remove a buffered block */ | |
| 1993/1227/sys/src/9/port/qio.c:490,497 – 1994/0208/sys/src/9/port/qio.c:567,573 | ||
| 1993/0811 | if(b->rp >= b->wp || (q->state&Qmsg)) { poison(b); | |
| 1993/0528 | free(b); | |
| 1993/0811 |
| |
| 1993/0526 |
| |
| 1994/0208 | } else { | |
| 1993/0526 | x = splhi(); lock(q); | |
| 1993/0528 | b->next = q->bfirst; | |
| 1993/1227/sys/src/9/port/qio.c:521,584 – 1994/0208/sys/src/9/port/qio.c:597,707 | ||
| 1993/0528 | /* * write to a queue. if no reader blocks are posted * queue the data. | |
| 1994/0208 | * * all copies should be outside of spl since they can fault. | |
| 1993/0528 | */ long | |
| 1993/0601 | qwrite(Queue *q, void *vp, int len, int nowait) | |
| 1993/0528 | { | |
| 1994/0208 | int n, sofar, x, dowakeup; | |
| 1993/0528 | Block *b; | |
| 1993/0601 | uchar *p = vp; | |
| 1993/0526 | ||
| 1993/0528 |
| |
| 1994/0208 | dowakeup = 0; | |
| 1993/0526 | ||
| 1993/0528 |
| |
| 1993/0601 |
| |
| 1993/0528 |
| |
| 1993/1227 |
| |
| 1994/0208 | if(waserror()){ qunlock(&q->wlock); nexterror(); }; qlock(&q->wlock); sofar = 0; if(q->syncbuf){ if(len < q->synclen) sofar = len; else sofar = q->synclen; memmove(q->syncbuf, p, sofar); q->synclen = sofar; q->syncbuf = 0; wakeup(&q->rr); if(len == sofar || (q->state & Qmsg)){ | |
| 1993/1227 | qunlock(&q->wlock); | |
| 1994/0208 | poperror(); return len; | |
| 1993/1227 | } | |
| 1993/0528 |
| |
| 1993/1227 |
| |
| 1993/0526 | } | |
| 1993/0528 |
| |
| 1994/0208 | do { n = len-sofar; if(n > 128*1024) n = 128*1024; | |
| 1993/0528 |
| |
| 1994/0208 | b = allocb(n); memmove(b->wp, p+sofar, n); b->wp += n; /* flow control */ while(!qnotfull(q)){ if(nowait){ free(b); qunlock(&q->wlock); poperror(); return len; } q->state |= Qflow; sleep(&q->wr, qnotfull, q); } x = splhi(); lock(q); if(q->state & Qclosed){ unlock(q); splx(x); error(Ehungup); } if(q->syncbuf){ /* we guessed wrong and did an extra copy */ if(n > q->synclen) n = q->synclen; memmove(q->syncbuf, b->rp, n); q->synclen = n; q->syncbuf = 0; dowakeup = 1; free(b); } else { /* we guessed right, queue it */ if(q->bfirst) q->blast->next = b; else q->bfirst = b; q->blast = b; q->len += n; if(q->state & Qstarve){ q->state &= ~Qstarve; dowakeup = 1; } } | |
| 1993/0527 | unlock(q); splx(x); | |
| 1993/0528 |
| |
| 1993/0527 |
| |
| 1993/0526 | ||
| 1993/0601 |
| |
| 1993/0526 |
| |
| 1994/0208 | if(dowakeup){ if(q->kick) (*q->kick)(q->arg); wakeup(&q->rr); } | |
| 1993/0528 |
| |
| 1993/0526 |
| |
| 1993/0528 |
| |
| 1994/0208 | sofar += n; } while(sofar < len && (q->state & Qmsg) == 0); | |
| 1993/0528 | ||
| 1993/0526 |
| |
| 1993/0601 |
| |
| 1993/0528 |
| |
| 1993/0601 |
| |
| 1993/0528 | ||
| 1994/0208 | qunlock(&q->wlock); poperror(); | |
| 1993/0526 | return len; } | |
| 1994/0208/sys/src/9/port/qio.c:591,597 – 1994/0215/sys/src/9/port/qio.c:591,597 (short | long) | ||
| 1993/0526 | { | |
| 1993/0528 | Queue *q = a; | |
| 1993/0526 | ||
| 1993/0528 |
| |
| 1994/0215 | return q->len < q->limit || (q->state & Qclosed); | |
| 1993/0528 | } | |
| 1993/0527 | ||
| 1993/0528 | /* | |
| 1994/0215/sys/src/9/port/qio.c:721,726 – 1994/0219/sys/src/9/port/qio.c:721,727 (short | long) | ||
| 1993/0528 | q->state |= Qclosed; bfirst = q->bfirst; q->bfirst = 0; | |
| 1994/0219 | q->len = 0; | |
| 1993/0528 | unlock(q); splx(x); | |
| 1993/0527 | ||
| 1994/0219/sys/src/9/port/qio.c:97,102 – 1994/0222/sys/src/9/port/qio.c:97,117 (short | long) | ||
| 1993/0530 | }; | |
| 1993/0811 | void | |
| 1994/0222 | checkb(Block *b, char *msg) { if(b->base > b->lim) panic("checkb 0 %s %lux %lux", msg, b->base, b->lim); if(b->rp < b->base) panic("checkb 1 %s %lux %lux", msg, b->base, b->rp); if(b->wp < b->base) panic("checkb 2 %s %lux %lux", msg, b->base, b->wp); if(b->rp > b->lim) panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim); if(b->wp > b->lim) panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim); } void | |
| 1993/0811 | poison(Block *b) { b->next = (void*)0xdeadbabe; | |
| 1994/0219/sys/src/9/port/qio.c:310,316 – 1994/0222/sys/src/9/port/qio.c:325,330 | ||
| 1993/0804 | b->rp = b->base; b->wp = b->base; | |
| 1994/0208 | b->lim = ((uchar*)b) + size; | |
| 1993/0527 |
| |
| 1993/0526 | return b; } | |
| 1994/0219/sys/src/9/port/qio.c:335,340 – 1994/0222/sys/src/9/port/qio.c:349,355 | ||
| 1993/0526 | unlock(q); return -1; } | |
| 1994/0222 | checkb(b, "qconsume 1"); | |
| 1993/0528 | ||
| 1993/0526 | n = BLEN(b); if(n < len) | |
| 1994/0219/sys/src/9/port/qio.c:342,349 – 1994/0222/sys/src/9/port/qio.c:357,363 | ||
| 1993/0526 | memmove(p, b->rp, len); | |
| 1993/0527 | if((q->state & Qmsg) || len == n) | |
| 1993/0526 | q->bfirst = b->next; | |
| 1994/0222 | b->rp += len; | |
| 1993/0526 | q->len -= len; | |
| 1993/0528 | /* if writer flow controlled, restart */ | |
| 1994/0219/sys/src/9/port/qio.c:358,363 – 1994/0222/sys/src/9/port/qio.c:372,378 | ||
| 1993/0528 | if(dowakeup) wakeup(&q->wr); | |
| 1994/0222 | checkb(b, "qconsume 2"); | |
| 1993/0528 | /* discard the block if we're done with it */ | |
| 1993/0811 | if((q->state & Qmsg) || len == n) { poison(b); | |
| 1994/0219/sys/src/9/port/qio.c:403,428 – 1994/0222/sys/src/9/port/qio.c:418,438 | ||
| 1993/0526 | } /* save in buffer */ | |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/1103 |
| |
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1994/0222 | b = iallocb(len); if(b == 0){ unlock(q); return -2; | |
| 1993/0526 | } | |
| 1994/0222 | memmove(b->wp, p, len); b->wp += len; if(q->bfirst) q->blast->next = b; else q->bfirst = b; q->blast = b; | |
| 1993/0526 | q->len += len; | |
| 1994/0222 | checkb(b, "qproduce"); | |
| 1993/0528 | if(q->state & Qstarve){ q->state &= ~Qstarve; dowakeup = 1; | |
| 1994/0219/sys/src/9/port/qio.c:542,547 – 1994/0222/sys/src/9/port/qio.c:552,558 | ||
| 1994/0208 | sleep(&q->rr, notempty, q); } | |
| 1993/0526 | } | |
| 1994/0222 | checkb(b, "qread 1"); | |
| 1993/0526 | ||
| 1993/0528 | /* remove a buffered block */ q->bfirst = b->next; | |
| 1994/0219/sys/src/9/port/qio.c:563,568 – 1994/0222/sys/src/9/port/qio.c:574,580 | ||
| 1993/0528 | memmove(p, b->rp, n); b->rp += n; | |
| 1993/0526 | ||
| 1994/0222 | checkb(b, "qread 2"); | |
| 1993/0725 | /* free it or put what's left on the queue */ | |
| 1993/0811 | if(b->rp >= b->wp || (q->state&Qmsg)) { poison(b); | |
| 1994/0219/sys/src/9/port/qio.c:663,669 – 1994/0222/sys/src/9/port/qio.c:675,682 | ||
| 1994/0208 | splx(x); error(Ehungup); } | |
| 1994/0222 | checkb(b, "qwrite"); | |
| 1994/0208 | if(q->syncbuf){ /* we guessed wrong and did an extra copy */ if(n > q->synclen) | |
| 1994/0222/sys/src/9/port/qio.c:45,63 – 1994/0306/sys/src/9/port/qio.c:45,51 (short | long) | ||
| 1993/0526 | /* | |
| 1993/0530 | * IO queues */ | |
| 1994/0306/sys/src/9/port/qio.c:46,52 – 1994/0309/sys/src/9/port/qio.c:46,51 (short | long) | ||
| 1993/0530 | * IO queues */ typedef struct Queue Queue; | |
| 1994/0309/sys/src/9/port/qio.c:369,374 – 1994/0311/sys/src/9/port/qio.c:369,441 (short | long) | ||
| 1993/0526 | } | |
| 1993/0528 | int | |
| 1994/0311 | qpass(Queue *q, Block *b) { int s, i, len; int dowakeup; s = splhi(); len = BLEN(b); /* sync with qread */ dowakeup = 0; lock(q); if(q->syncbuf){ /* synchronous communications, just copy into buffer */ if(len < q->synclen) q->synclen = len; i = q->synclen; memmove(q->syncbuf, b->rp, i); q->syncbuf = 0; /* tell reader buffer is full */ len -= i; if(len <= 0 || (q->state & Qmsg)){ unlock(q); wakeup(&q->rr); ifree(b); splx(s); return i; } /* queue anything that's left */ dowakeup = 1; b->rp += i; } /* no waiting receivers, room in buffer? */ if(q->len >= q->limit){ unlock(q); splx(s); return -1; } /* save in buffer */ if(q->bfirst) q->blast->next = b; else q->bfirst = b; q->blast = b; q->len += len; checkb(b, "qproduce"); if(q->state & Qstarve){ q->state &= ~Qstarve; dowakeup = 1; } unlock(q); if(dowakeup){ if(q->kick) (*q->kick)(q->arg); wakeup(&q->rr); } splx(s); return len; } int | |
| 1993/0601 | qproduce(Queue *q, void *vp, int len) | |
| 1993/0526 | { Block *b; | |
| 1994/0311/sys/src/9/port/qio.c:371,378 – 1994/0312/sys/src/9/port/qio.c:371,377 (short | long) | ||
| 1993/0528 | int | |
| 1994/0311 | qpass(Queue *q, Block *b) { | |
| 1994/0312 | int s, i, len, dowakeup; | |
| 1994/0311 | s = splhi(); | |
| 1994/0311/sys/src/9/port/qio.c:417,423 – 1994/0312/sys/src/9/port/qio.c:416,422 | ||
| 1994/0311 | q->bfirst = b; q->blast = b; q->len += len; | |
| 1994/0312 | checkb(b, "qpass"); | |
| 1994/0311 | if(q->state & Qstarve){ q->state &= ~Qstarve; | |
| 1994/0312/sys/src/9/port/qio.c:15,21 – 1994/0319/sys/src/9/port/qio.c:15,21 (short | long) | ||
| 1993/0526 | enum { Minpow= 7, | |
| 1994/0319 | Maxpow= 16, | |
| 1993/0526 | }; struct Chunk | |
| 1994/0312/sys/src/9/port/qio.c:196,211 – 1994/0319/sys/src/9/port/qio.c:196,216 | ||
| 1994/0208 | qinit(void) | |
| 1993/0526 | { int pow; | |
| 1994/0208 | Chunk *p; | |
| 1994/0319 | Chunkl *cl; | |
| 1993/0526 | ||
| 1994/0208 | /* start with a bunch of initial blocks */ | |
| 1993/0526 | for(pow = Minpow; pow <= Maxpow; pow++){ cl = &arena.alloc[pow]; | |
| 1994/0208 |
| |
| 1994/0319 | cl->goal = 0; if(pow < 12) cl->goal = Maxpow-pow + 32; | |
| 1994/0208 | cl->first = 0; for(; cl->have < cl->goal; cl->have++){ p = malloc(1<<pow); | |
| 1994/0319 | if(p == 0) panic("qinit"); | |
| 1994/0208 | p->next = cl->first; cl->first = p; } | |
| 1994/0319/sys/src/9/port/qio.c:165,170 – 1994/0320/sys/src/9/port/qio.c:165,172 (short | long) | ||
| 1993/0819 | else cl->goal += i; cl->wanted = 0; | |
| 1994/0320 | if(cl->goal > 5000) cl->goal = 5000; | |
| 1993/0819 | } | |
| 1993/0526 | first = 0; | |
| 1994/0319/sys/src/9/port/qio.c:202,211 – 1994/0320/sys/src/9/port/qio.c:204,212 | ||
| 1994/0208 | /* start with a bunch of initial blocks */ | |
| 1993/0526 | for(pow = Minpow; pow <= Maxpow; pow++){ cl = &arena.alloc[pow]; | |
| 1994/0319 |
| |
| 1994/0320 | cl->goal = 4; | |
| 1994/0319 | if(pow < 12) cl->goal = Maxpow-pow + 32; | |
| 1994/0208 | cl->first = 0; for(; cl->have < cl->goal; cl->have++){ p = malloc(1<<pow); | |
| 1994/0319/sys/src/9/port/qio.c:397,403 – 1994/0320/sys/src/9/port/qio.c:398,404 | ||
| 1994/0311 | if(len <= 0 || (q->state & Qmsg)){ unlock(q); wakeup(&q->rr); | |
| 1994/0320 | free(b); | |
| 1994/0311 | splx(s); return i; } | |
| 1994/0320/sys/src/9/port/qio.c:5,47 – 1994/0321/sys/src/9/port/qio.c:5,28 (short | long) | ||
| 1993/0526 | #include "fns.h" #include "../port/error.h" | |
| 1993/0530 |
| |
| 1993/0526 |
| |
| 1994/0319 |
| |
| 1994/0321 | Minpow = 7, Maxpow = 16, | |
| 1993/0526 | }; | |
| 1994/0321 | struct Pool | |
| 1993/0526 | { | |
| 1994/0321 | Block* list; int had; | |
| 1993/0526 | int have; | |
| 1994/0321 | int want; | |
| 1993/0526 | int goal; | |
| 1993/0819 |
| |
| 1993/0526 | }; | |
| 1994/0321 | Pool pool[Maxpow]; | |
| 1993/0526 |
| |
| 1993/0530 | * IO queues */ | |
| 1994/0320/sys/src/9/port/qio.c:51,58 – 1994/0321/sys/src/9/port/qio.c:32,39 | ||
| 1993/0530 | { Lock; | |
| 1994/0321 | Block* bfirst; /* buffer */ Block* blast; | |
| 1993/0530 | int len; /* bytes in queue */ int limit; /* max bytes in queue */ | |
| 1994/0320/sys/src/9/port/qio.c:60,66 – 1994/0321/sys/src/9/port/qio.c:41,47 | ||
| 1993/0908 | int eof; /* number of eofs read by user */ | |
| 1993/0530 | void (*kick)(void*); /* restart output */ | |
| 1994/0321 | void* arg; /* argument to kick */ | |
| 1993/0530 | QLock rlock; /* mutex for reading processes */ Rendez rr; /* process waiting to read */ | |
| 1994/0320/sys/src/9/port/qio.c:67,73 – 1994/0321/sys/src/9/port/qio.c:48,54 | ||
| 1993/0530 | QLock wlock; /* mutex for writing processes */ Rendez wr; /* process waiting to write */ | |
| 1994/0208 |
| |
| 1994/0321 | uchar* syncbuf; /* synchronous IO buffer */ | |
| 1994/0208 | int synclen; /* syncbuf length */ | |
| 1993/0530 | }; | |
| 1994/0320/sys/src/9/port/qio.c:112,196 – 1994/0321/sys/src/9/port/qio.c:93,150 | ||
| 1993/0526 | * Manage interrupt level memory allocation. */ static void | |
| 1994/0321 | iallocmgr(void) | |
| 1993/0526 | { | |
| 1994/0321 | int pow; | |
| 1993/0526 |
| |
| 1994/0321 | attention = 0; spllo(); for(pow = Minpow; pow <= Maxpow; pow++) { p = &pool[pow]; | |
| 1993/0526 |
| |
| 1993/0804 |
| |
| 1993/0526 |
| |
| 1993/0804 |
| |
| 1993/0526 |
| |
| 1994/0321 | /* Low pass filter */ delta = 3 * (p->had - p->have); delta = (delta/2) + p->want; | |
| 1993/0526 |
| |
| 1993/0819 |
| |
| 1993/0526 |
| |
| 1993/0819 |
| |
| 1993/0526 |
| |
| 1993/0819 |
| |
| 1993/1102 |
| |
| 1993/0819 |
| |
| 1993/1102 |
| |
| 1993/0819 |
| |
| 1994/0320 |
| |
| 1994/0321 | if(delta < 0) { lock(p); p->have -= delta; bp = p->list; while(delta--) p->list = p->list->next; unlock(p); spllo(); while(bp) { next = bp->next; free(bp); bp = next; | |
| 1993/0819 | } | |
| 1993/0526 |
| |
| 1993/0804 |
| |
| 1993/0526 |
| |
| 1994/0321 | splhi(); } else { spllo(); n = 0; s = sizeof(Block)+(1<<pow)+(BY2V-1); while(delta--) { b = malloc(s); if(b == 0) | |
| 1993/0526 | break; | |
| 1993/0804 | ||
| 1993/0526 |
| |
| 1994/0321 | addr = (ulong)b; addr = (addr+sizeof(Block)+(BY2V-1)) & ~(BY2V-1); b->base = (uchar*)addr; b->rp = b->base; b->wp = b->base; b->lim = ((uchar*)b)+size; b->size = pow; n++; | |
| 1993/0526 | } | |
| 1993/0819 |
| |
| 1993/0526 |
| |
| 1994/0321 | spllo(); lock(p); unlock(p); splhi(); | |
| 1993/0526 | } | |
| 1994/0321 | p->had = p->have; p->want = 0; | |
| 1993/0526 | } } | |
| 1994/0320/sys/src/9/port/qio.c:197,301 – 1994/0321/sys/src/9/port/qio.c:151,221 | ||
| 1993/0526 | void | |
| 1994/0208 | qinit(void) | |
| 1993/0526 | { | |
| 1994/0208 |
| |
| 1994/0319 |
| |
| 1993/0526 | ||
| 1994/0208 |
| |
| 1993/0526 |
| |
| 1994/0320 |
| |
| 1994/0319 |
| |
| 1994/0208 |
| |
| 1994/0319 |
| |
| 1994/0208 |
| |
| 1993/0526 |
| |
| 1994/0208 | } void | |
| 1993/0725 |
| |
| 1993/0526 |
| |
| 1993/0819 |
| |
| 1994/0321 | Pool *p; | |
| 1993/0819 | print("size have/goal\n"); for(pow = Minpow; pow <= Maxpow; pow++){ | |
| 1994/0321 | cl = &pool[pow]; print("%d %d/%d\n", 1<<pow, p->have, p->goal); | |
| 1993/0819 | } print("\n"); } | |
| 1994/0208 | /* | |
| 1994/0321 | * interrupt time allocation | |
| 1994/0208 | */ | |
| 1993/0526 | Block* iallocb(int size) { int pow; | |
| 1994/0208 |
| |
| 1993/0526 |
| |
| 1994/0321 | Block *bp; | |
| 1993/0526 | ||
| 1994/0208 |
| |
| 1993/0804 |
| |
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0819 |
| |
| 1993/0527 |
| |
| 1993/0819 |
| |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1993/0527 |
| |
| 1993/0526 |
| |
| 1994/0321 | for(pow = Minpow; pow < Maxpow; pow++) if(size >= (1<<pow)) break; | |
| 1994/0208 | ||
| 1993/0526 |
| |
| 1993/0528 |
| |
| 1994/0208 |
| |
| 1993/0804 |
| |
| 1994/0208 |
| |
| 1993/0526 |
| |
| 1994/0321 | if(pow == Maxpow) return 0; p = &pool[pow]; lock(p); bp = p->list; if(p == 0) { p->want++; unlock(p); if(attention == 0) { attention++; newcallback(iallocmgr); | |
| 1993/0526 | } | |
| 1994/0321 | return 0; | |
| 1993/0804 | } | |
| 1993/0526 |
| |
| 1994/0321 | p->have--; p->list = bp->next; unlock(p); bp->wp = b->base; bp->rp = b->base; bp->list = 0; bp->next = 0; return bp; | |
| 1993/0526 | } void | |
| 1994/0321 | ifreeb(Block *bp) | |
| 1993/0526 | { | |
| 1994/0321 | Pool *p; | |
| 1993/0526 |
| |
| 1994/0321 | p = &pool[bp->size]; lock(p); bp->next = p->list; p->list = bp; p->have++; unlock(p); | |
| 1993/0526 | } /* | |
| Too many diffs (26 > 25). Stopping. | ||