shithub: drawcpu

ref: be21af8515dcebab0ae2991e8e952af04e06baad
dir: /kern/procinit.c/

View raw version
#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");
}