diff --git a/defs.h b/defs.h index 9d7a94f..f9c64d3 100644 --- a/defs.h +++ b/defs.h @@ -61,10 +61,9 @@ int cpu(void); // spinlock.c struct spinlock; -void acquire(struct spinlock * lock); -void release(struct spinlock * lock); -void acquire1(struct spinlock * lock, struct proc *); -void release1(struct spinlock * lock, struct proc *); +void acquire(struct spinlock*); +void release(struct spinlock*); +int holding(struct spinlock*); // main.c void load_icode(struct proc *p, uint8_t *binary, uint size); diff --git a/ide.c b/ide.c index 3228f7f..2ea2253 100644 --- a/ide.c +++ b/ide.c @@ -10,6 +10,7 @@ #include "proc.h" #include "defs.h" #include "x86.h" +#include "spinlock.h" #define IDE_BSY 0x80 #define IDE_DRDY 0x40 @@ -23,6 +24,7 @@ struct ide_request { }; struct ide_request request[NREQUEST]; int head, tail; +struct spinlock ide_lock; static int diskno = 0; int disk_channel; @@ -107,12 +109,14 @@ void * ide_start_read(uint32_t secno, void *dst, uint nsecs) { struct ide_request *r; + if(!holding(&ide_lock)) + panic("ide_start_read: not holding ide_lock"); if(nsecs > 256) panic("ide_start_read: nsecs too large"); while ((head + 1) % NREQUEST == tail) - sleep (&disk_channel, 0); + sleep (&disk_channel, &ide_lock); r = &request[head]; r->secno = secno; @@ -132,6 +136,8 @@ ide_finish_read(void *c) int r = 0; struct ide_request *req = (struct ide_request *) c; + if(!holding(&ide_lock)) + panic("ide_start_read: not holding ide_lock"); for (; req->nsecs > 0; req->nsecs--, req->dst += 512) { if ((r = ide_wait_ready(1)) < 0) break; diff --git a/proc.c b/proc.c index 4a05098..b3f352b 100644 --- a/proc.c +++ b/proc.c @@ -176,6 +176,15 @@ scheduler(void) if(p->state == RUNNING) panic("swtch to scheduler with state=RUNNING"); + if(!holding(&proc_table_lock)){ + cprintf("back to scheduler without proc_table_lock (pid=%d state=%d)", p->pid, p->state); + panic("scheduler lock"); + } + if(cpus[cpu()].nlock != 1){ + cprintf("holding %d locks in scheduler (pid=%d state=%d)\n", cpus[cpu()].nlock, p->pid, p->state); + panic("scheduler lock"); + } + // XXX if not holding proc_table_lock panic. } release(&proc_table_lock); @@ -236,6 +245,9 @@ sleep(void *chan, struct spinlock *lk) if(p == 0) panic("sleep"); + if(lk == 0) + panic("sleep without lk"); + // Must acquire proc_table_lock in order to // change p->state and then call sched. // Once we hold proc_table_lock, we can be diff --git a/spinlock.c b/spinlock.c index c0f236d..171afaf 100644 --- a/spinlock.c +++ b/spinlock.c @@ -21,20 +21,32 @@ getcallerpc(void *v) void acquire(struct spinlock * lock) { + if(holding(lock)) + panic("acquire"); + if(cpus[cpu()].nlock++ == 0) cli(); while(cmpxchg(0, 1, &lock->locked) == 1) ; cpuid(0, 0, 0, 0, 0); // memory barrier - lock->locker_pc = getcallerpc(&lock); + lock->pc = getcallerpc(&lock); + lock->cpu = cpu(); } void release(struct spinlock * lock) { + if(!holding(lock)) + panic("release"); + cpuid(0, 0, 0, 0, 0); // memory barrier lock->locked = 0; if(--cpus[cpu()].nlock == 0) sti(); } +int +holding(struct spinlock *lock) +{ + return lock->locked && lock->cpu == cpu(); +} diff --git a/spinlock.h b/spinlock.h index 044e4d8..656d272 100644 --- a/spinlock.h +++ b/spinlock.h @@ -1,4 +1,5 @@ struct spinlock { uint locked; - uint locker_pc; + uint32_t pc; + int cpu; }; diff --git a/syscall.c b/syscall.c index 7bd37b7..58045d4 100644 --- a/syscall.c +++ b/syscall.c @@ -228,17 +228,20 @@ sys_block(void) char buf[512]; int i, j; void *c; + extern struct spinlock ide_lock; cprintf("%d: call sys_block\n", cpu()); for (i = 0; i < 100; i++) { + acquire(&ide_lock); if ((c = ide_start_read(i, buf, 1)) == 0) { panic("couldn't start read\n"); } cprintf("call sleep\n"); - sleep (c, 0); + sleep (c, &ide_lock); if (ide_finish_read(c)) { panic("couldn't do read\n"); } + release(&ide_lock); cprintf("sector %d: ", i); for (j = 0; j < 2; j++) cprintf("%x ", buf[j] & 0xff);