passes both usertests

exit had acquire where I meant release
swtch now checks that you hold no locks
This commit is contained in:
rtm 2006-07-12 15:35:33 +00:00
parent 8148b6ee53
commit 6eb6f10c56
6 changed files with 34 additions and 31 deletions

23
Notes
View file

@ -114,26 +114,15 @@ wakeup needs proc_table_lock
so we need recursive locks? so we need recursive locks?
or you must hold the lock to call wakeup? or you must hold the lock to call wakeup?
if locks contain proc *, they can't be used at interrupt time
only proc_table_lock will be used at interrupt time?
maybe it doesn't matter if we use curproc?
in general, the table locks protect both free-ness and in general, the table locks protect both free-ness and
public variables of table elements public variables of table elements
in many cases you can use table elements w/o a lock in many cases you can use table elements w/o a lock
e.g. if you are the process, or you are using an fd e.g. if you are the process, or you are using an fd
why can't i get a lock in console code?
always triple fault
because release turns on interrupts!
a bad idea very early in main()
but mp_init() calls cprintf
lock code shouldn't call cprintf... lock code shouldn't call cprintf...
ide_init doesn't work now?
and IOAPIC: read from unsupported address nasty hack to allow locks before first process,
when running pre-empt user test and to allow them in interrupts when curproc may be zero
so maybe something wrong with clock interrupts
no! if one cpu holds lock w/ curproc0=, race between release and sleep in sys_wait()
then another cpu can take it, it looks like race between sys_exit waking up parent and setting state=ZOMBIE
a recursive acquire()

18
proc.c
View file

@ -181,7 +181,9 @@ swtch(int newstate)
{ {
struct proc *p = curproc[cpu()]; struct proc *p = curproc[cpu()];
if(p == 0) if(p == 0)
panic("swtch"); panic("swtch no proc");
if(p->locks != 0)
panic("swtch w/ locks");
p->newstate = newstate; // basically an argument to scheduler() p->newstate = newstate; // basically an argument to scheduler()
if(setjmp(&p->jmpbuf) == 0) if(setjmp(&p->jmpbuf) == 0)
longjmp(&cpus[cpu()].jmpbuf); longjmp(&cpus[cpu()].jmpbuf);
@ -203,9 +205,11 @@ wakeup(void *chan)
struct proc *p; struct proc *p;
acquire(&proc_table_lock); acquire(&proc_table_lock);
for(p = proc; p < &proc[NPROC]; p++) for(p = proc; p < &proc[NPROC]; p++){
if(p->state == WAITING && p->chan == chan) if(p->state == WAITING && p->chan == chan){
p->state = RUNNABLE; p->state = RUNNABLE;
}
}
release(&proc_table_lock); release(&proc_table_lock);
} }
@ -225,7 +229,7 @@ proc_exit()
struct proc *cp = curproc[cpu()]; struct proc *cp = curproc[cpu()];
int fd; int fd;
cprintf("exit %x\n", cp); cprintf("exit %x pid %d ppid %d\n", cp, cp->pid, cp->ppid);
for(fd = 0; fd < NOFILE; fd++){ for(fd = 0; fd < NOFILE; fd++){
if(cp->fds[fd]){ if(cp->fds[fd]){
@ -246,7 +250,7 @@ proc_exit()
if(p->ppid == cp->pid) if(p->ppid == cp->pid)
p->pid = 1; p->pid = 1;
acquire(&proc_table_lock); release(&proc_table_lock);
// switch into scheduler // switch into scheduler
swtch(ZOMBIE); swtch(ZOMBIE);
@ -265,10 +269,8 @@ cli(void)
void void
sti(void) sti(void)
{ {
if(cpus[cpu()].clis < 1){ if(cpus[cpu()].clis < 1)
cprintf("cpu %d clis %d\n", cpu(), cpus[cpu()].clis);
panic("sti"); panic("sti");
}
cpus[cpu()].clis -= 1; cpus[cpu()].clis -= 1;
if(cpus[cpu()].clis < 1) if(cpus[cpu()].clis < 1)
__asm __volatile("sti"); __asm __volatile("sti");

1
proc.h
View file

@ -45,6 +45,7 @@ struct proc{
int ppid; int ppid;
void *chan; // sleep void *chan; // sleep
int killed; int killed;
int locks; // # of locks currently held
struct fd *fds[NOFILE]; struct fd *fds[NOFILE];
struct Taskstate ts; // only to give cpu address of kernel stack struct Taskstate ts; // only to give cpu address of kernel stack

View file

@ -17,10 +17,11 @@ int getcallerpc(void *v) {
void void
acquire(struct spinlock * lock) acquire(struct spinlock * lock)
{ {
struct proc *cp = curproc[cpu()];
unsigned who; unsigned who;
if(curproc[cpu()]) if(cp)
who = (unsigned) curproc[cpu()]; who = (unsigned) cp;
else else
who = cpu() + 1; who = cpu() + 1;
@ -38,16 +39,20 @@ acquire(struct spinlock * lock)
lock->who = who; lock->who = who;
} }
if(cp)
cp->locks += 1;
if(DEBUG) cprintf("cpu%d: acquired at %x\n", cpu(), getcallerpc(&lock)); if(DEBUG) cprintf("cpu%d: acquired at %x\n", cpu(), getcallerpc(&lock));
} }
void void
release(struct spinlock * lock) release(struct spinlock * lock)
{ {
struct proc *cp = curproc[cpu()];
unsigned who; unsigned who;
if(curproc[cpu()]) if(cp)
who = (unsigned) curproc[cpu()]; who = (unsigned) cp;
else else
who = cpu() + 1; who = cpu() + 1;
@ -57,6 +62,8 @@ release(struct spinlock * lock)
panic("release"); panic("release");
lock->count -= 1; lock->count -= 1;
if(cp)
cp->locks -= 1;
if(lock->count < 1){ if(lock->count < 1){
lock->who = 0; lock->who = 0;
cmpxchg(1, 0, &lock->locked); cmpxchg(1, 0, &lock->locked);

4
trap.c
View file

@ -62,6 +62,9 @@ trap(struct Trapframe *tf)
struct proc *cp = curproc[cpu()]; struct proc *cp = curproc[cpu()];
lapic_timerintr(); lapic_timerintr();
if(cp){ if(cp){
if(cpus[cpu()].clis != 0)
panic("trap clis > 0");
cpus[cpu()].clis += 1;
sti(); sti();
if(cp->killed) if(cp->killed)
proc_exit(); proc_exit();
@ -69,6 +72,7 @@ trap(struct Trapframe *tf)
} }
return; return;
} }
if(v == (IRQ_OFFSET + IRQ_IDE)){ if(v == (IRQ_OFFSET + IRQ_IDE)){
ide_intr(); ide_intr();
return; return;

View file

@ -93,8 +93,8 @@ preempt()
main() main()
{ {
puts("usertests starting\n"); puts("usertests starting\n");
//pipe1(); pipe1();
preempt(); //preempt();
while(1) while(1)
; ;