add ide_lock for sleep

This commit is contained in:
rsc 2006-07-17 05:00:25 +00:00
parent b5f17007f4
commit 0dd4253747
6 changed files with 41 additions and 8 deletions

7
defs.h
View file

@ -61,10 +61,9 @@ int cpu(void);
// spinlock.c // spinlock.c
struct spinlock; struct spinlock;
void acquire(struct spinlock * lock); void acquire(struct spinlock*);
void release(struct spinlock * lock); void release(struct spinlock*);
void acquire1(struct spinlock * lock, struct proc *); int holding(struct spinlock*);
void release1(struct spinlock * lock, struct proc *);
// main.c // main.c
void load_icode(struct proc *p, uint8_t *binary, uint size); void load_icode(struct proc *p, uint8_t *binary, uint size);

8
ide.c
View file

@ -10,6 +10,7 @@
#include "proc.h" #include "proc.h"
#include "defs.h" #include "defs.h"
#include "x86.h" #include "x86.h"
#include "spinlock.h"
#define IDE_BSY 0x80 #define IDE_BSY 0x80
#define IDE_DRDY 0x40 #define IDE_DRDY 0x40
@ -23,6 +24,7 @@ struct ide_request {
}; };
struct ide_request request[NREQUEST]; struct ide_request request[NREQUEST];
int head, tail; int head, tail;
struct spinlock ide_lock;
static int diskno = 0; static int diskno = 0;
int disk_channel; int disk_channel;
@ -107,12 +109,14 @@ void *
ide_start_read(uint32_t secno, void *dst, uint nsecs) ide_start_read(uint32_t secno, void *dst, uint nsecs)
{ {
struct ide_request *r; struct ide_request *r;
if(!holding(&ide_lock))
panic("ide_start_read: not holding ide_lock");
if(nsecs > 256) if(nsecs > 256)
panic("ide_start_read: nsecs too large"); panic("ide_start_read: nsecs too large");
while ((head + 1) % NREQUEST == tail) while ((head + 1) % NREQUEST == tail)
sleep (&disk_channel, 0); sleep (&disk_channel, &ide_lock);
r = &request[head]; r = &request[head];
r->secno = secno; r->secno = secno;
@ -132,6 +136,8 @@ ide_finish_read(void *c)
int r = 0; int r = 0;
struct ide_request *req = (struct ide_request *) c; 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) { for (; req->nsecs > 0; req->nsecs--, req->dst += 512) {
if ((r = ide_wait_ready(1)) < 0) if ((r = ide_wait_ready(1)) < 0)
break; break;

12
proc.c
View file

@ -176,6 +176,15 @@ scheduler(void)
if(p->state == RUNNING) if(p->state == RUNNING)
panic("swtch to scheduler with 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. // XXX if not holding proc_table_lock panic.
} }
release(&proc_table_lock); release(&proc_table_lock);
@ -236,6 +245,9 @@ sleep(void *chan, struct spinlock *lk)
if(p == 0) if(p == 0)
panic("sleep"); panic("sleep");
if(lk == 0)
panic("sleep without lk");
// Must acquire proc_table_lock in order to // Must acquire proc_table_lock in order to
// change p->state and then call sched. // change p->state and then call sched.
// Once we hold proc_table_lock, we can be // Once we hold proc_table_lock, we can be

View file

@ -21,20 +21,32 @@ getcallerpc(void *v)
void void
acquire(struct spinlock * lock) acquire(struct spinlock * lock)
{ {
if(holding(lock))
panic("acquire");
if(cpus[cpu()].nlock++ == 0) if(cpus[cpu()].nlock++ == 0)
cli(); cli();
while(cmpxchg(0, 1, &lock->locked) == 1) while(cmpxchg(0, 1, &lock->locked) == 1)
; ;
cpuid(0, 0, 0, 0, 0); // memory barrier cpuid(0, 0, 0, 0, 0); // memory barrier
lock->locker_pc = getcallerpc(&lock); lock->pc = getcallerpc(&lock);
lock->cpu = cpu();
} }
void void
release(struct spinlock * lock) release(struct spinlock * lock)
{ {
if(!holding(lock))
panic("release");
cpuid(0, 0, 0, 0, 0); // memory barrier cpuid(0, 0, 0, 0, 0); // memory barrier
lock->locked = 0; lock->locked = 0;
if(--cpus[cpu()].nlock == 0) if(--cpus[cpu()].nlock == 0)
sti(); sti();
} }
int
holding(struct spinlock *lock)
{
return lock->locked && lock->cpu == cpu();
}

View file

@ -1,4 +1,5 @@
struct spinlock { struct spinlock {
uint locked; uint locked;
uint locker_pc; uint32_t pc;
int cpu;
}; };

View file

@ -228,17 +228,20 @@ sys_block(void)
char buf[512]; char buf[512];
int i, j; int i, j;
void *c; void *c;
extern struct spinlock ide_lock;
cprintf("%d: call sys_block\n", cpu()); cprintf("%d: call sys_block\n", cpu());
for (i = 0; i < 100; i++) { for (i = 0; i < 100; i++) {
acquire(&ide_lock);
if ((c = ide_start_read(i, buf, 1)) == 0) { if ((c = ide_start_read(i, buf, 1)) == 0) {
panic("couldn't start read\n"); panic("couldn't start read\n");
} }
cprintf("call sleep\n"); cprintf("call sleep\n");
sleep (c, 0); sleep (c, &ide_lock);
if (ide_finish_read(c)) { if (ide_finish_read(c)) {
panic("couldn't do read\n"); panic("couldn't do read\n");
} }
release(&ide_lock);
cprintf("sector %d: ", i); cprintf("sector %d: ", i);
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
cprintf("%x ", buf[j] & 0xff); cprintf("%x ", buf[j] & 0xff);