Ejemplo n.º 1
0
int main(int argc, char *argv[]) {
	if (argc != 2) return 0;

	sscanf(argv[1], "%d", &pid);

	printf("attaching\n");
	proctrace(PTRACE_ATTACH, pid, NULL, NULL);
	printf("waiting for child to stop\n");
	proctrace_wait(-1, NULL, 0, NULL);
	print_signal();
	printf("waited. child should be stopped\n");
	proctrace(PTRACE_SYSCALL, pid, NULL, NULL);
	proctrace(PTRACE_CONT, pid, NULL, NULL);
	printf("waiting for the system call\n");
	proctrace_wait(-1, NULL, 0, NULL);
	print_signal();
	printf("child did it's thing. continuing and waiting for child to quit...\n");

	long sc = proctrace(PTRACE_PEEKUSER, pid, (void*) (4 * ORIG_EAX), NULL);
	printf("not minus 1: %ld\n", sc);

	proctrace(PTRACE_CONT, pid, NULL, NULL);
	proctrace_wait(-1, NULL, 0, NULL);

	return 0;
}
Ejemplo n.º 2
0
Archivo: proc.c Proyecto: npe9/harvey
static void
schedready(Sched *sch, Proc *p, int locked)
{
	Mpl pl;
	int pri;
	Schedq *rq;

	pl = splhi();
	if(edfready(p)){
		splx(pl);
		return;
	}

/*	if(m->externup != p)
		m->readied = p;	*//* group scheduling, will be removed */

	updatecpu(p);
	pri = reprioritize(p);
	p->priority = pri;
	rq = &sch->runq[pri];
	p->state = Ready;
	queueproc(sch, rq, p, locked);
	if(p->trace)
		proctrace(p, SReady, 0);
	splx(pl);
}
Ejemplo n.º 3
0
Archivo: edf.c Proyecto: Requaos/harvey
static void
deadlineintr(Ureg* ureg, Timer *t)
{
	Proc *up = externup();
	/* Proc reached deadline */
	extern int panicking;
	Sched *sch;
	Proc *p;

	if(panicking || active.exiting)
		return;

	p = t->ta;
	now = ms();
	DPRINT("%lu deadlineintr %d[%s]\n", now, p->pid, statename[p->state]);
	/* If we're interrupting something other than the proc pointed to by t->a,
	 * we've already achieved recheduling, so we need not do anything
	 * Otherwise, we must cause a reschedule, but if we call sched()
	 * here directly, the timer interrupt routine will not finish its business
	 * Instead, we cause the resched to happen when the interrupted proc
	 * returns to user space
	 */
	if(p == up){
		if(up->trace)
			proctrace(up, SInts, 0);
		up->delaysched++;
		sch = procsched(up);
 		sch->delayedscheds++;
	}
}
Ejemplo n.º 4
0
Archivo: edf.c Proyecto: Requaos/harvey
void
edfrecord(Proc *p)
{
	int32_t used;
	Edf *e;

	if((e = edflock(p)) == nil)
		return;
	used = now - e->s;
	if(e->d - now <= 0)
		e->edfused += used;
	else
		e->extraused += used;
	if(e->S > 0){
		if(e->S <= used){
			if(p->trace)
				proctrace(p, SSlice, 0);
			DPRINT("%lu edfrecord slice used up\n", now);
			e->d = now;
			e->S = 0;
		}else
			e->S -= used;
	}
	e->s = now;
	edfunlock();
}
Ejemplo n.º 5
0
Archivo: proc.c Proyecto: npe9/harvey
/*
 * SMP performs better than AMP with few cores.
 * So, leave this here by now. We should probably
 * write a unified version of runproc good enough for
 * both SMP and AMP.
 */
static Proc*
smprunproc(void)
{
	Mach *m = machp();
	Schedq *rq;
	Proc *p;
	uint32_t start, now;
	int i;

	start = perfticks();
	run.preempts++;

loop:
	/*
	 *  find a process that last ran on this processor (affinity),
	 *  or one that hasn't moved in a while (load balancing).  Every
	 *  time around the loop affinity goes down.
	 */
	spllo();
	for(i = 0;; i++){
		/*
		 *  find the highest priority target process that this
		 *  processor can run given affinity constraints.
		 *
		 */
		for(rq = &run.runq[Nrq-1]; rq >= run.runq; rq--){
			for(p = rq->head; p; p = p->rnext){
				if(p->mp == nil || p->mp == sys->machptr[m->machno]
				|| (!p->wired && i > 0))
					goto found;
			}
		}

		/* waste time or halt the CPU */
		idlehands();
		/* remember how much time we're here */
		now = perfticks();
		m->perf.inidle += now-start;
		start = now;
	}

found:
	splhi();
	p = dequeueproc(&run, rq, p);
	if(p == nil)
		goto loop;

	p->state = Scheding;
	p->mp = sys->machptr[m->machno];

	if(edflock(p)){
		edfrun(p, rq == &run.runq[PriEdf]);	/* start deadline timer and do admin */
		edfunlock();
	}
	if(p->trace)
		proctrace(p, SRun, 0);
	return p;
}
Ejemplo n.º 6
0
Archivo: edf.c Proyecto: Requaos/harvey
static void
release(Proc *p)
{
	/* Called with edflock held */
	Edf *e;
	int32_t n;
	int64_t nowns;

	e = p->edf;
	e->flags &= ~Yield;
	if(e->d - now < 0){
		e->periods++;
		e->r = now;
		if((e->flags & Sporadic) == 0){
			/*
			 * Non sporadic processes stay true to their period;
			 * calculate next release time.
			 * Second test limits duration of while loop.
			 */
			if((n = now - e->t) > 0){
				if(n < e->T)
					e->t += e->T;
				else
					e->t = now + e->T - (n % e->T);
			}
		}else{
			/* Sporadic processes may not be released earlier than
			 * one period after this release
			 */
			e->t = e->r + e->T;
		}
		e->d = e->r + e->D;
		e->S = e->C;
		DPRINT("%lu release %d[%s], r=%lu, d=%lu, t=%lu, S=%lu\n",
			now, p->pid, statename[p->state], e->r, e->d, e->t, e->S);
		if(p->trace){
			nowns = todget(nil);
			proctrace(p, SRelease, nowns);
			proctrace(p, SDeadline, nowns + 1000LL*e->D);
		}
	}else{
		DPRINT("%lu release %d[%s], too late t=%lu, called from %#p\n",
			now, p->pid, statename[p->state], e->t, getcallerpc());
	}
}
Ejemplo n.º 7
0
// substitute for wait4() system call
pid_t proctrace_wait(pid_t pid, int *status, int options, struct rusage *rusage) {
#ifdef USE_PTRACE
	return wait4(pid, status, options, rusage);
#endif

	disable_signal();

	if (attached_pid == 0) {
		if (pid == -1) {
			printf("I don't know what to do in proctrace_wait\n");
			exit(1);
		}
		attached_pid = pid;
	}

	if (singlestep) {
		ctl("step");
		singlestep = 0;
	} else {
		char buf[35];
		sprintf(buf, "/proc/%d/wait", attached_pid);

		int fd = open(buf, O_WRONLY);
		proctrace_wait_mask = ((1ULL << 31) - 1) << 1;
		proctrace_wait_mask |= 1ULL;
		proctrace_wait_mask |= (1ULL << 40);
		// temp hack for strace 
		proctrace_wait_mask |= (1ULL << 33);
		unsigned long long big_endian = 0;
		int i;
		for (i = 0; i < 8; ++i) {
			big_endian |= ((proctrace_wait_mask >> (8*i)) & ((1 << 8)-1)) << (8-i-1)*8;
		}

		long retvalue = write(fd, &big_endian, sizeof(big_endian));
		if (retvalue < 0) {
			printf("write to wait failed, fd: %d, buf: %s\n", fd, buf);
		}
		close(fd);
	}

	if (status) {
		siginfo_t a;
		if (proctrace(PTRACE_GETSIGINFO, attached_pid, NULL, (void *)&a) == -1) {
			*status = 0;
		} else {
			if (a.si_signo == 0) a.si_signo = SIGSTOP;
			if (a.si_signo > 32) {
				*status = (SIGTRAP << 8) | 0177;
			} else {
				*status = (a.si_signo << 8) | 0177;
			}
		}
	}

	return attached_pid;
}
Ejemplo n.º 8
0
Archivo: edf.c Proyecto: Requaos/harvey
void
edfstop(Proc *p)
{
	Edf *e;

	if(e = edflock(p)){
		DPRINT("%lu edfstop %d[%s]\n", now, p->pid, statename[p->state]);
		if(p->trace)
			proctrace(p, SExpel, 0);
		e->flags &= ~Admitted;
		if(e->Timer.tt)
			timerdel(&e->Timer);
		edfunlock();
	}
}
Ejemplo n.º 9
0
void
qlock(QLock *q)
{
	Proc *up = externup();
	Proc *p;
	uint64_t t0;

	cycles(&t0);

	if(!islo() && machp()->ilockdepth != 0){
		print("qlock with ilockdepth %d,", machp()->ilockdepth);
		stacksnippet();
	}

	if(up != nil && up->nlocks)
		print("qlock: %#p: nlocks %d", getcallerpc(&q), up->nlocks);

	if(!canlock(&q->use)){
		lock(&q->use);
		slockstat(getcallerpc(&q), t0);
	}
	qlockstats.qlock++;
	if(!q->locked) {
		q->locked = 1;
		q->pc = getcallerpc(&q);
		unlock(&q->use);
		return;
	}
	if(up == nil)
		panic("qlock");
	qlockstats.qlockq++;
	p = q->tail;
	if(p == 0)
		q->head = up;
	else
		p->qnext = up;
	q->tail = up;
	up->qnext = 0;
	up->state = Queueing;
	up->qpc = getcallerpc(&q);
	if(up->trace)
		proctrace(up, SLock, 0);
	unlock(&q->use);
	sched();
	lockstat(getcallerpc(&q), t0);
}
Ejemplo n.º 10
0
Archivo: proc.c Proyecto: npe9/harvey
Proc*
runproc(void)
{
	Mach *m = machp();
	Schedq *rq;
	Proc *p;
	uint32_t start, now;

	if(nosmp)
		return singlerunproc();

	//NIX modeset cannot work without halt every cpu at boot
	//if(sys->nmach <= AMPmincores)
	else
		return smprunproc();

	start = perfticks();
	run.preempts++;
	rq = nil;
	if(m->machno != 0){
		do{
			spllo();
			while(m->proc == nil)
				idlehands();
			now = perfticks();
			m->perf.inidle += now-start;
			start = now;
			splhi();
			p = m->proc;
		}while(p == nil);
		p->state = Scheding;
		p->mp = sys->machptr[m->machno];
	
		if(edflock(p)){
			edfrun(p, rq == &run.runq[PriEdf]);	/* start deadline timer and do admin */
			edfunlock();
		}
		if(p->trace)
			proctrace(p, SRun, 0);
		return p;
	}

	mach0sched();
	return nil;	/* not reached */
}
Ejemplo n.º 11
0
Archivo: edf.c Proyecto: Requaos/harvey
void
edfrun(Proc *p, int edfpri)
{
	Edf *e;
	int32_t tns;
	Sched *sch;

	e = p->edf;
	sch = procsched(p);
	/* Called with edflock held */
	if(edfpri){
		tns = e->d - now;
		if(tns <= 0 || e->S == 0){
			/* Deadline reached or resources exhausted,
			 * deschedule forthwith
			 */
			p->delaysched++;
			sch->delayedscheds++;
			e->s = now;
			return;
		}
		if(e->S < tns)
			tns = e->S;
		if(tns < 20)
			tns = 20;
		e->Timer.tns = 1000LL * tns;	/* µs to ns */
		if(e->Timer.tt == nil || e->Timer.tf != deadlineintr){
			DPRINT("%lu edfrun, deadline=%lu\n", now, tns);
		}else{
			DPRINT("v");
		}
		if(p->trace)
			proctrace(p, SInte, todget(nil) + e->Timer.tns);
		e->Timer.tmode = Trelative;
		e->Timer.tf = deadlineintr;
		e->Timer.ta = p;
		timeradd(&e->Timer);
	}else{
		DPRINT("<");
	}
	e->s = now;
}
Ejemplo n.º 12
0
void
wlock(RWlock *q)
{
	Proc *up = externup();
	Proc *p;
	uint64_t t0;

	cycles(&t0);
	if(!canlock(&q->use)){
		lock(&q->use);
		slockstat(getcallerpc(&q), t0);
	}
	qlockstats.wlock++;
	if(q->readers == 0 && q->writer == 0){
		/* noone waiting, go for it */
		q->wpc = getcallerpc(&q);
		q->wproc = up;
		q->writer = 1;
		unlock(&q->use);
		return;
	}

	/* wait */
	qlockstats.wlockq++;
	p = q->tail;
	if(up == nil)
		panic("wlock");
	if(p == nil)
		q->head = up;
	else
		p->qnext = up;
	q->tail = up;
	up->qnext = 0;
	up->state = QueueingW;
	if(up->trace)
		proctrace(up, SLock, 0);
	unlock(&q->use);
	sched();
	lockstat(getcallerpc(&q), t0);
}
Ejemplo n.º 13
0
static void
schedready(Sched *sch, Proc *p, int locked)
{
	Mpl pl;
	int pri;
	Schedq *rq;

	pl = splhi();
	if(edfready(p)){
		splx(pl);
		return;
	}

	updatecpu(p);
	pri = reprioritize(p);
	p->priority = pri;
	rq = &sch->runq[pri];
	p->state = Ready;
	queueproc(sch, rq, p, locked);
	if(p->trace)
		proctrace(p, SReady, 0);
	splx(pl);
}
Ejemplo n.º 14
0
Archivo: edf.c Proyecto: Requaos/harvey
void
edfyield(void)
{
	Proc *up = externup();
	/* sleep until next release */
	Edf *e;
	int32_t n;

	if((e = edflock(up)) == nil)
		return;
	if(up->trace)
		proctrace(up, SYield, 0);
	if((n = now - e->t) > 0){
		if(n < e->T)
			e->t += e->T;
		else
			e->t = now + e->T - (n % e->T);
	}
	e->r = e->t;
	e->flags |= Yield;
	e->d = now;
	if (up->Timer.tt == nil){
		n = e->t - now;
		if(n < 20)
			n = 20;
		up->Timer.tns = 1000LL * n;
		up->Timer.tf = releaseintr;
		up->Timer.tmode = Trelative;
		up->Timer.ta = up;
		up->trend = &up->sleep;
		timeradd(&up->Timer);
	}else if(up->Timer.tf != releaseintr)
		print("edfyield: surprise! %#p\n", up->Timer.tf);
	edfunlock();
	sleep(&up->sleep, yfn, nil);
}
Ejemplo n.º 15
0
void print_signal() {
	siginfo_t sig;
	proctrace(PTRACE_GETSIGINFO, pid, NULL, &sig);
	printf("I quit because of the signal %d\n", sig.si_signo);
}
Ejemplo n.º 16
0
Archivo: edf.c Proyecto: Requaos/harvey
int
edfready(Proc *p)
{
	Edf *e;
	Sched *sch;
	Schedq *rq;
	Proc *l, *pp;
	int32_t n;

	if((e = edflock(p)) == nil)
		return 0;

	if(p->state == Wakeme && p->r){
		iprint("edfready: wakeme\n");
	}
	if(e->d - now <= 0){
		/* past deadline, arrange for next release */
		if((e->flags & Sporadic) == 0){
			/*
			 * Non sporadic processes stay true to their period;
			 * calculate next release time.
			 */
			if((n = now - e->t) > 0){
				if(n < e->T)
					e->t += e->T;
				else
					e->t = now + e->T - (n % e->T);
			}
		}
		if(now - e->t < 0){
			/* Next release is in the future, schedule it */
			if(e->Timer.tt == nil || e->Timer.tf != releaseintr){
				n = e->t - now;
				if(n < 20)
					n = 20;
				e->Timer.tns = 1000LL * n;
				e->Timer.tmode = Trelative;
				e->Timer.tf = releaseintr;
				e->Timer.ta = p;
				timeradd(&e->Timer);
				DPRINT("%lu edfready %d[%s], release=%lu\n",
					now, p->pid, statename[p->state], e->t);
			}
			if(p->state == Running && (e->flags & (Yield|Yieldonblock)) == 0 && (e->flags & Extratime)){
				/* If we were running, we've overrun our CPU allocation
				 * or missed the deadline, continue running best-effort at low priority
				 * Otherwise we were blocked.  If we don't yield on block, we continue
				 * best effort
				 */
				DPRINT(">");
				p->basepri = PriExtra;
				p->fixedpri = 1;
				edfunlock();
				return 0;	/* Stick on runq[PriExtra] */
			}
			DPRINT("%lu edfready %d[%s] wait release at %lu\n",
				now, p->pid, statename[p->state], e->t);
			p->state = Waitrelease;
			edfunlock();
			return 1;	/* Make runnable later */
		}
		DPRINT("%lu edfready %d %s release now\n", now, p->pid, statename[p->state]);
		/* release now */
		release(p);
	}
	edfunlock();
	DPRINT("^");
	sch = procsched(p);
	rq = &sch->runq[PriEdf];
	/* insert in queue in earliest deadline order */
	lock(&sch->l);
	l = nil;
	for(pp = rq->head; pp; pp = pp->rnext){
		if(pp->edf->d > e->d)
			break;
		l = pp;
	}
	p->rnext = pp;
	if (l == nil)
		rq->head = p;
	else
		l->rnext = p;
	if(pp == nil)
		rq->tail = p;
	rq->n++;
	sch->nrdy++;
	sch->runvec |= 1 << PriEdf;
	p->priority = PriEdf;
	p->readytime = machp()->ticks;
	p->state = Ready;
	unlock(&sch->l);
	if(p->trace)
		proctrace(p, SReady, 0);
	return 1;
}
Ejemplo n.º 17
0
Archivo: edf.c Proyecto: Requaos/harvey
char *
edfadmit(Proc *p)
{
	Proc *up = externup();
	char *err;
	Edf *e;
	int i;
	Proc *r;
	int32_t tns;

	e = p->edf;
	if (e->flags & Admitted)
		return "task state";	/* should never happen */

	/* simple sanity checks */
	if (e->T == 0)
		return "T not set";
	if (e->C == 0)
		return "C not set";
	if (e->D > e->T)
		return "D > T";
	if (e->D == 0)	/* if D is not set, set it to T */
		e->D = e->T;
	if (e->C > e->D)
		return "C > D";

	qlock(&edfschedlock);
	if (err = testschedulability(p)){
		qunlock(&edfschedlock);
		return err;
	}
	e->flags |= Admitted;

	edflock(p);

	if(p->trace)
		proctrace(p, SAdmit, 0);

	/* Look for another proc with the same period to synchronize to */
	for(i=0; (r = psincref(i)) != nil; i++) {
		if(r->state == Dead || r == p){
			psdecref(r);
			continue;
		}
		if (r->edf == nil || (r->edf->flags & Admitted) == 0){
			psdecref(r);
			continue;
		}
		if (r->edf->T == e->T)
			break;
	}
	if (r == nil){
		/* Can't synchronize to another proc, release now */
		e->t = now;
		e->d = 0;
		release(p);
		if (p == up){
			DPRINT("%lu edfadmit self %d[%s], release now: r=%lu d=%lu t=%lu\n",
				now, p->pid, statename[p->state], e->r, e->d, e->t);
			/* We're already running */
			edfrun(p, 1);
		}else{
			/* We're releasing another proc */
			DPRINT("%lu edfadmit other %d[%s], release now: r=%lu d=%lu t=%lu\n",
				now, p->pid, statename[p->state], e->r, e->d, e->t);
			p->Timer.ta = p;
			edfunlock();
			qunlock(&edfschedlock);
			releaseintr(nil, &p->Timer);
			return nil;
		}
	}else{
		/* Release in synch to something else */
		e->t = r->edf->t;
		psdecref(r);
		if (p == up){
			DPRINT("%lu edfadmit self %d[%s], release at %lu\n",
				now, p->pid, statename[p->state], e->t);
		}else{
			DPRINT("%lu edfadmit other %d[%s], release at %lu\n",
				now, p->pid, statename[p->state], e->t);
			if(e->Timer.tt == nil){
				e->Timer.tf = releaseintr;
				e->Timer.ta = p;
				tns = e->t - now;
				if(tns < 20)
					tns = 20;
				e->Timer.tns = 1000LL * tns;
				e->Timer.tmode = Trelative;
				timeradd(&e->Timer);
			}
		}
	}
	edfunlock();
	qunlock(&edfschedlock);
	return nil;
}
Ejemplo n.º 18
0
Archivo: proc.c Proyecto: npe9/harvey
/*
 *  sleep if a condition is not true.  Another process will
 *  awaken us after it sets the condition.  When we awaken
 *  the condition may no longer be true.
 *
 *  we lock both the process and the rendezvous to keep r->p
 *  and p->r synchronized.
 */
void
sleep(Rendez *r, int (*f)(void*), void *arg)
{
	Mach *m = machp();
	Mpl pl;

	pl = splhi();

	if(m->externup->nlocks)
		print("process %d sleeps with %d locks held, last lock %#p locked at pc %#p, sleep called from %#p\n",
			m->externup->pid, m->externup->nlocks, m->externup->lastlock, m->externup->lastlock->_pc, getcallerpc(&r));
	lock(r);
	lock(&m->externup->rlock);
	if(r->_p){
		print("double sleep called from %#p, %d %d\n",
			getcallerpc(&r), r->_p->pid, m->externup->pid);
		dumpstack();
	}

	/*
	 *  Wakeup only knows there may be something to do by testing
	 *  r->p in order to get something to lock on.
	 *  Flush that information out to memory in case the sleep is
	 *  committed.
	 */
	r->_p = m->externup;

	if((*f)(arg) || m->externup->notepending){
		/*
		 *  if condition happened or a note is pending
		 *  never mind
		 */
		r->_p = nil;
		unlock(&m->externup->rlock);
		unlock(r);
	} else {
		/*
		 *  now we are committed to
		 *  change state and call scheduler
		 */
		if(m->externup->trace)
			proctrace(m->externup, SSleep, 0);
		m->externup->state = Wakeme;
		m->externup->r = r;

		/* statistics */
		m->cs++;

		procsave(m->externup);
		mmuflushtlb(m->pml4->pa);
		if(setlabel(&m->externup->sched)) {
			/*
			 *  here when the process is awakened
			 */
			procrestore(m->externup);
			spllo();
		} else {
			/*
			 *  here to go to sleep (i.e. stop Running)
			 */
			unlock(&m->externup->rlock);
			unlock(r);
			/*debug*/gotolabel(&m->sched);
		}
	}

	if(m->externup->notepending) {
		m->externup->notepending = 0;
		splx(pl);
		if(m->externup->procctl == Proc_exitme && m->externup->closingfgrp)
			forceclosefgrp();
		error(Eintr);
	}

	splx(pl);
}
Ejemplo n.º 19
0
Archivo: proc.c Proyecto: npe9/harvey
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");
}
Ejemplo n.º 20
0
Archivo: proc.c Proyecto: npe9/harvey
static Proc*
singlerunproc(void)
{
	Mach *m = machp();
	Schedq *rq;
	Proc *p;
	uint32_t start, now, skipscheds;
	int i;

	start = perfticks();

	/* cooperative scheduling until the clock ticks */
	if((p=m->readied) && p->mach==0 && p->state==Ready
	&& &run.runq[Nrq-1].head == nil && &run.runq[Nrq-2].head == nil){
		skipscheds++;
		rq = &run.runq[p->priority];
		if(0)hi("runproc going to found before loop...\n");
		goto found;
	}

	run.preempts++;

loop:
	/*
	 *  find a process that last ran on this processor (affinity),
	 *  or one that hasn't moved in a while (load balancing).  Every
	 *  time around the loop affinity goes down.
	 */
	spllo();
	for(i = 0;; i++){
		/*
		 *  find the highest priority target process that this
		 *  processor can run given affinity constraints.
		 *
		 */
		for(rq = &run.runq[Nrq-1]; rq >= run.runq; rq--){
			for(p = rq->head; p; p = p->rnext){
				if(p->mp == nil || p->mp == sys->machptr[m->machno]
				|| (!p->wired && i > 0))
				{
					if(0)hi("runproc going to found inside loop...\n");
					goto found;
				}
			}
		}

		/* waste time or halt the CPU */
		idlehands();

		/* remember how much time we're here */
		now = perfticks();
		m->perf.inidle += now-start;
		start = now;
	}

found:
	splhi();
	if(0)hi("runproc into found...\n");
	p = dequeueproc(&run, rq, p);
	if(p == nil)
	{
		if(0)hi("runproc p=nil :(\n");
			goto loop;
	}

	p->state = Scheding;
	if(0)hi("runproc, pm->mp = sys->machptr[m->machno]\n");
	p->mp = sys->machptr[m->machno];
	if(0){hi("runproc, sys->machptr[m->machno] = "); put64((uint64_t)p->mp); hi("\n");}

	if(edflock(p)){
		edfrun(p, rq == &run.runq[PriEdf]);	/* start deadline timer and do admin */
		edfunlock();
	}
	if(p->trace)
		proctrace(p, SRun, 0);
	/* avoiding warnings, this will be removed */
	USED(mach0sched); USED(smprunproc);
	if(0){hi("runproc, returning p ");
	put64((uint64_t)p);
	hi("\n");}

	
	return p;
}