Proc* newproc(void) { Proc *p; lock(&procalloc); for(;;) { if(p = procalloc.free) break; unlock(&procalloc); resrcwait("no procs"); lock(&procalloc); } procalloc.free = p->qnext; unlock(&procalloc); p->type = Unknown; p->state = Scheding; p->pri = PriNormal; p->psstate = "New"; p->mach = 0; p->qnext = 0; p->fpstate = FPINIT; p->kp = 0; p->killed = 0; p->swipend = 0; p->mp = 0; p->movetime = 0; p->delaysched = 0; p->edf = nil; memset(&p->defenv, 0, sizeof(p->defenv)); p->env = &p->defenv; p->dbgreg = 0; kstrdup(&p->env->user, "*nouser"); p->env->errstr = p->env->errbuf0; p->env->syserrstr = p->env->errbuf1; p->pid = incref(&pidalloc); if(p->pid == 0) panic("pidalloc"); if(p->kstack == 0) p->kstack = smalloc(KSTACK); addprog(p); return p; }
Proc* psalloc(void) { Proc *p; lock(&procalloc); for(;;) { if(p = procalloc.free) break; unlock(&procalloc); resrcwait("no procs"); lock(&procalloc); } procalloc.free = p->qnext; procalloc.nproc++; unlock(&procalloc); return p; }
Proc* newproc(void) { char msg[64]; Proc *p; lock(&procalloc); for(;;) { if((p = procalloc.free) != nil) break; snprint(msg, sizeof msg, "no procs; %s forking", up != nil ? up->text: "kernel"); unlock(&procalloc); resrcwait(msg); lock(&procalloc); } procalloc.free = p->qnext; unlock(&procalloc); p->state = Scheding; p->psstate = "New"; p->mach = nil; p->eql = nil; p->qnext = nil; p->nchild = 0; p->nwait = 0; p->waitq = nil; p->parent = nil; p->pgrp = nil; p->egrp = nil; p->fgrp = nil; p->rgrp = nil; p->pdbg = nil; p->fpstate = FPinit; p->kp = 0; p->procctl = 0; p->syscalltrace = nil; p->notepending = 0; p->ureg = nil; p->privatemem = 0; p->noswap = 0; p->errstr = p->errbuf0; p->syserrstr = p->errbuf1; p->errbuf0[0] = '\0'; p->errbuf1[0] = '\0'; p->nlocks = 0; p->delaysched = 0; p->trace = 0; kstrdup(&p->user, "*nouser"); kstrdup(&p->text, "*notext"); kstrdup(&p->args, ""); p->nargs = 0; p->setargs = 0; memset(p->seg, 0, sizeof p->seg); p->parentpid = 0; p->noteid = pidalloc(p); if(p->kstack == nil) p->kstack = smalloc(KSTACK); /* sched params */ p->mp = nil; p->wired = nil; procpriority(p, PriNormal, 0); p->cpu = 0; p->lastupdate = MACHP(0)->ticks*Scaling; p->edf = nil; return p; }
Image* attachimage(int type, Chan *c, ulong base, ulong len) { Image *i, **l; lock(&imagealloc); /* * Search the image cache for remains of the text from a previous * or currently running incarnation */ for(i = ihash(c->qid.path); i; i = i->hash) { if(c->qid.path == i->qid.path) { lock(i); if(eqqid(c->qid, i->qid) && eqqid(c->mqid, i->mqid) && c->mchan == i->mchan && c->type == i->type) { goto found; } unlock(i); } } /* * imagereclaim dumps pages from the free list which are cached by image * structures. This should free some image structures. */ while(!(i = imagealloc.free)) { unlock(&imagealloc); imagereclaim(); if(!imagealloc.free){ freebroken(); /* can use the memory */ resrcwait("no image after reclaim"); } lock(&imagealloc); } imagealloc.free = i->next; lock(i); incref(c); c->flag &= ~CCACHE; i->c = c; i->type = c->type; i->qid = c->qid; i->mqid = c->mqid; i->mchan = c->mchan; l = &ihash(c->qid.path); i->hash = *l; *l = i; found: unlock(&imagealloc); if(i->s == 0) { i->ref++; if(waserror()) { unlock(i); putimage(i); nexterror(); } i->s = newseg(type, base, len); i->s->image = i; poperror(); } else incref(i->s); return i; }
static long sdrio(SDreq* r, void* a, long n) { char *errstr; int rv; void *data; SDunit *u; int (*f)(SDreq*); if(n >= SDmaxio || n < 0) error(Etoobig); u = r->unit; if(u->haversense && r->cmd[0] == 0x03){ u->haversense = 0; r->rlen = sizeof u->rsense; if(r->rlen > n) r->rlen = n; memmove(a, u->rsense, r->rlen); r->status = SDok; return r->rlen; } data = nil; while(n > 0 && (data = sdmalloc(n)) == nil){ if(!waserror()){ resrcwait("no memory for sdrio"); poperror(); } } if(waserror()){ sdfree(data); r->data = nil; nexterror(); } if(r->write && n > 0) memmove(data, a, n); r->data = data; r->dlen = n; if(r->proto == SData){ f = u->dev->ifc->ataio; errstr = Enoata; }else{ f = u->dev->ifc->rio; errstr = Enoscsi; } if(f == nil) error(errstr); rv = f(r); if(r->flags & SDvalidsense){ memmove(u->rsense, r->sense, sizeof u->rsense); u->haversense = 1; } if(rv != SDok) error(Eio); if(!r->write && r->rlen > 0) memmove(a, data, r->rlen); poperror(); sdfree(data); r->data = nil; return r->rlen; }
static long sdbio(Chan* c, int write, char* a, long len, uvlong off) { int nchange, hard, allocd, locked; long l; uchar *b; SDpart *pp; SDunit *unit; SDev *sdev; ulong max, nb, offset; uvlong bno; sdev = sdgetdev(DEV(c->qid)); if(sdev == nil){ decref(&sdev->r); error(Enonexist); } unit = sdev->unit[UNIT(c->qid)]; if(unit == nil) error(Enonexist); nchange = 0; qlock(&unit->ctl); while(waserror()){ /* notification of media change; go around again */ if(strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){ sdinitpart(unit); continue; } /* other errors; give up */ qunlock(&unit->ctl); decref(&sdev->r); nexterror(); } pp = &unit->part[PART(c->qid)]; if(unit->vers+pp->vers != c->qid.vers) error(Echange); /* * Check the request is within bounds. * Removeable drives are locked throughout the I/O * in case the media changes unexpectedly. * Non-removeable drives are not locked during the I/O * to allow the hardware to optimise if it can; this is * a little fast and loose. * It's assumed that non-removeable media parameters * (sectors, secsize) can't change once the drive has * been brought online. */ bno = (off/unit->secsize) + pp->start; nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno; max = SDmaxio/unit->secsize; if(nb > max) nb = max; if(bno+nb > pp->end) nb = pp->end - bno; if(bno >= pp->end || nb == 0){ if(write) error(Eio); qunlock(&unit->ctl); decref(&sdev->r); poperror(); return 0; } locked = (unit->inquiry[1] & 0x80) != 0; if(!locked){ qunlock(&unit->ctl); poperror(); } offset = off%unit->secsize; if(offset+len > nb*unit->secsize) len = nb*unit->secsize - offset; hard = offset || write && len%unit->secsize; if(iskaddr(a) && ((uintptr)a & (BY2PG-1))==0 && !hard) { b = (uchar*)a; allocd = 0; }else{ while((b = sdmalloc(nb*unit->secsize)) == nil){ if(!waserror()){ resrcwait("no memory for sdbio"); poperror(); } } allocd = 1; } if(waserror()){ if(allocd) sdfree(b); if(!locked) decref(&sdev->r); /* gadverdamme! */ nexterror(); } if(write){ if(hard){ l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); if(l < 0) error(Eio); if(l < (nb*unit->secsize)){ nb = l/unit->secsize; l = nb*unit->secsize - offset; if(len > l) len = l; } } if(allocd) memmove(b+offset, a, len); l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno); if(l < 0) error(Eio); if(l < offset) len = 0; else if(len > l - offset) len = l - offset; } else{ l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno); if(l < 0) error(Eio); if(l < offset) len = 0; else if(len > l - offset) len = l - offset; if(allocd) memmove(a, b+offset, len); } if(allocd) sdfree(b); poperror(); if(locked){ qunlock(&unit->ctl); poperror(); } decref(&sdev->r); return len; }
Proc* newproc(void) { char msg[64]; Proc *p; lock(&procalloc); while((p = procalloc.free) == nil) { unlock(&procalloc); snprint(msg, sizeof msg, "no procs; %s forking", up? up->text: "kernel"); /* * the situation is unlikely to heal itself. * dump the proc table and restart by default. * *noprocspersist in plan9.ini will yield the old * behaviour of trying forever. */ if(getconf("*noprocspersist") == nil) noprocpanic(msg); resrcwait(msg); lock(&procalloc); } procalloc.free = p->qnext; unlock(&procalloc); p->state = Scheding; p->psstate = "New"; p->mach = 0; p->qnext = 0; p->nchild = 0; p->nwait = 0; p->waitq = 0; p->parent = 0; p->pgrp = 0; p->egrp = 0; p->fgrp = 0; p->rgrp = 0; p->pdbg = 0; p->fpstate = FPinit; p->kp = 0; if(up && up->procctl == Proc_tracesyscall) p->procctl = Proc_tracesyscall; else p->procctl = 0; p->syscalltrace = 0; p->notepending = 0; p->ureg = 0; p->privatemem = 0; p->noswap = 0; p->errstr = p->errbuf0; p->syserrstr = p->errbuf1; p->errbuf0[0] = '\0'; p->errbuf1[0] = '\0'; p->nlocks.ref = 0; p->delaysched = 0; p->trace = 0; kstrdup(&p->user, "*nouser"); kstrdup(&p->text, "*notext"); kstrdup(&p->args, ""); p->nargs = 0; p->setargs = 0; memset(p->seg, 0, sizeof p->seg); p->pid = incref(&pidalloc); pidhash(p); p->noteid = incref(¬eidalloc); if(p->pid==0 || p->noteid==0) panic("pidalloc"); if(p->kstack == 0) p->kstack = smalloc(KSTACK); /* sched params */ p->mp = 0; p->wired = 0; procpriority(p, PriNormal, 0); p->cpu = 0; p->lastupdate = MACHP(0)->ticks*Scaling; p->edf = nil; return p; }