void waitforkick(Round *r) { int n; qlock(&r->lock); r->last = r->current; assert(r->current+1 == r->next); rwakeupall(&r->finish); while(!r->doanother) rsleep(&r->start); n = r->next++; r->current = n; r->doanother = 0; qunlock(&r->lock); }
void unbreak(Proc *p) { int b; qlock(&broken); for(b=0; b < broken.n; b++) if(broken.p[b] == p) { broken.n--; memmove(&broken.p[b], &broken.p[b+1], sizeof(Proc*)*(NBROKEN-(b+1))); ready(p); break; } qunlock(&broken); }
void putbuf(Iobuf *p) { if(canqlock(p)) print("buffer not locked %Z(%lld)\n", p->dev, (Wideoff)p->addr); if(p->flags & Bimm) { if(!(p->flags & Bmod)) print("imm and no mod %Z(%lld)\n", p->dev, (Wideoff)p->addr); if(!devwrite(p->dev, p->addr, p->iobuf)) p->flags &= ~(Bmod|Bimm); } iobufunmap(p); qunlock(p); }
/* * main filesystem server loop. * entered by many processes. * they wait for message buffers and * then process them. */ void serve(void *) { int i; Chan *cp; Msgbuf *mb; for (;;) { qlock(&reflock); /* read 9P request from a network input process */ mb = fs_recv(serveq, 0); assert(mb->magic == Mbmagic); /* fs kernel sets chan in /sys/src/fs/ip/il.c:/^getchan */ cp = mb->chan; if (cp == nil) panic("serve: nil mb->chan"); rlock(&cp->reflock); qunlock(&reflock); rlock(&mainlock); if (mb->data == nil) panic("serve: nil mb->data"); /* better sniffing code in /sys/src/cmd/disk/kfs/9p12.c */ if(cp->protocol == nil){ /* do we recognise the protocol in this packet? */ /* better sniffing code: /sys/src/cmd/disk/kfs/9p12.c */ for(i = 0; fsprotocol[i] != nil; i++) if(fsprotocol[i](mb) != 0) { cp->protocol = fsprotocol[i]; break; } if(cp->protocol == nil){ print("no protocol for message\n"); for(i = 0; i < 12; i++) print(" %2.2X", mb->data[i]); print("\n"); } } else /* process the request, generate an answer and reply */ cp->protocol(mb); mbfree(mb); runlock(&mainlock); runlock(&cp->reflock); } }
/* * allocate rest of mem * for io buffers. */ #define HWIDTH 5 /* buffers per hash */ void iobufinit(void) { int32_t i; Iobuf *p, *q; Hiob *hp; i = conf.niobuf*RBUFSIZE; niob = i / (sizeof(Iobuf) + RBUFSIZE + sizeof(Hiob)/HWIDTH); nhiob = niob / HWIDTH; while(!prime(nhiob)) nhiob++; if(chat) print(" %ld buffers; %ld hashes\n", niob, nhiob); hiob = ialloc(nhiob * sizeof(Hiob)); hp = hiob; for(i=0; i<nhiob; i++) { lock(hp); unlock(hp); hp++; } p = ialloc(niob * sizeof(Iobuf)); hp = hiob; for(i=0; i<niob; i++) { qlock(p); qunlock(p); if(hp == hiob) hp = hiob + nhiob; hp--; q = hp->link; if(q) { p->fore = q; p->back = q->back; q->back = p; p->back->fore = p; } else { hp->link = p; p->fore = p; p->back = p; } p->dev = devnone; p->addr = -1; p->xiobuf = ialloc(RBUFSIZE); p->iobuf = (char*)-1; p++; } }
ulong procalarm(ulong time) { Proc **l, *f; ulong when, old; if(up->alarm) old = tk2ms(up->alarm - MACHP(0)->ticks); else old = 0; if(time == 0) { up->alarm = 0; return old; } when = ms2tk(time)+MACHP(0)->ticks; qlock(&alarms); l = &alarms.head; for(f = *l; f; f = f->palarm) { if(up == f){ *l = f->palarm; break; } l = &f->palarm; } up->palarm = 0; if(alarms.head) { l = &alarms.head; for(f = *l; f; f = f->palarm) { if(f->alarm > when) { up->palarm = f; *l = up; goto done; } l = &f->palarm; } *l = up; } else alarms.head = up; done: up->alarm = when; qunlock(&alarms); return old; }
static void pageouttext(int pgszi, int color) { Proc *p; Pgsza *pa; int i, n, np, x; Segment *s; int prepaged; USED(color); pa = &pga.pgsza[pgszi]; n = x = 0; prepaged = 0; /* * Try first to steal text pages from non-prepaged processes, * then from anyone. */ Again: do{ if((p = psincref(x)) == nil) break; np = 0; if(p->prepagemem == 0 || prepaged != 0) if(p->state != Dead && p->noswap == 0 && canqlock(&p->seglock)){ for(i = 0; i < NSEG; i++){ if((s = p->seg[i]) == nil) continue; if((s->type&SG_TYPE) == SG_TEXT) np = pageout(p, s); } qunlock(&p->seglock); } /* * else process dead or locked or changing its segments */ psdecref(p); n += np; if(np > 0) DBG("pager: %d from proc #%d %#p\n", np, x, p); x++; }while(pa->freecount < Minpages); if(pa->freecount < Minpages && prepaged++ == 0) goto Again; }
/* * always called with cp->flock locked */ File* newfp(Chan *cp) { File *f, *e; retry: lock(&suballoc.flock); f = suballoc.ffree; if(f != nil){ suballoc.ffree = f->list; unlock(&suballoc.flock); f->list = 0; f->cp = cp; f->next = cp->flist; f->wpath = 0; f->tlock = 0; f->dslot = 0; f->doffset = 0; f->uid = 0; f->cuid = 0; cp->flist = f; return f; } unlock(&suballoc.flock); if(conf.nfile > Fmax){ print("%d: out of files\n", cp->chan); return 0; } /* * create a few new files */ f = malloc(Finc*sizeof(*f)); memset(f, 0, Finc*sizeof(*f)); lock(&suballoc.flock); for(e = f+Finc; f < e; f++){ qlock(f); qunlock(f); f->list = suballoc.ffree; suballoc.ffree = f; } conf.nfile += Finc; unlock(&suballoc.flock); goto retry; }
static Chan * cecattach(char *spec) { Chan *c; static QLock q; static int inited; qlock(&q); if(inited == 0){ kproc("cectimer", cectimer, nil); inited++; } qunlock(&q); c = devattach(L'©', spec); c->qid.path = Qdir; return c; }
static Walkqid* loopbackwalk(Chan *c, Chan *nc, char **name, int nname) { Walkqid *wq; Loop *lb; wq = devwalk(c, nc, name, nname, nil, 0, loopbackgen); if(wq != nil && wq->clone != nil && wq->clone != c){ lb = c->aux; qlock(lb); lb->ref++; if((c->flag & COPEN) && TYPE(c->qid.path) == Qdata) lb->link[ID(c->qid.path)].ref++; qunlock(lb); } return wq; }
void addbroken(Proc *p) { qlock(&broken); if(broken.n == NBROKEN) { ready(broken.p[0]); memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1)); --broken.n; } broken.p[broken.n++] = p; qunlock(&broken); edfstop(up); p->state = Broken; p->psstate = nil; sched(); }
void usbfsdirdump(void) { int i; qlock(&fslck); fprint(2, "%s: fs list: (%d used %d total)\n", argv0, fsused, nfs); for(i = 1; i < nfs; i++) if(fs[i] != nil) { if(fs[i]->dev != nil) fprint(2, "%s\t%s dev %#p refs %ld\n", argv0, fs[i]->name, fs[i]->dev, fs[i]->dev->Ref.ref); else fprint(2, "%s:\t%s\n", argv0, fs[i]->name); } qunlock(&fslck); }
static void aoeinit(void) { static int init; static QLock l; if(!canqlock(&l)) return; if(init == 0){ fmtinstall(L'æ', fmtæ); events.rp = events.wp = events.buf; kproc("aoesweep", aoesweepproc, nil); aoecfg(); init = 1; } qunlock(&l); }
static int32_t unionread(Chan *c, void *va, int32_t n) { Proc *up = externup(); int i; int32_t nr; Mhead *mh; Mount *mount; qlock(&c->umqlock); mh = c->umh; rlock(&mh->lock); mount = mh->mount; /* bring mount in sync with c->uri and c->umc */ for(i = 0; mount != nil && i < c->uri; i++) mount = mount->next; nr = 0; while(mount != nil){ /* Error causes component of union to be skipped */ if(mount->to && !waserror()){ if(c->umc == nil){ c->umc = cclone(mount->to); c->umc = c->umc->dev->open(c->umc, OREAD); } nr = c->umc->dev->read(c->umc, va, n, c->umc->offset); c->umc->offset += nr; poperror(); } if(nr > 0) break; /* Advance to next element */ c->uri++; if(c->umc){ cclose(c->umc); c->umc = nil; } mount = mount->next; } runlock(&mh->lock); qunlock(&c->umqlock); return nr; }
/* called from icmp(v6) for unreachable hosts, time exceeded, etc. */ void espadvise(Proto *esp, Block *bp, char *msg) { Conv *c; Versdep vers; getverslens(pktipvers(esp->f, &bp), &vers); getpktspiaddrs(bp->rp, &vers); qlock(esp); c = convlookup(esp, vers.spi); if(c != nil) { qhangup(c->rq, msg); qhangup(c->wq, msg); } qunlock(esp); freeblist(bp); }
int sendq(Queue *q, void *p) { Qel *e; e = emalloc(sizeof(Qel)); qlock(&q->lk); e->p = p; e->next = nil; if(q->head == nil) q->head = e; else q->tail->next = e; q->tail = e; rwakeup(&q->r); qunlock(&q->lk); return 0; }
int cursoron(int dolock) { int retry; if (dolock) lock(&cursor); if (canqlock(&drawlock)) { retry = 0; swcursorhide(); swcursordraw(); qunlock(&drawlock); } else retry = 1; if (dolock) unlock(&cursor); return retry; }
static void rudpstartackproc(Proto *rudp) { Rudppriv *rpriv; char kpname[KNAMELEN]; rpriv = rudp->priv; if(rpriv->ackprocstarted == 0){ qlock(&rpriv->apl); if(rpriv->ackprocstarted == 0){ snprint(kpname, sizeof kpname, "#I%drudpack", rudp->f->dev); kproc(kpname, relackproc, rudp); rpriv->ackprocstarted = 1; } qunlock(&rpriv->apl); } }
/* * wire this proc to a machine */ void procwired(Proc *p, int bm) { Mach *m = machp(); Proc *pp; int i; char nwired[MACHMAX]; Mach *wm; if(bm < 0){ /* pick a machine to wire to */ memset(nwired, 0, sizeof(nwired)); p->wired = 0; for(i=0; (pp = psincref(i)) != nil; i++){ wm = pp->wired; if(wm && pp->pid) nwired[wm->machno]++; psdecref(pp); } bm = 0; for(i=0; i<sys->nmach; i++) if(nwired[i] < nwired[bm]) bm = i; } else { /* use the virtual machine requested */ bm = bm % sys->nmach; } p->wired = sys->machptr[bm]; p->mp = p->wired; /* * adjust our color to the new domain. */ if(m->externup == nil || p != m->externup) return; m->externup->color = corecolor(m->externup->mp->machno); qlock(&m->externup->seglock); for(i = 0; i < NSEG; i++) if(m->externup->seg[i]) m->externup->seg[i]->color = m->externup->color; qunlock(&m->externup->seglock); }
static void pipeclose(struct chan *c) { Pipe *p; p = c->aux; qlock(&p->qlock); if (c->flag & COPEN) { /* * closing either side hangs up the stream */ switch (NETTYPE(c->qid.path)) { case Qdata0: p->qref[0]--; if (p->qref[0] == 0) { qhangup(p->q[1], 0); qclose(p->q[0]); } break; case Qdata1: p->qref[1]--; if (p->qref[1] == 0) { qhangup(p->q[0], 0); qclose(p->q[1]); } break; } } /* * if both sides are closed, they are reusable */ if (p->qref[0] == 0 && p->qref[1] == 0) { qreopen(p->q[0]); qreopen(p->q[1]); } qunlock(&p->qlock); /* * free the structure on last close */ kref_put(&p->ref); }
void putseg(Segment *s) { Pte **pp, **emap; Image *i; if(s == 0) return; i = s->image; if(i != 0) { lock(i); lock(s); if(i->s == s && s->ref == 1) i->s = 0; unlock(i); } else lock(s); s->ref--; if(s->ref != 0) { unlock(s); return; } unlock(s); qlock(&s->lk); if(i) putimage(i); emap = &s->map[s->mapsize]; for(pp = s->map; pp < emap; pp++) if(*pp) freepte(s, *pp); qunlock(&s->lk); if(s->map != s->ssegmap) free(s->map); if(s->profile != 0) free(s->profile); free(s); }
void f_fstat(Chan *cp, Fcall *in, Fcall *ou) { File *f; Iobuf *p; Dentry *d; int i; if(CHAT(cp)) { fprint(2, "c_fstat %d\n", cp->chan); fprint(2, "\tfid = %d\n", in->fid); } p = 0; f = filep(cp, in->fid, 0); if(!f) { ou->err = Efid; goto out; } p = getbuf(f->fs->dev, f->addr, Brd); d = getdir(p, f->slot); if(d == 0) goto out; print("name = %.*s\n", NAMELEN, d->name); print("uid = %d; gid = %d; muid = %d\n", d->uid, d->gid, d->muid); print("size = %lld; qid = %llux/%lux\n", (Wideoff)d->size, (Wideoff)d->qid.path, d->qid.version); print("atime = %ld; mtime = %ld\n", d->atime, d->mtime); print("dblock ="); for(i=0; i<NDBLOCK; i++) print(" %lld", (Wideoff)d->dblock[i]); for (i = 0; i < NIBLOCK; i++) print("; iblocks[%d] = %lld", i, (Wideoff)d->iblocks[i]); print("\n\n"); out: if(p) putbuf(p); ou->fid = in->fid; if(f) qunlock(f); }
/* * read a clump of data * n is a hint of the size of the data, not including the header * make sure it won't run off the end, then return the number of bytes actually read */ uint32_t readarena(Arena *arena, uint64_t aa, uint8_t *buf, int32_t n) { DBlock *b; uint64_t a; uint32_t blocksize, off, m; int32_t nn; if(n == 0) return -1; qlock(&arena->lock); a = arena->size - arenadirsize(arena, arena->memstats.clumps); qunlock(&arena->lock); if(aa >= a){ seterr(EOk, "reading beyond arena clump storage: clumps=%d aa=%lld a=%lld -1 clumps=%lld\n", arena->memstats.clumps, aa, a, arena->size - arenadirsize(arena, arena->memstats.clumps - 1)); return -1; } if(aa + n > a) n = a - aa; blocksize = arena->blocksize; a = arena->base + aa; off = a & (blocksize - 1); a -= off; nn = 0; for(;;){ b = getdblock(arena->part, a, OREAD); if(b == nil) return -1; m = blocksize - off; if(m > n - nn) m = n - nn; memmove(&buf[nn], &b->data[off], m); putdblock(b); nn += m; if(nn == n) break; off = 0; a += blocksize; } return n; }
char * nbdgramlisten(NbName to, int (*deliver)(void *magic, NbDgram *s), void *magic) { Listen *l; char *e; nbnametablefind(to, 1); e = startlistener(); if (e) return e; l = nbemalloc(sizeof(Listen)); nbnamecpy(l->to, to); l->deliver = deliver; l->magic = magic; qlock(&listens); l->next = listens.head; listens.head = l; qunlock(&listens); return 0; }
void addbroken(Proc *p) { Mach *m = machp(); qlock(&broken); if(broken.n == NBROKEN) { ready(broken.p[0]); memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1)); --broken.n; } broken.p[broken.n++] = p; qunlock(&broken); stopac(); edfstop(m->externup); p->state = Broken; p->psstate = 0; sched(); }
void swcursorclock(void) { int x; if(!swenabled) return; if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers) return; x = splhi(); if(swenabled) if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers) if(canqlock(&drawlock)){ swcursorhide(); swcursordraw(); qunlock(&drawlock); } splx(x); }
void espadvise(Proto *esp, Block *bp, char *msg) { Esphdr *h; Conv *c; ulong spi; h = (Esphdr*)(bp->rp); spi = nhgets(h->espspi); qlock(esp); c = convlookup(esp, spi); if(c != nil) { qhangup(c->rq, msg); qhangup(c->wq, msg); } qunlock(esp); freeblist(bp); }
static long dsoaction(char** args, int nargs){ long r = 0; // Comprobar que no introdujo '/' if(nargs > 1) validname(args[1],0); // Bloqueo al introducir nuevo dispositivos qlock(&fichLock); if(strcmp(args[0],"+") == 0){ if(nargs > 3) r = dsoconcat(args,nargs); else{ qunlock(&fichLock); error("#Q: USO: + <dest> <origen1> ... <origenN>"); } }else if(strcmp(args[0],"p") == 0){ if(nargs == 5) r = dsopart(args,nargs); else{ qunlock(&fichLock); error("#Q: USO: p <dest> <offset> <size> <origen>"); } }else if(strcmp(args[0],"m") == 0){ if(nargs > 3) r = dsomirror(args,nargs); else{ qunlock(&fichLock); error("#Q: USO: m <dest> <origen1> ... <origenN>"); } }else if(strcmp(args[0],"i") == 0){ if(nargs > 3) r = dsointerl(args,nargs); else{ qunlock(&fichLock); error("#Q: USO: i <dest> <origen1> ... <origenN>"); } }else{ qunlock(&fichLock); error("#Q: Comando invalido"); } qunlock(&fichLock); return r; }
void killbig(char *why) { int i; Segment *s; ulong l, max; Proc *p, *ep, *kp; max = 0; kp = 0; ep = procalloc.arena+conf.nproc; for(p = procalloc.arena; p < ep; p++) { if(p->state == Dead || p->kp) continue; l = 0; for(i=1; i<NSEG; i++) { s = p->seg[i]; if(s != 0) l += s->top - s->base; } if(l > max && ((p->procmode&0222) || strcmp(eve, p->user)!=0)) { kp = p; max = l; } } print("%lud: %s killed: %s\n", kp->pid, kp->text, why); for(p = procalloc.arena; p < ep; p++) { if(p->state == Dead || p->kp) continue; if(p != kp && p->seg[BSEG] && p->seg[BSEG] == kp->seg[BSEG]) p->procctl = Proc_exitbig; } kp->procctl = Proc_exitbig; for(i = 0; i < NSEG; i++) { s = kp->seg[i]; if(s != 0 && canqlock(&s->lk)) { mfreeseg(s, s->base, (s->top - s->base)/BY2PG); qunlock(&s->lk); } } }
void sdadddevs(SDev *sdev) { int i, j, id; SDev *next; for(; sdev; sdev=next){ next = sdev->next; sdev->unit = (SDunit**)malloc(sdev->nunit * sizeof(SDunit*)); sdev->unitflg = (int*)malloc(sdev->nunit * sizeof(int)); if(sdev->unit == nil || sdev->unitflg == nil){ print("sdadddevs: out of memory\n"); giveup: free(sdev->unit); free(sdev->unitflg); if(sdev->ifc->clear) sdev->ifc->clear(sdev); free(sdev); continue; } id = sdindex(sdev->idno); if(id == -1){ print("sdadddevs: bad id number %d (%C)\n", id, id); goto giveup; } qlock(&devslock); for(i=0; i<nelem(devs); i++){ if(devs[j = (id+i)%nelem(devs)] == nil){ sdev->idno = devletters[j]; devs[j] = sdev; snprint(sdev->name, sizeof sdev->name, "sd%c", devletters[j]); break; } } qunlock(&devslock); if(i == nelem(devs)){ print("sdadddevs: out of device letters\n"); goto giveup; } } }