/* * 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; }
/* * exit kernel either on a panic or user request */ void exit(int code) { shutdown(code); splhi(); if (m->machno == 0) archreboot(); else { intrcpushutdown(); stopcpu(m->machno); for (;;) idlehands(); } }
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 */ }
/* * pick a process to run */ Proc* runproc(void) { Schedq *rq; Proc *p; ulong start, now; int i; void (*pt)(Proc*, int, vlong); start = perfticks(); /* cooperative scheduling until the clock ticks */ if((p = m->readied) != nil && p->mach == nil && p->state == Ready && (p->wired == nil || p->wired == MACHP(m->machno)) && runq[Nrq-1].head == nil && runq[Nrq-2].head == nil){ skipscheds++; rq = &runq[p->priority]; goto found; } 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 = &runq[Nrq-1]; rq >= runq; rq--){ for(p = rq->head; p != nil; p = p->rnext){ if(p->mp == nil || p->mp == MACHP(m->machno) || (p->wired == nil && 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(rq, p); if(p == nil) goto loop; p->state = Scheding; p->mp = MACHP(m->machno); if(edflock(p)){ edfrun(p, rq == &runq[PriEdf]); /* start deadline timer and do admin */ edfunlock(); } pt = proctrace; if(pt != nil) pt(p, SRun, 0); return p; }
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; }
/* * Scheduling thread run as the main loop of cpu 0 * Used in AMP sched. */ static void mach0sched(void) { Mach *m = machp(); Schedq *rq; Proc *p; Mach *mp; uint32_t start, now; int n, i; //, j; assert(m->machno == 0); acmodeset(NIXKC); /* we don't time share any more */ n = 0; start = perfticks(); loop: /* * find a ready process that we might run. */ spllo(); for(rq = &run.runq[Nrq-1]; rq >= run.runq; rq--) for(p = rq->head; p; p = p->rnext){ /* * wired processes may only run when their core is available. */ if(p->wired != nil){ if(p->wired->proc == nil) goto found; continue; } /* * find a ready process that did run at an available core * or one that has not moved for some time. */ if(p->mp == nil || p->mp->proc == nil || n>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; n++; goto loop; found: assert(m->machno == 0); splhi(); /* * find a core for this process, but honor wiring. */ mp = p->wired; if(mp != nil){ if(mp->proc != nil) goto loop; }else{ for(i = 0; i < MACHMAX; i++){ /*j = pickcore(p->color, i); if((mp = sys->machptr[j]) != nil && mp->online && mp->nixtype == NIXTC){*/ if((mp = sys->machptr[i]) != nil){ // && mp->online && mp->nixtype == NIXTC){ if(mp != m && mp->proc == nil) break; } } if(i == MACHMAX){ preemptfor(p); goto loop; } } p = dequeueproc(&run, rq, p); mp->proc = p; if(p != nil){ p->state = Scheding; p->mp = mp; } n = 0; goto loop; }
Proc* runproc(void) { Proc *p, *l; Schedq *rq, *erq; erq = runq + Nrq - 1; loop: splhi(); for(rq = runq; rq->head == 0; rq++) if(rq >= erq) { idlehands(); spllo(); goto loop; } if(!canlock(runq)) goto loop; /* choose first one we last ran on this processor at this level or hasn't moved recently */ l = nil; for(p = rq->head; p != nil; p = p->rnext) if(p->mp == nil || p->mp == MACHP(m->machno) || p->movetime < MACHP(0)->ticks) break; if(p == nil) p = rq->head; /* p->mach==0 only when process state is saved */ if(p == 0 || p->mach) { unlock(runq); goto loop; } if(p->rnext == nil) rq->tail = l; if(l) l->rnext = p->rnext; else rq->head = p->rnext; if(rq->head == nil){ rq->tail = nil; occupied &= ~(1<<p->pri); } nrdy--; if(p->dbgstop){ p->state = Stopped; unlock(runq); goto loop; } if(p->state != Ready) print("runproc %s %lud %s\n", p->text, p->pid, statename[p->state]); unlock(runq); p->state = Scheding; if(p->mp != MACHP(m->machno)) p->movetime = MACHP(0)->ticks + HZ/10; p->mp = MACHP(m->machno); /* if(edflock(p)){ edfrun(p, rq == &runq[PriEdf]); // start deadline timer and do admin edfunlock(); } */ return p; }