summaryrefslogtreecommitdiff
path: root/spinlock.c
diff options
context:
space:
mode:
authorrtm <rtm>2006-08-08 19:58:06 +0000
committerrtm <rtm>2006-08-08 19:58:06 +0000
commit0e84a0ec6e7893dad13dff9a958c5bc987b79c82 (patch)
tree5739d0a2af8277db7a47c74e52975d9e9d81cef7 /spinlock.c
parente8d11c2e846ad15b32caacc8a919722b76d00f79 (diff)
downloadxv6-labs-0e84a0ec6e7893dad13dff9a958c5bc987b79c82.tar.gz
xv6-labs-0e84a0ec6e7893dad13dff9a958c5bc987b79c82.tar.bz2
xv6-labs-0e84a0ec6e7893dad13dff9a958c5bc987b79c82.zip
fix race in holding() check in acquire()
give cpu1 a TSS and gdt for when it enters scheduler() and a pseudo proc[] entry for each cpu cpu0 waits for each other cpu to start up read() for files
Diffstat (limited to 'spinlock.c')
-rw-r--r--spinlock.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/spinlock.c b/spinlock.c
index bde6e46..5a0fd23 100644
--- a/spinlock.c
+++ b/spinlock.c
@@ -12,29 +12,31 @@
extern int use_console_lock;
-int
-getcallerpc(void *v)
+void
+getcallerpcs(void *v, uint pcs[])
{
- return ((int*)v)[-1];
+ uint *ebp = (uint*)v - 2;
+ int i;
+ for(i = 0; i < 10 && ebp && ebp != (uint*)0xffffffff; ebp = (uint*)*ebp, i++){
+ pcs[i] = *(ebp + 1);
+ }
+ for( ; i < 10; i++)
+ pcs[i] = 0;
}
void
acquire(struct spinlock * lock)
{
- if(holding(lock)){
- extern use_console_lock;
- use_console_lock = 0;
- cprintf("lock %s pc %x\n", lock->name ? lock->name : "", lock->pc);
- panic("acquire");
- }
+ 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->pc = getcallerpc(&lock);
- lock->cpu = cpu();
+ getcallerpcs(&lock, lock->pcs);
+ lock->cpu = cpu() + 10;
cpus[cpu()].lastacquire = lock;
}
@@ -45,6 +47,8 @@ release(struct spinlock * lock)
panic("release");
cpus[cpu()].lastrelease = lock;
+ lock->pcs[0] = 0;
+ lock->cpu = 0xffffffff;
cpuid(0, 0, 0, 0, 0); // memory barrier
lock->locked = 0;
if(--cpus[cpu()].nlock == 0)
@@ -54,5 +58,5 @@ release(struct spinlock * lock)
int
holding(struct spinlock *lock)
{
- return lock->locked && lock->cpu == cpu();
+ return lock->locked && lock->cpu == cpu() + 10;
}