int reprioritize(Proc*);
ulong delayedscheds; /* statistics */
-long skipscheds;
-long preempts;
-ulong load;
+ulong skipscheds;
+ulong preempts;
+ulong load;
static struct Procalloc
{
edfrecord(up);
m->proc = nil;
switch(up->state) {
+ default:
+ updatecpu(up);
+ break;
case Running:
ready(up);
break;
mmurelease(up);
unlock(&palloc);
- up->mach = nil;
updatecpu(up);
+ up->mach = nil;
up->qnext = procalloc.free;
procalloc.free = up;
unlock(&procalloc);
sched();
}
+ coherence();
up->mach = nil;
- updatecpu(up);
up = nil;
}
sched();
if(up->state != Moribund)
if(up->delaysched < 20
|| palloc.Lock.p == up
+ || fscache.Lock.p == up
|| procalloc.Lock.p == up){
up->delaysched++;
delayedscheds++;
/* unless preempted, get to run for at least 100ms */
if(anyhigher()
- || (!up->fixedpri && m->ticks > m->schedticks && anyready())){
+ || (!up->fixedpri && (long)(m->ticks - m->schedticks) > 0 && anyready())){
m->readied = nil; /* avoid cooperative scheduling */
up->delaysched++;
}
void
updatecpu(Proc *p)
{
- int n, t, ocpu;
- int D = schedgain*HZ*Scaling;
+ ulong t, ocpu, n, D;
if(p->edf != nil)
return;
t = MACHP(0)->ticks*Scaling + Scaling/2;
n = t - p->lastupdate;
- p->lastupdate = t;
-
if(n == 0)
return;
+ p->lastupdate = t;
+
+ D = schedgain*HZ*Scaling;
if(n > D)
n = D;
t = (t*(D-n))/D;
p->cpu = 1000 - t;
}
-
-//iprint("pid %d %s for %d cpu %d -> %d\n", p->pid,p==up?"active":"inactive",n, ocpu,p->cpu);
+//iprint("pid %lud %s for %lud cpu %lud -> %lud\n", p->pid,p==up?"active":"inactive",n, ocpu,p->cpu);
}
/*
ratio = p->basepri;
if(ratio < 0)
panic("reprioritize");
-//iprint("pid %d cpu %d load %d fair %d pri %d\n", p->pid, p->cpu, load, fairshare, ratio);
+//iprint("pid %lud cpu %lud load %d fair %d pri %d\n", p->pid, p->cpu, load, fairshare, ratio);
return ratio;
}
static void
rebalance(void)
{
- int pri, npri, t, x;
+ int pri, npri, x;
Schedq *rq;
Proc *p;
+ ulong t;
t = m->ticks;
if(t - balancetime < HZ)
p = rq->head;
if(p == nil)
continue;
- if(p->mp != MACHP(m->machno))
- continue;
if(pri == p->basepri)
continue;
updatecpu(p);
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.
+ * or one that can be moved to this processor.
*/
spllo();
for(i = 0;; i++){
procalloc.free = p->qnext;
unlock(&procalloc);
- p->state = Scheding;
+ assert(p->state == Dead);
p->psstate = "New";
p->mach = nil;
p->eql = nil;
p->syscalltrace = nil;
p->notepending = 0;
p->ureg = nil;
+ p->dbgreg = nil;
p->privatemem = 0;
p->noswap = 0;
+ p->nerrlab = 0;
p->errstr = p->errbuf0;
p->syserrstr = p->errbuf1;
p->errbuf0[0] = '\0';
p->nlocks = 0;
p->delaysched = 0;
p->trace = 0;
- kstrdup(&p->user, "*nouser");
- kstrdup(&p->text, "*notext");
- kstrdup(&p->args, "");
p->nargs = 0;
p->setargs = 0;
memset(p->seg, 0, sizeof p->seg);
p->parentpid = 0;
- p->noteid = pidalloc(p);
+ p->noteid = 0;
if(p->kstack == nil)
p->kstack = smalloc(KSTACK);
p = t->ta;
trend = p->trend;
- p->trend = nil;
- if(trend != nil)
+ if(trend != nil){
+ p->trend = nil;
wakeup(trend);
+ }
}
void
tsleep(Rendez *r, int (*fn)(void*), void *arg, ulong ms)
{
if(up->tt != nil){
- print("tsleep: timer active: mode %d, tf %#p\n", up->tmode, up->tf);
+ print("%s %lud: tsleep timer active: mode %d, tf %#p, pc %#p\n",
+ up->text, up->pid, up->tmode, up->tf, getcallerpc(&r));
timerdel(up);
}
up->tns = MS2NS(ms);
timeradd(up);
if(waserror()){
+ up->trend = nil;
timerdel(up);
nexterror();
}
sleep(r, tfn, arg);
- if(up->tt != nil)
- timerdel(up);
- up->twhen = 0;
+ up->trend = nil;
+ timerdel(up);
poperror();
}
return 0;
}
- if(n != nil && flag != NUser && (p->notify == 0 || p->notified))
+ if(n != nil && flag != NUser && (p->notify == nil || p->notified))
p->nnote = 0;
ret = 0;
{
Proc *p;
Segment **s, **es;
- long utime, stime;
+ ulong utime, stime;
Waitq *wq;
Fgrp *fgrp;
Egrp *egrp;
Chan *dot;
void (*pt)(Proc*, int, vlong);
+ up->fpstate &= ~FPillegal;
up->alarm = 0;
- if(up->tt != nil)
- timerdel(up);
+ timerdel(up);
pt = proctrace;
if(pt != nil)
pt(up, SDead, 0);
* if not a kernel process and have a parent,
* do some housekeeping.
*/
- if(up->kp == 0 && up->parentpid != 0) {
+ if(up->kp)
+ goto Nowait;
+
+ p = up->parent;
+ if(p != nil){
+ if(p->pid != up->parentpid || p->state == Broken)
+ goto Nowait;
+
wq = smalloc(sizeof(Waitq));
wq->w.pid = up->pid;
utime = up->time[TUser] + up->time[TCUser];
else
wq->w.msg[0] = '\0';
- p = up->parent;
lock(&p->exl);
/*
* Check that parent is still alive.
if(wq != nil)
free(wq);
}
- else if(up->kp == 0 && up->parent == nil){
+ else if(up->parentpid == 0){
if(exitstr == nil)
exitstr = "unknown";
panic("boot process died: %s", exitstr);
}
+Nowait:
if(!freemem)
addbroken(up);
free(up->syscalltrace);
up->syscalltrace = nil;
}
+ if(up->watchpt != nil){
+ free(up->watchpt);
+ up->watchpt = nil;
+ }
+ up->nwatchpt = 0;
qunlock(&up->debug);
/* Sched must not loop for these locks */
}
/*
- * wait till all processes have flushed their mmu
- * state about segement s
+ * wait till all matching processes have flushed their mmu
*/
-void
-procflushseg(Segment *s)
+static void
+procflushmmu(int (*match)(Proc*, void*), void *a)
{
- int i, ns, nm, nwait;
+ Proc *await[MAXMACH];
+ int i, nm, nwait;
Proc *p;
/*
- * tell all processes with this
- * segment to flush their mmu's
+ * tell all matching processes to flush their mmu's
*/
+ memset(await, 0, conf.nmach*sizeof(await[0]));
nwait = 0;
- for(i=0; i<conf.nproc; i++) {
+ for(i = 0; i < conf.nproc; i++){
p = &procalloc.arena[i];
- if(p->state == Dead)
- continue;
- for(ns = 0; ns < NSEG; ns++)
- if(p->seg[ns] == s){
- p->newtlb = 1;
- for(nm = 0; nm < conf.nmach; nm++){
- if(MACHP(nm)->proc == p){
- MACHP(nm)->flushmmu = 1;
+ if(p->state != Dead && (*match)(p, a)){
+ p->newtlb = 1;
+ for(nm = 0; nm < conf.nmach; nm++){
+ if(MACHP(nm)->proc == p){
+ coherence();
+ MACHP(nm)->flushmmu = 1;
+ if(await[nm] == nil)
nwait++;
- }
+ await[nm] = p;
}
- break;
}
+ }
}
- if(nwait == 0)
- return;
-
/*
* wait for all other processors to take a clock interrupt
* and flush their mmu's
*/
- for(nm = 0; nm < conf.nmach; nm++)
- while(m->machno != nm && MACHP(nm)->flushmmu)
- sched();
+ for(;;){
+ if(nwait == 0 || nwait == 1 && await[m->machno] != nil)
+ break;
+
+ sched();
+
+ for(nm = 0; nm < conf.nmach; nm++){
+ p = await[nm];
+ if(p != nil && (MACHP(nm)->proc != p || MACHP(nm)->flushmmu == 0)){
+ await[nm] = nil;
+ nwait--;
+ }
+ }
+ }
+}
+
+static int
+matchseg(Proc *p, void *a)
+{
+ int ns;
+
+ for(ns = 0; ns < NSEG; ns++){
+ if(p->seg[ns] == a)
+ return 1;
+ }
+ return 0;
+}
+void
+procflushseg(Segment *s)
+{
+ procflushmmu(matchseg, s);
+}
+
+static int
+matchpseg(Proc *p, void *a)
+{
+ Segment *s;
+ int ns;
+
+ for(ns = 0; ns < NSEG; ns++){
+ s = p->seg[ns];
+ if(s != nil && s->pseg == a)
+ return 1;
+ }
+ return 0;
+}
+void
+procflushpseg(Physseg *ps)
+{
+ procflushmmu(matchpseg, ps);
+}
+
+static int
+matchother(Proc *p, void *a)
+{
+ return p != a;
+}
+void
+procflushothers(void)
+{
+ procflushmmu(matchother, up);
}
void
for(rq = &runq[Nrq-1]; rq >= runq; rq--){
if(rq->head == nil)
continue;
- print("rq%ld:", rq-runq);
+ print("rq%zd:", rq-runq);
for(p = rq->head; p != nil; p = p->rnext)
print(" %lud(%lud)", p->pid, m->ticks - p->readytime);
print("\n");
void
kproc(char *name, void (*func)(void *), void *arg)
{
- Proc *p;
static Pgrp *kpgrp;
+ Proc *p;
p = newproc();
- p->psstate = nil;
- p->procmode = 0640;
- p->kp = 1;
- p->noswap = 1;
- p->scallnr = up->scallnr;
- p->s = up->s;
- p->nerrlab = 0;
- p->slash = up->slash;
- p->dot = up->dot;
- if(p->dot != nil)
- incref(p->dot);
+ if(up != nil){
+ p->slash = up->slash;
+ p->dot = up->slash; /* unlike fork, do not inherit the dot for kprocs */
+ if(p->dot != nil)
+ incref(p->dot);
+ } else {
+ p->slash = nil;
+ p->dot = nil;
+ }
- memmove(p->note, up->note, sizeof(p->note));
- p->nnote = up->nnote;
+ p->nnote = 0;
+ p->notify = nil;
p->notified = 0;
- p->lastnote = up->lastnote;
- p->notify = up->notify;
- p->ureg = nil;
- p->dbgreg = nil;
- procpriority(p, PriKproc, 0);
+ p->procmode = 0640;
+ p->noswap = 1;
+ p->kp = 1;
kprocchild(p, func, arg);
- kstrdup(&p->user, eve);
kstrdup(&p->text, name);
+ kstrdup(&p->user, eve);
+ kstrdup(&p->args, "");
+
if(kpgrp == nil)
kpgrp = newpgrp();
p->pgrp = kpgrp;
incref(kpgrp);
+ p->insyscall = 1;
memset(p->time, 0, sizeof(p->time));
p->time[TReal] = MACHP(0)->ticks;
+
+ pidalloc(p);
+
+ procpriority(p, PriKproc, 0);
+
+ p->psstate = nil;
ready(p);
}
* reasoning.
*/
void
-procctl(Proc *p)
+procctl(void)
{
char *state;
ulong s;
- switch(p->procctl) {
+ switch(up->procctl) {
case Proc_exitbig:
spllo();
+ up->fpstate &= ~FPillegal;
pprint("Killed: Insufficient physical memory\n");
pexit("Killed: Insufficient physical memory", 1);
pexit("Killed", 1);
case Proc_traceme:
- if(p->nnote == 0)
+ if(up->nnote == 0)
return;
/* No break */
case Proc_stopme:
- p->procctl = 0;
- state = p->psstate;
- p->psstate = "Stopped";
+ up->procctl = 0;
+ state = up->psstate;
+ up->psstate = "Stopped";
/* free a waiting debugger */
s = spllo();
- qlock(&p->debug);
- if(p->pdbg != nil) {
- wakeup(&p->pdbg->sleep);
- p->pdbg = nil;
+ qlock(&up->debug);
+ if(up->pdbg != nil) {
+ wakeup(&up->pdbg->sleep);
+ up->pdbg = nil;
}
- qunlock(&p->debug);
+ qunlock(&up->debug);
splhi();
- p->state = Stopped;
+ up->state = Stopped;
sched();
- p->psstate = state;
+ up->psstate = state;
splx(s);
return;
}
error(buf);
}
+ulong
+procpagecount(Proc *p)
+{
+ Segment *s;
+ ulong pages;
+ int i;
+
+ eqlock(&p->seglock);
+ if(waserror()){
+ qunlock(&p->seglock);
+ nexterror();
+ }
+ pages = 0;
+ for(i=0; i<NSEG; i++){
+ if((s = p->seg[i]) != nil){
+ eqlock(s);
+ pages += mcountseg(s);
+ qunlock(s);
+ }
+ }
+ qunlock(&p->seglock);
+ poperror();
+
+ return pages;
+}
+
void
killbig(char *why)
{
kp = nil;
ep = procalloc.arena+conf.nproc;
for(p = procalloc.arena; p < ep; p++) {
- if(p->state == Dead || p->kp || !canqlock(&p->seglock))
+ if(p->state == Dead || p->kp)
continue;
- l = 0;
- for(i=1; i<NSEG; i++) {
- s = p->seg[i];
- if(s == nil || !canqlock(s))
- continue;
- l += mcountseg(s);
- qunlock(s);
- }
- qunlock(&p->seglock);
- if(l > max && ((p->procmode&0222) || strcmp(eve, p->user)!=0)) {
+ if((p->noswap || (p->procmode & 0222) == 0) && strcmp(eve, p->user) == 0)
+ continue;
+ l = procpagecount(p);
+ if(l > max){
kp = p;
max = l;
}
}
- if(kp == nil || !canqlock(&kp->seglock))
+ if(kp == nil)
return;
print("%lud: %s killed: %s\n", kp->pid, kp->text, why);
+ qlock(&kp->seglock);
for(p = procalloc.arena; p < ep; p++) {
if(p->state == Dead || p->kp)
continue;
kp->procctl = Proc_exitbig;
for(i = 0; i < NSEG; i++) {
s = kp->seg[i];
- if(s != nil && canqlock(s)) {
- mfreeseg(s, s->base, (s->top - s->base)/BY2PG);
- qunlock(s);
+ if(s == nil)
+ continue;
+ switch(s->type & SG_TYPE){
+ case SG_SHARED:
+ case SG_PHYSICAL:
+ case SG_FIXED:
+ case SG_STICKY:
+ continue;
}
+ qlock(s);
+ mfreeseg(s, s->base, (s->top - s->base)/BY2PG);
+ qunlock(s);
}
qunlock(&kp->seglock);
}
n = perfticks();
per = n - m->perf.last;
m->perf.last = n;
- per = (m->perf.period*(HZ-1) + per)/HZ;
+ per = ((uvlong)m->perf.period*(HZ-1) + per)/HZ;
if(per != 0)
m->perf.period = per;
- m->perf.avg_inidle = (m->perf.avg_inidle*(HZ-1)+m->perf.inidle)/HZ;
+ m->perf.avg_inidle = ((uvlong)m->perf.avg_inidle*(HZ-1)+m->perf.inidle)/HZ;
m->perf.inidle = 0;
- m->perf.avg_inintr = (m->perf.avg_inintr*(HZ-1)+m->perf.inintr)/HZ;
+ m->perf.avg_inintr = ((uvlong)m->perf.avg_inintr*(HZ-1)+m->perf.inintr)/HZ;
m->perf.inintr = 0;
/* only one processor gets to compute system load averages */
*/
n = nrun;
nrun = 0;
- n = (nrdy+n)*1000;
- m->load = (m->load*(HZ-1)+n)/HZ;
+ n = (nrdy+n)*1000*100;
+ load = ((uvlong)load*(HZ-1)+n)/HZ;
+ m->load = load/100;
}
int