diff options
author | rtm <rtm> | 2006-07-15 12:03:57 +0000 |
---|---|---|
committer | rtm <rtm> | 2006-07-15 12:03:57 +0000 |
commit | 46bbd72f3eeaff9386b2a90af88f3d46b458a0e8 (patch) | |
tree | 31ca93c160a10c50948329b30d27475aa6b38313 /proc.c | |
parent | d9872ffa951291fcc3f7a92c0d235b86435c5714 (diff) | |
download | xv6-labs-46bbd72f3eeaff9386b2a90af88f3d46b458a0e8.tar.gz xv6-labs-46bbd72f3eeaff9386b2a90af88f3d46b458a0e8.tar.bz2 xv6-labs-46bbd72f3eeaff9386b2a90af88f3d46b458a0e8.zip |
no more recursive locks
wakeup1() assumes you hold proc_table_lock
sleep(chan, lock) provides atomic sleep-and-release to wait for condition
ugly code in swtch/scheduler to implement new sleep
fix lots of bugs in pipes, wait, and exit
fix bugs if timer interrupt goes off in schedule()
console locks per line, not per byte
Diffstat (limited to 'proc.c')
-rw-r--r-- | proc.c | 75 |
1 files changed, 52 insertions, 23 deletions
@@ -95,7 +95,6 @@ newproc() np->tf = (struct Trapframe *) (np->kstack + KSTACKSIZE - sizeof(struct Trapframe)); *(np->tf) = *(op->tf); np->tf->tf_regs.reg_eax = 0; // so fork() returns 0 in child - cprintf("newproc pid=%d return to %x:%x tf-%p\n", np->pid, np->tf->tf_cs, np->tf->tf_eip, np->tf); // set up new jmpbuf to start executing at trapret with esp pointing at tf memset(&np->jmpbuf, 0, sizeof np->jmpbuf); @@ -109,8 +108,6 @@ newproc() fd_reference(np->fds[fd]); } - cprintf("newproc %x\n", np); - return np; } @@ -126,18 +123,27 @@ scheduler(void) setjmp(&cpus[cpu()].jmpbuf); op = curproc[cpu()]; + + if(op == 0 || op->mtx != &proc_table_lock) + acquire1(&proc_table_lock, op); + if(op){ if(op->newstate <= 0 || op->newstate > ZOMBIE) panic("scheduler"); op->state = op->newstate; op->newstate = -1; + if(op->mtx){ + struct spinlock *mtx = op->mtx; + op->mtx = 0; + if(mtx != &proc_table_lock) + release1(mtx, op); + } } // find a runnable process and switch to it curproc[cpu()] = 0; np = cpus[cpu()].lastproc + 1; while(1){ - acquire(&proc_table_lock); for(i = 0; i < NPROC; i++){ if(np >= &proc[NPROC]) np = &proc[0]; @@ -148,11 +154,13 @@ scheduler(void) if(i < NPROC){ np->state = RUNNING; - release(&proc_table_lock); + release1(&proc_table_lock, op); break; } - release(&proc_table_lock); + release1(&proc_table_lock, op); + op = 0; + acquire(&proc_table_lock); np = &proc[0]; } @@ -180,36 +188,56 @@ void swtch(int newstate) { struct proc *p = curproc[cpu()]; + if(p == 0) panic("swtch no proc"); - if(p->locks != 0) + if(p->mtx == 0 && p->locks != 0) panic("swtch w/ locks"); + if(p->mtx && p->locks != 1) + panic("swtch w/ locks 1"); + if(p->mtx && p->mtx->locked == 0) + panic("switch w/ lock but not held"); + if(p->locks && (read_eflags() & FL_IF)) + panic("swtch w/ lock but FL_IF"); + p->newstate = newstate; // basically an argument to scheduler() if(setjmp(&p->jmpbuf) == 0) longjmp(&cpus[cpu()].jmpbuf); } void -sleep(void *chan) +sleep(void *chan, struct spinlock *mtx) { struct proc *p = curproc[cpu()]; + if(p == 0) panic("sleep"); + p->chan = chan; + p->mtx = mtx; // scheduler will release it + swtch(WAITING); + + if(mtx) + acquire(mtx); + p->chan = 0; } void -wakeup(void *chan) +wakeup1(void *chan) { struct proc *p; - acquire(&proc_table_lock); - for(p = proc; p < &proc[NPROC]; p++){ - if(p->state == WAITING && p->chan == chan){ + for(p = proc; p < &proc[NPROC]; p++) + if(p->state == WAITING && p->chan == chan) p->state = RUNNABLE; - } - } +} + +void +wakeup(void *chan) +{ + acquire(&proc_table_lock); + wakeup1(chan); release(&proc_table_lock); } @@ -229,8 +257,6 @@ proc_exit() struct proc *cp = curproc[cpu()]; int fd; - cprintf("exit %x pid %d ppid %d\n", cp, cp->pid, cp->ppid); - for(fd = 0; fd < NOFILE; fd++){ if(cp->fds[fd]){ fd_close(cp->fds[fd]); @@ -243,32 +269,35 @@ proc_exit() // wake up parent for(p = proc; p < &proc[NPROC]; p++) if(p->pid == cp->ppid) - wakeup(p); + wakeup1(p); // abandon children for(p = proc; p < &proc[NPROC]; p++) if(p->ppid == cp->pid) p->pid = 1; - - release(&proc_table_lock); - - // switch into scheduler + + cp->mtx = &proc_table_lock; swtch(ZOMBIE); + panic("a zombie revived"); } // disable interrupts void cli(void) { - cpus[cpu()].clis += 1; - if(cpus[cpu()].clis == 1) + if(cpus[cpu()].clis == 0) __asm __volatile("cli"); + cpus[cpu()].clis += 1; + if((read_eflags() & FL_IF) != 0) + panic("cli but enabled"); } // enable interrupts void sti(void) { + if((read_eflags() & FL_IF) != 0) + panic("sti but enabled"); if(cpus[cpu()].clis < 1) panic("sti"); cpus[cpu()].clis -= 1; |