提交 8cb54158 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

fix various scheduler bugs

上级 71c80cc0
...@@ -33,8 +33,6 @@ cv_sleep(struct condvar *cv, struct spinlock *lk) ...@@ -33,8 +33,6 @@ cv_sleep(struct condvar *cv, struct spinlock *lk)
cv->waiters = proc; // XXX should be queue cv->waiters = proc; // XXX should be queue
delrun(proc);
acquire(&proc->lock); acquire(&proc->lock);
release(&cv->lock); release(&cv->lock);
...@@ -45,15 +43,8 @@ cv_sleep(struct condvar *cv, struct spinlock *lk) ...@@ -45,15 +43,8 @@ cv_sleep(struct condvar *cv, struct spinlock *lk)
release(&proc->lock); release(&proc->lock);
acquire(&cv->lock);
// Tidy up.
cv->waiters = 0;
// Reacquire original lock. // Reacquire original lock.
acquire(lk); acquire(lk);
release(&cv->lock);
} }
void void
...@@ -62,6 +53,7 @@ cv_wakeup(struct condvar *cv) ...@@ -62,6 +53,7 @@ cv_wakeup(struct condvar *cv)
acquire(&cv->lock); acquire(&cv->lock);
if (cv->waiters != 0) { if (cv->waiters != 0) {
addrun(cv->waiters); addrun(cv->waiters);
cv->waiters = 0;
} }
release(&cv->lock); release(&cv->lock);
} }
...@@ -102,7 +102,6 @@ int pipewrite(struct pipe*, char*, int); ...@@ -102,7 +102,6 @@ int pipewrite(struct pipe*, char*, int);
// proc.c // proc.c
void addrun(struct proc *); void addrun(struct proc *);
struct proc* copyproc(struct proc*); struct proc* copyproc(struct proc*);
void delrun(struct proc*);
void exit(void); void exit(void);
int fork(int); int fork(int);
int growproc(int); int growproc(int);
...@@ -184,3 +183,4 @@ int pagefault(pde_t*, struct vmap *, uint); ...@@ -184,3 +183,4 @@ int pagefault(pde_t*, struct vmap *, uint);
// number of elements in fixed-size array // number of elements in fixed-size array
#define NELEM(x) (sizeof(x)/sizeof((x)[0])) #define NELEM(x) (sizeof(x)/sizeof((x)[0]))
#define NULL 0
...@@ -36,6 +36,7 @@ pinit(void) ...@@ -36,6 +36,7 @@ pinit(void)
runqs[c].name[0] = (char) (c + '0'); runqs[c].name[0] = (char) (c + '0');
safestrcpy(runqs[c].name+1, "runq", MAXNAME-1); safestrcpy(runqs[c].name+1, "runq", MAXNAME-1);
initlock(&runqs[c].lock, runqs[c].name); initlock(&runqs[c].lock, runqs[c].name);
STAILQ_INIT(&runqs[c].runq);
} }
} }
...@@ -90,15 +91,13 @@ static void ...@@ -90,15 +91,13 @@ static void
addrun1(struct runq *rq, struct proc *p) addrun1(struct runq *rq, struct proc *p)
{ {
struct proc *q; struct proc *q;
SLIST_FOREACH(q, &rq->runq, run_next) { STAILQ_FOREACH(q, &rq->runq, run_next)
if (q == p) { if (q == p)
cprintf("allready on q\n"); panic("addrun1: already on queue");
p->state = RUNNABLE; acquire(&p->lock);
return; p->state = RUNNABLE;
} STAILQ_INSERT_TAIL(&rq->runq, p, run_next);
} release(&p->lock);
p->state = RUNNABLE; // XXX race?
SLIST_INSERT_HEAD(&rq->runq, p, run_next);
} }
void void
...@@ -114,12 +113,15 @@ static void ...@@ -114,12 +113,15 @@ static void
delrun1(struct runq *rq, struct proc *p) delrun1(struct runq *rq, struct proc *p)
{ {
struct proc *q, *nq; struct proc *q, *nq;
SLIST_FOREACH_SAFE(q, &rq->runq, run_next, nq) { STAILQ_FOREACH_SAFE(q, &rq->runq, run_next, nq) {
if (q == p) { if (q == p) {
SLIST_REMOVE(&rq->runq, q, proc, run_next); acquire(&p->lock);
STAILQ_REMOVE(&rq->runq, q, proc, run_next);
release(&p->lock);
return; return;
} }
} }
panic("delrun1: not on runq");
} }
void void
...@@ -289,8 +291,6 @@ exit(void) ...@@ -289,8 +291,6 @@ exit(void)
acquire(&proc->lock); acquire(&proc->lock);
delrun(proc);
// Jump into the scheduler, never to return. // Jump into the scheduler, never to return.
proc->state = ZOMBIE; proc->state = ZOMBIE;
sched(); sched();
...@@ -354,14 +354,15 @@ steal(void) ...@@ -354,14 +354,15 @@ steal(void)
if (c == cpunum()) if (c == cpunum())
continue; continue;
acquire(&runqs[c].lock); acquire(&runqs[c].lock);
SLIST_FOREACH(p, &runqs[c].runq, run_next) { STAILQ_FOREACH(p, &runqs[c].runq, run_next) {
if (p->state == RUNNABLE) { if (p->state != RUNNABLE)
//cprintf("%d: steal %d from %d\n", cpunum(), p->pid, c); panic("non-runnable proc on runq");
delrun1(&runqs[c], p);
release(&runqs[c].lock); // cprintf("%d: steal %d from %d\n", cpunum(), p->pid, c);
addrun(p); delrun1(&runqs[c], p);
return; release(&runqs[c].lock);
} addrun(p);
return;
} }
release(&runqs[c].lock); release(&runqs[c].lock);
} }
...@@ -396,11 +397,13 @@ scheduler(void) ...@@ -396,11 +397,13 @@ scheduler(void)
// Loop over process table looking for process to run. // Loop over process table looking for process to run.
acquire(&runq->lock); acquire(&runq->lock);
SLIST_FOREACH(p, &runq->runq, run_next) { STAILQ_FOREACH(p, &runq->runq, run_next) {
acquire(&p->lock);
if(p->state != RUNNABLE) if(p->state != RUNNABLE)
continue; panic("non-runnable process on runq\n");
acquire(&p->lock); STAILQ_REMOVE(&runq->runq, p, proc, run_next);
release(&runq->lock);
// Switch to chosen process. It is the process's job // Switch to chosen process. It is the process's job
// to release proc->lock and then reacquire it // to release proc->lock and then reacquire it
...@@ -409,9 +412,6 @@ scheduler(void) ...@@ -409,9 +412,6 @@ scheduler(void)
switchuvm(p); switchuvm(p);
p->state = RUNNING; p->state = RUNNING;
// Release runq lock only after setting RUNNING, to prevent stealing.
release(&runq->lock);
mtrace_fcall_register(pid, 0, 0, mtrace_pause); mtrace_fcall_register(pid, 0, 0, mtrace_pause);
mtrace_fcall_register(proc->pid, 0, 0, mtrace_resume); mtrace_fcall_register(proc->pid, 0, 0, mtrace_resume);
mtrace_call_set(1, cpunum()); mtrace_call_set(1, cpunum());
...@@ -424,8 +424,6 @@ scheduler(void) ...@@ -424,8 +424,6 @@ scheduler(void)
// It should have changed its p->state before coming back. // It should have changed its p->state before coming back.
proc = 0; proc = 0;
release(&p->lock); release(&p->lock);
// Cannot loop: process may have been stolen, run_next is another runq.
break; break;
} }
...@@ -463,8 +461,9 @@ sched(void) ...@@ -463,8 +461,9 @@ sched(void)
void void
yield(void) yield(void)
{ {
addrun(proc);
acquire(&proc->lock); //DOC: yieldlock acquire(&proc->lock); //DOC: yieldlock
proc->state = RUNNABLE;
sched(); sched();
release(&proc->lock); release(&proc->lock);
} }
...@@ -498,8 +497,10 @@ kill(int pid) ...@@ -498,8 +497,10 @@ kill(int pid)
if(p->pid == pid){ if(p->pid == pid){
p->killed = 1; p->killed = 1;
// Wake process from sleep if necessary. // Wake process from sleep if necessary.
if(p->state == SLEEPING) if(p->state == SLEEPING) {
addrun1(&runqs[c], p); p->state = RUNNABLE;
STAILQ_INSERT_TAIL(&runq->runq, p, run_next);
}
release(&p->lock); release(&p->lock);
release(&ptables[c].lock); release(&ptables[c].lock);
return 0; return 0;
...@@ -549,7 +550,7 @@ procdump(int c) ...@@ -549,7 +550,7 @@ procdump(int c)
cprintf("\n"); cprintf("\n");
} }
cprintf("runq: "); cprintf("runq: ");
SLIST_FOREACH(q, &runqs[c].runq, run_next) { STAILQ_FOREACH(q, &runqs[c].runq, run_next) {
if(q->state >= 0 && q->state < NELEM(states) && states[q->state]) if(q->state >= 0 && q->state < NELEM(states) && states[q->state])
state = states[q->state]; state = states[q->state];
else else
......
...@@ -70,7 +70,7 @@ struct proc { ...@@ -70,7 +70,7 @@ struct proc {
struct inode *cwd; // Current directory struct inode *cwd; // Current directory
char name[16]; // Process name (debugging) char name[16]; // Process name (debugging)
struct spinlock lock; struct spinlock lock;
SLIST_ENTRY(proc) run_next; STAILQ_ENTRY(proc) run_next;
SLIST_HEAD(childlist, proc) childq; SLIST_HEAD(childlist, proc) childq;
SLIST_ENTRY(proc) child_next; SLIST_ENTRY(proc) child_next;
struct condvar cv; struct condvar cv;
...@@ -103,7 +103,7 @@ struct cpu { ...@@ -103,7 +103,7 @@ struct cpu {
struct runq { struct runq {
char name[MAXNAME]; char name[MAXNAME];
struct spinlock lock; struct spinlock lock;
SLIST_HEAD(runlist, proc) runq; STAILQ_HEAD(runlist, proc) runq;
}; };
struct ptable { struct ptable {
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论