| plan 9 kernel history: overview | file list | diff list |
1993/0528/port/qio.c (diff list | history)
| 1993/0527/sys/src/9/port/qio.c:150,159 – 1993/0528/sys/src/9/port/qio.c:150,159 (short | long | prev | next) | ||
| 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 | } | |