/* * called splhi() by notify(). See comment in notify for the * reasoning. */ void procctl(Proc *p) { Mach *m = machp(); Mpl pl; char *state; switch(p->procctl) { case Proc_exitbig: spllo(); pexit("Killed: Insufficient physical memory", 1); case Proc_exitme: spllo(); /* pexit has locks in it */ pexit("Killed", 1); case Proc_traceme: if(p->nnote == 0) return; /* No break */ case Proc_stopme: p->procctl = 0; state = p->psstate; p->psstate = "Stopped"; /* free a waiting debugger */ pl = spllo(); qlock(&p->debug); if(p->pdbg) { wakeup(&p->pdbg->sleep); p->pdbg = 0; } qunlock(&p->debug); splhi(); p->state = Stopped; sched(); p->psstate = state; splx(pl); return; case Proc_toac: p->procctl = 0; /* * This pretends to return from the system call, * by moving to a core, but never returns (unless * the process gets moved back to a TC.) */ spllo(); runacore(); return; case Proc_totc: p->procctl = 0; if(p != m->externup) panic("procctl: stopac: p != up"); spllo(); stopac(); return; } }
/* * Always splhi()'ed. */ void schedinit(void) /* never returns */ { Edf *e; machp()->inidle = 1; machp()->proc = nil; ainc(&run.nmach); setlabel(&machp()->sched); Proc *up = externup(); if(infected_with_std()){ print("mach %d got an std from %s (pid %d)!\n", machp()->machno, up ? up->text : "*notext", up ? up->pid : -1 ); disinfect_std(); } if(up) { if((e = up->edf) && (e->flags & Admitted)) edfrecord(up); machp()->qstart = 0; machp()->qexpired = 0; coherence(); machp()->proc = 0; switch(up->state) { case Running: ready(up); break; case Moribund: up->state = Dead; stopac(); edfstop(up); if (up->edf) free(up->edf); up->edf = nil; /* * Holding locks from pexit: * procalloc * pga */ mmurelease(up); unlock(&pga.l); psrelease(up); unlock(&procalloc.l); break; } up->mach = nil; updatecpu(up); machp()->externup = nil; } sched(); }
/* * Always splhi()'ed. */ void schedinit(void) /* never returns */ { Mach *m = machp(); Edf *e; m->inidle = 1; m->proc = nil; ainc(&run.nmach); setlabel(&m->sched); if(m->externup) { if((e = m->externup->edf) && (e->flags & Admitted)) edfrecord(m->externup); m->qstart = 0; m->qexpired = 0; coherence(); m->proc = 0; switch(m->externup->state) { case Running: ready(m->externup); break; case Moribund: m->externup->state = Dead; stopac(); edfstop(m->externup); if (m->externup->edf) free(m->externup->edf); m->externup->edf = nil; /* * Holding locks from pexit: * procalloc * pga */ mmurelease(m->externup); unlock(&pga); psrelease(m->externup); unlock(&procalloc); break; } m->externup->mach = nil; updatecpu(m->externup); m->externup = nil; } sched(); }
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); stopac(); edfstop(up); p->state = Broken; p->psstate = 0; sched(); }
void pexit(char *exitstr, int freemem) { Mach *m = machp(); Proc *p; Segment **s, **es; int32_t utime, stime; Waitq *wq, *f, *next; Fgrp *fgrp; Egrp *egrp; Rgrp *rgrp; Pgrp *pgrp; Chan *dot; if(0 && m->externup->nfullq > 0) iprint(" %s=%d", m->externup->text, m->externup->nfullq); if(0 && m->externup->nicc > 0) iprint(" [%s nicc %ud tctime %ulld actime %ulld]\n", m->externup->text, m->externup->nicc, m->externup->tctime, m->externup->actime); if(m->externup->syscalltrace != nil) free(m->externup->syscalltrace); m->externup->syscalltrace = nil; m->externup->alarm = 0; if (m->externup->tt) timerdel(m->externup); if(m->externup->trace) proctrace(m->externup, SDead, 0); /* nil out all the resources under lock (free later) */ qlock(&m->externup->debug); fgrp = m->externup->fgrp; m->externup->fgrp = nil; egrp = m->externup->egrp; m->externup->egrp = nil; rgrp = m->externup->rgrp; m->externup->rgrp = nil; pgrp = m->externup->pgrp; m->externup->pgrp = nil; dot = m->externup->dot; m->externup->dot = nil; qunlock(&m->externup->debug); if(fgrp) closefgrp(fgrp); if(egrp) closeegrp(egrp); if(rgrp) closergrp(rgrp); if(dot) cclose(dot); if(pgrp) closepgrp(pgrp); /* * if not a kernel process and have a parent, * do some housekeeping. */ if(m->externup->kp == 0) { p = m->externup->parent; if(p == 0) { if(exitstr == 0) exitstr = "unknown"; //die("bootprocessdeath"); panic("boot process died: %s", exitstr); } while(waserror()) ; wq = smalloc(sizeof(Waitq)); poperror(); wq->w.pid = m->externup->pid; utime = m->externup->time[TUser] + m->externup->time[TCUser]; stime = m->externup->time[TSys] + m->externup->time[TCSys]; wq->w.time[TUser] = tk2ms(utime); wq->w.time[TSys] = tk2ms(stime); wq->w.time[TReal] = tk2ms(sys->machptr[0]->ticks - m->externup->time[TReal]); if(exitstr && exitstr[0]) snprint(wq->w.msg, sizeof(wq->w.msg), "%s %d: %s", m->externup->text, m->externup->pid, exitstr); else wq->w.msg[0] = '\0'; lock(&p->exl); /* * Check that parent is still alive. */ if(p->pid == m->externup->parentpid && p->state != Broken) { p->nchild--; p->time[TCUser] += utime; p->time[TCSys] += stime; /* * If there would be more than 128 wait records * processes for my parent, then don't leave a wait * record behind. This helps prevent badly written * daemon processes from accumulating lots of wait * records. */ if(p->nwait < 128) { wq->next = p->waitq; p->waitq = wq; p->nwait++; wq = nil; wakeup(&p->waitr); } } unlock(&p->exl); if(wq) free(wq); } if(!freemem) addbroken(m->externup); qlock(&m->externup->seglock); es = &m->externup->seg[NSEG]; for(s = m->externup->seg; s < es; s++) { if(*s) { putseg(*s); *s = 0; } } qunlock(&m->externup->seglock); lock(&m->externup->exl); /* Prevent my children from leaving waits */ psunhash(m->externup); m->externup->pid = 0; wakeup(&m->externup->waitr); unlock(&m->externup->exl); for(f = m->externup->waitq; f; f = next) { next = f->next; free(f); } /* release debuggers */ qlock(&m->externup->debug); if(m->externup->pdbg) { wakeup(&m->externup->pdbg->sleep); m->externup->pdbg = 0; } qunlock(&m->externup->debug); /* Sched must not loop for these locks */ lock(&procalloc); lock(&pga); stopac(); edfstop(m->externup); m->externup->state = Moribund; sched(); panic("pexit"); }