提交 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) ...@@ -29,18 +29,17 @@ cv_sleep(struct condvar *cv, struct spinlock *lk)
release(lk); release(lk);
if(proc->cv_next) acquire(&proc->lock);
panic("cv_sleep cv_next");
if(proc->cv_next || proc->oncv)
panic("cv_sleep cv_next");
proc->cv_next = cv->waiters; proc->cv_next = cv->waiters;
cv->waiters = proc; cv->waiters = proc;
proc->state = SLEEPING;
acquire(&proc->lock); proc->oncv = cv;
release(&cv->lock); release(&cv->lock);
proc->state = SLEEPING;
sched(); sched();
release(&proc->lock); release(&proc->lock);
...@@ -55,11 +54,13 @@ cv_wakeup(struct condvar *cv) ...@@ -55,11 +54,13 @@ cv_wakeup(struct condvar *cv)
{ {
acquire(&cv->lock); acquire(&cv->lock);
while(cv->waiters) { while(cv->waiters) {
if(cv->waiters->state != SLEEPING) struct proc *p = cv->waiters;
if(p->state != SLEEPING || p->oncv != cv)
panic("cv_wakeup"); panic("cv_wakeup");
struct proc *nxt = cv->waiters->cv_next; struct proc *nxt = p->cv_next;
cv->waiters->cv_next = 0; p->cv_next = 0;
addrun(cv->waiters); p->oncv = 0;
addrun(p);
cv->waiters = nxt; cv->waiters = nxt;
} }
release(&cv->lock); release(&cv->lock);
......
...@@ -168,13 +168,22 @@ userinit(void) ...@@ -168,13 +168,22 @@ userinit(void)
addrun(p); 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. // Return 0 on success, -1 on failure.
int int
growproc(int n) growproc(int n)
{ {
struct vmap *m = proc->vmap; 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) if(n < 0 || n > USERTOP || proc->brk + n > USERTOP)
return -1; return -1;
...@@ -549,16 +558,23 @@ kill(int pid) ...@@ -549,16 +558,23 @@ kill(int pid)
acquire(&p->lock); acquire(&p->lock);
if(p->pid == pid){ if(p->pid == pid){
p->killed = 1; p->killed = 1;
// Wake process from sleep if necessary. if(p->state == SLEEPING){
if(p->state == SLEEPING) { // XXX
p->state = RUNNABLE; // we need to wake p up if it is cv_sleep()ing.
STAILQ_INSERT_TAIL(&runq->runq, p, run_next); // 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(&p->lock);
release(&ptables[c].lock); release(&ptables[c].lock);
return 0; return 0;
} }
acquire(&p->lock); release(&p->lock);
} }
release(&ptables[c].lock); release(&ptables[c].lock);
} }
......
...@@ -75,7 +75,8 @@ struct proc { ...@@ -75,7 +75,8 @@ struct proc {
struct proc *parent; // Parent process struct proc *parent; // Parent process
struct trapframe *tf; // Trap frame for current syscall struct trapframe *tf; // Trap frame for current syscall
struct context *context; // swtch() here to run process 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 int killed; // If non-zero, have been killed
struct file *ofile[NOFILE]; // Open files struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory struct inode *cwd; // Current directory
......
...@@ -1290,7 +1290,6 @@ sbrktest(void) ...@@ -1290,7 +1290,6 @@ sbrktest(void)
exit(); exit();
} }
#if 0
// can one de-allocate? // can one de-allocate?
a = sbrk(0); a = sbrk(0);
c = sbrk(-4096); c = sbrk(-4096);
...@@ -1311,6 +1310,7 @@ sbrktest(void) ...@@ -1311,6 +1310,7 @@ sbrktest(void)
printf(stdout, "sbrk re-allocation failed, a %x c %x\n", a, c); printf(stdout, "sbrk re-allocation failed, a %x c %x\n", a, c);
exit(); exit();
} }
#if 0
if(*lastaddr == 99){ if(*lastaddr == 99){
// should be zero // should be zero
printf(stdout, "sbrk de-allocation didn't really deallocate\n"); printf(stdout, "sbrk de-allocation didn't really deallocate\n");
...@@ -1477,7 +1477,7 @@ main(int argc, char *argv[]) ...@@ -1477,7 +1477,7 @@ main(int argc, char *argv[])
bigargtest(); bigargtest();
bsstest(); bsstest();
// sbrktest(); sbrktest();
validatetest(); validatetest();
opentest(); opentest();
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论