ref: be21af8515dcebab0ae2991e8e952af04e06baad
dir: /kern/procinit.c/
#include "u.h"
#include "lib.h"
#include "dat.h"
#include "fns.h"
#include "error.h"
void
procinit0(void)
{
Proc *p;
p = newproc();
p->fgrp = dupfgrp(nil);
p->rgrp = newrgrp();
p->pgrp = newpgrp();
p->egrp = newegrp();
p->parentpid = 0;
p->kp = 1;
_setproc(p);
up->slash = namec("#/", Atodir, 0, 0);
pathclose(up->slash->path);
up->slash->path = newpath("/");
up->dot = cclone(up->slash);
}
Ref pidref;
Proc*
newproc(void)
{
Proc *p;
p = mallocz(sizeof(Proc), 1);
p->pid = incref(&pidref);
strcpy(p->user, eve);
p->syserrstr = p->errbuf0;
p->errstr = p->errbuf1;
strcpy(p->text, "drawcpu");
osnewproc(p);
return p;
}
Proc*
proctab(int i)
{
Proc *p;
for(p = up; p != nil; p = p->parent) {
if(p->pid == i)
return p;
}
return nil;
}
void *
kproc(char *name, void (*fn)(void*), void *arg)
{
Proc *p;
p = newproc();
p->fn = fn;
p->arg = arg;
p->slash = cclone(up->slash);
p->dot = cclone(up->dot);
p->rgrp = up->rgrp;
p->parent = up;
if(p->rgrp != nil)
incref(&p->rgrp->ref);
p->pgrp = up->pgrp;
if(up->pgrp != nil)
incref(&up->pgrp->ref);
p->fgrp = up->fgrp;
if(p->fgrp != nil)
incref(&p->fgrp->ref);
p->egrp = up->egrp;
if(p->egrp != nil)
incref(&p->egrp->ref);
strecpy(p->text, p->text+sizeof p->text, name);
osproc(p);
return (void*)p;
}
static int
haswaitq(void *x)
{
return ((Proc*)x)->waitq != nil;
}
static void
freenotes(Proc *p)
{
while(p->nnote > 0){
freenote(p->note[--p->nnote]);
up->note[p->nnote] = nil;
}
}
ulong
pwait(Waitmsg *w)
{
ulong cpid;
Waitq *wq;
if(!canqlock(&up->qwaitr))
error(Einuse);
if(waserror()) {
qunlock(&up->qwaitr);
nexterror();
}
lock(&up->exl);
while(up->waitq == nil) {
if(up->nchild == 0) {
unlock(&up->exl);
error(Enochild);
}
unlock(&up->exl);
sleep(&up->waitr, haswaitq, up);
lock(&up->exl);
}
wq = up->waitq;
up->waitq = wq->next;
up->nwait--;
unlock(&up->exl);
qunlock(&up->qwaitr);
poperror();
if(w != nil)
memmove(w, &wq->w, sizeof(Waitmsg));
cpid = wq->w.pid;
free(wq);
return cpid;
}
void
pexit(char *exitstr, int freemem)
{
Proc *p;
Waitq *wq;
Fgrp *fgrp;
Egrp *egrp;
Rgrp *rgrp;
Pgrp *pgrp;
Chan *dot;
Segment *s;
int i;
/* nil out all the resources under lock (free later) */
qlock(&up->debug);
fgrp = up->fgrp;
up->fgrp = nil;
egrp = up->egrp;
up->egrp = nil;
rgrp = up->rgrp;
up->rgrp = nil;
pgrp = up->pgrp;
up->pgrp = nil;
dot = up->dot;
up->dot = nil;
qunlock(&up->debug);
if(fgrp != nil)
closefgrp(fgrp);
if(egrp != nil)
closeegrp(egrp);
if(rgrp != nil)
closergrp(rgrp);
if(dot != nil)
cclose(dot);
if(pgrp != nil)
closepgrp(pgrp);
if(up->pid == 0){
if(exitstr == nil)
exitstr = "unknown";
panic("boot process died: %s", exitstr);
}
p = up->parent;
if(p != nil && p->pid == up->parentpid && p->state != Broken){
wq = smalloc(sizeof(Waitq));
wq->w.pid = up->pid;
// TODO: Timers
wq->w.dur[0] = 1000;
wq->w.dur[1] = 1000;
wq->w.dur[2] = 1000;
if(exitstr != nil && exitstr[0])
snprint(wq->w.msg, sizeof(wq->w.msg), "%s %lud: %s", up->text, up->pid, exitstr);
else
snprint(wq->w.msg, 1, "%c", '0');
lock(&p->exl);
/*
* Check that parent is still alive.
*/
if(p->pid == up->parentpid && p->state != Broken) {
p->nchild--;
//p->dur[TCUser] += 100;
//p->dur[TCSys] += 100;
/*
* 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 != nil)
free(wq);
}
qlock(&up->seglock);
for(i = 0; i < NSEG; i++){
s = up->seg[i];
if(s != nil){
up->seg[i] = nil;
putseg(s);
}
}
qunlock(&up->seglock);
qlock(&up->debug);
lock(&up->exl); /* Prevent my children from leaving waits */
up->parent = nil;
up->nchild = up->nwait = 0;
wakeup(&up->waitr);
unlock(&up->exl);
while((wq = up->waitq) != nil){
up->waitq = wq->next;
free(wq);
}
freenotes(up);
freenote(up->lastnote);
up->lastnote = nil;
up->notified = 0;
qunlock(&up->debug);
osexit(exitstr);
panic("pexit");
}