提交 e661e06a 创建 作者: Robert Morris's avatar Robert Morris

passes all usertests

BUT can't figure out how to fix bad kill()/condvar interaction
上级 ebba3c91
......@@ -29,18 +29,17 @@ cv_sleep(struct condvar *cv, struct spinlock *lk)
release(lk);
if(proc->cv_next)
panic("cv_sleep cv_next");
acquire(&proc->lock);
if(proc->cv_next || proc->oncv)
panic("cv_sleep cv_next");
proc->cv_next = cv->waiters;
cv->waiters = proc;
acquire(&proc->lock);
proc->state = SLEEPING;
proc->oncv = cv;
release(&cv->lock);
proc->state = SLEEPING;
sched();
release(&proc->lock);
......@@ -55,11 +54,13 @@ cv_wakeup(struct condvar *cv)
{
acquire(&cv->lock);
while(cv->waiters) {
if(cv->waiters->state != SLEEPING)
struct proc *p = cv->waiters;
if(p->state != SLEEPING || p->oncv != cv)
panic("cv_wakeup");
struct proc *nxt = cv->waiters->cv_next;
cv->waiters->cv_next = 0;
addrun(cv->waiters);
struct proc *nxt = p->cv_next;
p->cv_next = 0;
p->oncv = 0;
addrun(p);
cv->waiters = nxt;
}
release(&cv->lock);
......
......@@ -168,13 +168,22 @@ userinit(void)
addrun(p);
}
// Grow current process's memory by n bytes.
// Grow/shrink current process's memory by n bytes.
// Growing may allocate vmas and physical memory,
// but avoids interfering with any existing vma.
// Assumes vmas around proc->brk are part of the growable heap.
// Shrinking just decreases proc->brk; doesn't deallocate.
// Return 0 on success, -1 on failure.
int
growproc(int n)
{
struct vmap *m = proc->vmap;
if(n < 0 && 0 - n <= proc->brk){
proc->brk += n;
return 0;
}
if(n < 0 || n > USERTOP || proc->brk + n > USERTOP)
return -1;
......@@ -549,16 +558,23 @@ kill(int pid)
acquire(&p->lock);
if(p->pid == pid){
p->killed = 1;
// Wake process from sleep if necessary.
if(p->state == SLEEPING) {
p->state = RUNNABLE;
STAILQ_INSERT_TAIL(&runq->runq, p, run_next);
}
if(p->state == SLEEPING){
// XXX
// we need to wake p up if it is cv_sleep()ing.
// can't change p from SLEEPING to RUNNABLE since that
// would make some condvar->waiters a dangling reference,
// and the non-zero p->cv_next will cause a future panic.
// can't call cv_wakeup(p->oncv) since that results in
// deadlock (addrun() acquires p->lock).
// can't release p->lock then call cv_wakeup() since the
// cv might be deallocated while we're using it
// (pipes dynamically allocate condvars).
}
release(&p->lock);
release(&ptables[c].lock);
return 0;
}
acquire(&p->lock);
release(&p->lock);
}
release(&ptables[c].lock);
}
......
......@@ -75,7 +75,8 @@ struct proc {
struct proc *parent; // Parent process
struct trapframe *tf; // Trap frame for current syscall
struct context *context; // swtch() here to run process
struct proc *cv_next; // Linked list of processes waiting for condvar
struct condvar *oncv; // Where it is sleeping, for kill()
struct proc *cv_next; // Linked list of processes waiting for oncv
int killed; // If non-zero, have been killed
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
......
......@@ -1290,7 +1290,6 @@ sbrktest(void)
exit();
}
#if 0
// can one de-allocate?
a = sbrk(0);
c = sbrk(-4096);
......@@ -1311,6 +1310,7 @@ sbrktest(void)
printf(stdout, "sbrk re-allocation failed, a %x c %x\n", a, c);
exit();
}
#if 0
if(*lastaddr == 99){
// should be zero
printf(stdout, "sbrk de-allocation didn't really deallocate\n");
......@@ -1477,7 +1477,7 @@ main(int argc, char *argv[])
bigargtest();
bsstest();
// sbrktest();
sbrktest();
validatetest();
opentest();
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论