コード例 #1
0
ファイル: proc.c プロジェクト: 8l/inferno
void
sched(void)
{
	if(up) {
		splhi();
		procsave(up);
		if(setlabel(&up->sched)) {
			/* procrestore(up); */
			spllo();
			return;
		}
		gotolabel(&m->sched);
	}
	up = runproc();
	up->state = Running;
	up->mach = MACHP(m->machno);	/* m might be a fixed address; use MACHP */
	m->proc = up;
	gotolabel(&up->sched);
}
コード例 #2
0
ファイル: proc.c プロジェクト: grobe0ba/plan9front
/*
 *  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)
{
	int s;
	void (*pt)(Proc*, int, vlong);

	s = splhi();

	if(up->nlocks)
		print("process %lud sleeps with %d locks held, last lock %#p locked at pc %#p, sleep called from %#p\n",
			up->pid, up->nlocks, up->lastlock, up->lastlock->pc, getcallerpc(&r));
	lock(r);
	lock(&up->rlock);
	if(r->p != nil){
		print("double sleep called from %#p, %lud %lud\n", getcallerpc(&r), r->p->pid, up->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 = up;

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

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

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

	if(up->notepending) {
		up->notepending = 0;
		splx(s);
		interrupted();
	}

	splx(s);
}
コード例 #3
0
ファイル: proc.c プロジェクト: grobe0ba/plan9front
/*
 *  If changing this routine, look also at sleep().  It
 *  contains a copy of the guts of sched().
 */
void
sched(void)
{
	Proc *p;

	if(m->ilockdepth)
		panic("cpu%d: ilockdepth %d, last lock %#p at %#p, sched called from %#p",
			m->machno,
			m->ilockdepth,
			up != nil ? up->lastilock: nil,
			(up != nil && up->lastilock != nil) ? up->lastilock->pc: 0,
			getcallerpc(&p+2));
	if(up != nil) {
		/*
		 * Delay the sched until the process gives up the locks
		 * it is holding.  This avoids dumb lock loops.
		 * Don't delay if the process is Moribund.
		 * It called sched to die.
		 * But do sched eventually.  This avoids a missing unlock
		 * from hanging the entire kernel. 
		 * But don't reschedule procs holding palloc or procalloc.
		 * Those are far too important to be holding while asleep.
		 *
		 * This test is not exact.  There can still be a few instructions
		 * in the middle of taslock when a process holds a lock
		 * but Lock.p has not yet been initialized.
		 */
		if(up->nlocks)
		if(up->state != Moribund)
		if(up->delaysched < 20
		|| palloc.Lock.p == up
		|| procalloc.Lock.p == up){
			up->delaysched++;
 			delayedscheds++;
			return;
		}
		up->delaysched = 0;

		splhi();

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

		procsave(up);
		if(setlabel(&up->sched)){
			procrestore(up);
			spllo();
			return;
		}
		gotolabel(&m->sched);
	}
	p = runproc();
	if(p->edf == nil){
		updatecpu(p);
		p->priority = reprioritize(p);
	}
	if(p != m->readied)
		m->schedticks = m->ticks + HZ/10;
	m->readied = nil;
	up = p;
	up->state = Running;
	up->mach = MACHP(m->machno);
	m->proc = up;
	mmuswitch(up);
	gotolabel(&up->sched);
}
コード例 #4
0
ファイル: proc.c プロジェクト: npe9/harvey
/*
 *  If changing this routine, look also at sleep().  It
 *  contains a copy of the guts of sched().
 */
void
sched(void)
{
	Mach *m = machp();
	Proc *p;

	if(m->ilockdepth)
		panic("cpu%d: ilockdepth %d, last lock %#p at %#p, sched called from %#p",
			m->machno,
			m->ilockdepth,
			m->externup? m->externup->lastilock: nil,
			(m->externup && m->externup->lastilock)? m->externup->lastilock->_pc: 0,
			getcallerpc(&p+2));

	kstackok();
	if(m->externup){
		/*
		 * Delay the sched until the process gives up the locks
		 * it is holding.  This avoids dumb lock loops.
		 * Don't delay if the process is Moribund.
		 * It called sched to die.
		 * But do sched eventually.  This avoids a missing unlock
		 * from hanging the entire kernel.
		 * But don't reschedule procs holding palloc or procalloc.
		 * Those are far too important to be holding while asleep.
		 *
		 * This test is not exact.  There can still be a few
		 * instructions in the middle of taslock when a process
		 * holds a lock but Lock.p has not yet been initialized.
		 */
		if(m->externup->nlocks)
		if(m->externup->state != Moribund)
		if(m->externup->delaysched < 20
		|| pga.Lock.p == m->externup
		|| procalloc.Lock.p == m->externup){
			m->externup->delaysched++;
 			run.delayedscheds++;
			return;
		}
		m->externup->delaysched = 0;

		splhi();
		/* statistics */
		if(m->externup->nqtrap == 0 && m->externup->nqsyscall == 0)
			m->externup->nfullq++;
		m->cs++;

		procsave(m->externup);
		mmuflushtlb(m->pml4->pa);
		if(setlabel(&m->externup->sched)){
			procrestore(m->externup);
			spllo();
			return;
		}
		/*debug*/gotolabel(&m->sched);
	}

	m->inidle = 1;
	p = runproc();	/* core 0 never returns */
	m->inidle = 0;

	if(!p->edf){
		updatecpu(p);
		p->priority = reprioritize(p);
	}
	if(nosmp){
		if(p != m->readied)
			m->schedticks = m->ticks + HZ/10;
	m->readied = 0;
	}
	m->externup = p;
	m->qstart = m->ticks;
	m->externup->nqtrap = 0;
	m->externup->nqsyscall = 0;
	m->externup->state = Running;
	//m->externup->mach = m;
	m->externup->mach = sys->machptr[m->machno];
	m->proc = m->externup;
//	iprint("m->externup->sched.sp %p * %p\n", up->sched.sp,
//		*(void **) m->externup->sched.sp);
	mmuswitch(m->externup);

	assert(!m->externup->wired || m->externup->wired == m);
	if (0) hi("gotolabel\n");
	/*debug*/gotolabel(&m->externup->sched);
}
コード例 #5
0
ファイル: proc.c プロジェクト: 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);
}