passes both usertests
exit had acquire where I meant release swtch now checks that you hold no locks
This commit is contained in:
parent
8148b6ee53
commit
6eb6f10c56
6 changed files with 34 additions and 31 deletions
23
Notes
23
Notes
|
@ -114,26 +114,15 @@ wakeup needs proc_table_lock
|
|||
so we need recursive locks?
|
||||
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
|
||||
public variables of table elements
|
||||
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
|
||||
|
||||
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...
|
||||
ide_init doesn't work now?
|
||||
and IOAPIC: read from unsupported address
|
||||
when running pre-empt user test
|
||||
so maybe something wrong with clock interrupts
|
||||
no! if one cpu holds lock w/ curproc0=,
|
||||
then another cpu can take it, it looks like
|
||||
a recursive acquire()
|
||||
|
||||
nasty hack to allow locks before first process,
|
||||
and to allow them in interrupts when curproc may be zero
|
||||
|
||||
race between release and sleep in sys_wait()
|
||||
race between sys_exit waking up parent and setting state=ZOMBIE
|
||||
|
|
18
proc.c
18
proc.c
|
@ -181,7 +181,9 @@ swtch(int newstate)
|
|||
{
|
||||
struct proc *p = curproc[cpu()];
|
||||
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()
|
||||
if(setjmp(&p->jmpbuf) == 0)
|
||||
longjmp(&cpus[cpu()].jmpbuf);
|
||||
|
@ -203,9 +205,11 @@ wakeup(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;
|
||||
}
|
||||
}
|
||||
release(&proc_table_lock);
|
||||
}
|
||||
|
||||
|
@ -225,7 +229,7 @@ proc_exit()
|
|||
struct proc *cp = curproc[cpu()];
|
||||
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++){
|
||||
if(cp->fds[fd]){
|
||||
|
@ -246,7 +250,7 @@ proc_exit()
|
|||
if(p->ppid == cp->pid)
|
||||
p->pid = 1;
|
||||
|
||||
acquire(&proc_table_lock);
|
||||
release(&proc_table_lock);
|
||||
|
||||
// switch into scheduler
|
||||
swtch(ZOMBIE);
|
||||
|
@ -265,10 +269,8 @@ cli(void)
|
|||
void
|
||||
sti(void)
|
||||
{
|
||||
if(cpus[cpu()].clis < 1){
|
||||
cprintf("cpu %d clis %d\n", cpu(), cpus[cpu()].clis);
|
||||
if(cpus[cpu()].clis < 1)
|
||||
panic("sti");
|
||||
}
|
||||
cpus[cpu()].clis -= 1;
|
||||
if(cpus[cpu()].clis < 1)
|
||||
__asm __volatile("sti");
|
||||
|
|
1
proc.h
1
proc.h
|
@ -45,6 +45,7 @@ struct proc{
|
|||
int ppid;
|
||||
void *chan; // sleep
|
||||
int killed;
|
||||
int locks; // # of locks currently held
|
||||
struct fd *fds[NOFILE];
|
||||
|
||||
struct Taskstate ts; // only to give cpu address of kernel stack
|
||||
|
|
15
spinlock.c
15
spinlock.c
|
@ -17,10 +17,11 @@ int getcallerpc(void *v) {
|
|||
void
|
||||
acquire(struct spinlock * lock)
|
||||
{
|
||||
struct proc *cp = curproc[cpu()];
|
||||
unsigned who;
|
||||
|
||||
if(curproc[cpu()])
|
||||
who = (unsigned) curproc[cpu()];
|
||||
if(cp)
|
||||
who = (unsigned) cp;
|
||||
else
|
||||
who = cpu() + 1;
|
||||
|
||||
|
@ -38,16 +39,20 @@ acquire(struct spinlock * lock)
|
|||
lock->who = who;
|
||||
}
|
||||
|
||||
if(cp)
|
||||
cp->locks += 1;
|
||||
|
||||
if(DEBUG) cprintf("cpu%d: acquired at %x\n", cpu(), getcallerpc(&lock));
|
||||
}
|
||||
|
||||
void
|
||||
release(struct spinlock * lock)
|
||||
{
|
||||
struct proc *cp = curproc[cpu()];
|
||||
unsigned who;
|
||||
|
||||
if(curproc[cpu()])
|
||||
who = (unsigned) curproc[cpu()];
|
||||
if(cp)
|
||||
who = (unsigned) cp;
|
||||
else
|
||||
who = cpu() + 1;
|
||||
|
||||
|
@ -57,6 +62,8 @@ release(struct spinlock * lock)
|
|||
panic("release");
|
||||
|
||||
lock->count -= 1;
|
||||
if(cp)
|
||||
cp->locks -= 1;
|
||||
if(lock->count < 1){
|
||||
lock->who = 0;
|
||||
cmpxchg(1, 0, &lock->locked);
|
||||
|
|
4
trap.c
4
trap.c
|
@ -62,6 +62,9 @@ trap(struct Trapframe *tf)
|
|||
struct proc *cp = curproc[cpu()];
|
||||
lapic_timerintr();
|
||||
if(cp){
|
||||
if(cpus[cpu()].clis != 0)
|
||||
panic("trap clis > 0");
|
||||
cpus[cpu()].clis += 1;
|
||||
sti();
|
||||
if(cp->killed)
|
||||
proc_exit();
|
||||
|
@ -69,6 +72,7 @@ trap(struct Trapframe *tf)
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(v == (IRQ_OFFSET + IRQ_IDE)){
|
||||
ide_intr();
|
||||
return;
|
||||
|
|
|
@ -93,8 +93,8 @@ preempt()
|
|||
main()
|
||||
{
|
||||
puts("usertests starting\n");
|
||||
//pipe1();
|
||||
preempt();
|
||||
pipe1();
|
||||
//preempt();
|
||||
|
||||
while(1)
|
||||
;
|
||||
|
|
Loading…
Reference in a new issue