summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsc <rsc>2006-07-17 05:00:25 +0000
committerrsc <rsc>2006-07-17 05:00:25 +0000
commit0dd4253747eef56d0f1539fac7d62234f6af5f51 (patch)
tree1c28a6d0ce4cef90f85fd5f8b0106d431bfeffda
parentb5f17007f41770fee97fa850635976ceb7aa7492 (diff)
downloadxv6-labs-0dd4253747eef56d0f1539fac7d62234f6af5f51.tar.gz
xv6-labs-0dd4253747eef56d0f1539fac7d62234f6af5f51.tar.bz2
xv6-labs-0dd4253747eef56d0f1539fac7d62234f6af5f51.zip
add ide_lock for sleep
-rw-r--r--defs.h7
-rw-r--r--ide.c8
-rw-r--r--proc.c12
-rw-r--r--spinlock.c14
-rw-r--r--spinlock.h3
-rw-r--r--syscall.c5
6 files changed, 41 insertions, 8 deletions
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);