ulong procpagecount(Proc *p) { Segment *s; ulong pages; int i; eqlock(&p->seglock); if(waserror()){ qunlock(&p->seglock); nexterror(); } pages = 0; for(i=0; i<NSEG; i++){ if((s = p->seg[i]) != nil){ eqlock(s); pages += mcountseg(s); qunlock(s); } } qunlock(&p->seglock); poperror(); return pages; }
static long audioread(Chan *c, void *a, long n, vlong off) { Audiochan *ac; Audio *adev; long (*fn)(Audio *, void *, long, vlong); ac = c->aux; adev = ac->adev; fn = nil; switch((ulong)c->qid.path){ case Qdir: audiodir[Qaudio].length = adev->buffered ? adev->buffered(adev) : 0; return devdirread(c, a, n, audiodir, nelem(audiodir), devgen); case Qaudio: fn = adev->read; break; case Qaudiostat: fn = adev->status; break; case Qvolume: fn = adev->volread; break; } if(fn == nil) error(Egreg); eqlock(ac); if(waserror()){ qunlock(ac); nexterror(); } switch((ulong)c->qid.path){ case Qaudiostat: case Qvolume: /* generate the text on first read */ if(ac->data == nil || off == 0){ long l; ac->data = nil; l = fn(adev, ac->buf, sizeof(ac->buf)-1, 0); if(l < 0) l = 0; ac->buf[l] = 0; ac->data = ac->buf; } /* then serve all requests from buffer */ n = readstr(off, a, n, ac->data); break; default: n = fn(adev, a, n, off); } qunlock(ac); poperror(); return n; }
static void wpiattach(Ether *edev) { FWImage *fw; Ctlr *ctlr; char *err; ctlr = edev->ctlr; eqlock(ctlr); if(waserror()){ print("#l%d: %s\n", edev->ctlrno, up->errstr); if(ctlr->power) poweroff(ctlr); qunlock(ctlr); nexterror(); } if(ctlr->attached == 0){ if((csr32r(ctlr, Gpc) & RfKill) == 0) error("wifi disabled by switch"); if(ctlr->wifi == nil){ ctlr->wifi = wifiattach(edev, transmit); ctlr->wifi->rates = wpirates; } if(ctlr->fw == nil){ fw = readfirmware(); print("#l%d: firmware: %ux, size: %ux+%ux+%ux+%ux+%ux\n", edev->ctlrno, fw->version, fw->main.text.size, fw->main.data.size, fw->init.text.size, fw->init.data.size, fw->boot.text.size); ctlr->fw = fw; } if((err = reset(ctlr)) != nil) error(err); if((err = boot(ctlr)) != nil) error(err); ctlr->bcastnodeid = -1; ctlr->bssnodeid = -1; ctlr->channel = 1; ctlr->aid = 0; setoptions(edev); ctlr->attached = 1; kproc("wpirecover", wpirecover, edev); } qunlock(ctlr); poperror(); }
/* * get next block from a queue (up to a limit) */ Block* qbread(Queue *q, int len) { Block *b, *nb; int n; eqlock(&q->rlock); if(waserror()){ qunlock(&q->rlock); nexterror(); } ilock(q); switch(qwait(q)){ case 0: /* queue closed */ iunlock(q); qunlock(&q->rlock); poperror(); return nil; case -1: /* multiple reads on a closed queue */ iunlock(q); error(q->err); } /* if we get here, there's at least one block in the queue */ b = qremove(q); n = BLEN(b); /* split block if it's too big and this is not a message queue */ nb = b; if(n > len){ if((q->state&Qmsg) == 0){ n -= len; b = allocb(n); memmove(b->wp, nb->rp+len, n); b->wp += n; qputback(q, b); } nb->wp = nb->rp + len; } /* restart producer */ qwakeup_iunlock(q); poperror(); qunlock(&q->rlock); return nb; }
static long audiowrite(Chan *c, void *a, long n, vlong off) { Audiochan *ac; Audio *adev; long (*fn)(Audio *, void *, long, vlong); ac = c->aux; adev = ac->adev; fn = nil; switch((ulong)c->qid.path){ case Qaudio: fn = adev->write; break; case Qaudioctl: fn = adev->ctl; break; case Qvolume: fn = adev->volwrite; break; } if(fn == nil) error(Egreg); eqlock(ac); if(waserror()){ qunlock(ac); nexterror(); } switch((ulong)c->qid.path){ case Qaudioctl: case Qvolume: if(n >= sizeof(ac->buf)) error(Etoobig); /* copy data to audiochan buffer so it can be modified */ ac->data = nil; memmove(ac->buf, a, n); ac->buf[n] = 0; a = ac->buf; off = 0; } n = fn(adev, a, n, off); qunlock(ac); poperror(); return n; }
/* * flow control, wait for queue to get below the limit */ static void qflow(Queue *q) { for(;;){ if(q->noblock || qnotfull(q)) break; ilock(q); q->state |= Qflow; iunlock(q); eqlock(&q->wlock); if(waserror()){ qunlock(&q->wlock); nexterror(); } sleep(&q->wr, qnotfull, q); qunlock(&q->wlock); poperror(); } }
/* * read a queue. if no data is queued, post a Block * and wait on its Rendez. */ long qread(Queue *q, void *vp, int len) { Block *b, *first, **l; int m, n; eqlock(&q->rlock); if(waserror()){ qunlock(&q->rlock); nexterror(); } ilock(q); again: switch(qwait(q)){ case 0: /* queue closed */ iunlock(q); qunlock(&q->rlock); poperror(); return 0; case -1: /* multiple reads on a closed queue */ iunlock(q); error(q->err); } /* if we get here, there's at least one block in the queue */ if(q->state & Qcoalesce){ /* when coalescing, 0 length blocks just go away */ b = q->bfirst; m = BLEN(b); if(m <= 0){ freeb(qremove(q)); goto again; } /* grab the first block plus as many * following blocks as will partially * fit in the read. */ n = 0; l = &first; for(;;) { *l = qremove(q); l = &b->next; n += m; if(n >= len || (b = q->bfirst) == nil) break; m = BLEN(b); } } else { first = qremove(q); n = BLEN(first); } /* copy to user space outside of the ilock */ iunlock(q); b = bl2mem(vp, first, len); ilock(q); /* take care of any left over partial block */ if(b != nil){ n -= BLEN(b); if(q->state & Qmsg) freeb(b); else qputback(q, b); } /* restart producer */ qwakeup_iunlock(q); poperror(); qunlock(&q->rlock); return n; }