提交 1229ed4b 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

SPINLOCK_DEBUG

上级 71c12c3a
...@@ -5,7 +5,11 @@ ...@@ -5,7 +5,11 @@
// name spaces // name spaces
// XXX maybe use open hash table, no chain, better cache locality // XXX maybe use open hash table, no chain, better cache locality
#if SPINLOCK_DEBUG
#define NHASH 10
#else
#define NHASH 100 #define NHASH 100
#endif
// XXX cache align // XXX cache align
struct elem { struct elem {
......
...@@ -110,8 +110,10 @@ addrun1(struct runq *rq, struct proc *p) ...@@ -110,8 +110,10 @@ addrun1(struct runq *rq, struct proc *p)
void void
addrun(struct proc *p) addrun(struct proc *p)
{ {
#if SPINLOCK_DEBUG
if(!holding(&p->lock)) if(!holding(&p->lock))
panic("addrun no p->lock"); panic("addrun no p->lock");
#endif
acquire(&runqs[p->cpuid].lock); acquire(&runqs[p->cpuid].lock);
// cprintf("%d: addrun %d\n", cpu->id, p->pid); // cprintf("%d: addrun %d\n", cpu->id, p->pid);
addrun1(&runqs[p->cpuid], p); addrun1(&runqs[p->cpuid], p);
...@@ -134,8 +136,10 @@ delrun1(struct runq *rq, struct proc *p) ...@@ -134,8 +136,10 @@ delrun1(struct runq *rq, struct proc *p)
void void
delrun(struct proc *p) delrun(struct proc *p)
{ {
#if SPINLOCK_DEBUG
if(!holding(&p->lock)) if(!holding(&p->lock))
panic("delrun no p->lock"); panic("delrun no p->lock");
#endif
acquire(&runq->lock); acquire(&runq->lock);
// cprintf("%d: delrun %d\n", cpu->id, p->pid); // cprintf("%d: delrun %d\n", cpu->id, p->pid);
delrun1(runq, p); delrun1(runq, p);
...@@ -566,8 +570,10 @@ sched(void) ...@@ -566,8 +570,10 @@ sched(void)
{ {
int intena; int intena;
#if SPINLOCK_DEBUG
if(!holding(&proc->lock)) if(!holding(&proc->lock))
panic("sched proc->lock"); panic("sched proc->lock");
#endif
if(cpu->ncli != 1) if(cpu->ncli != 1)
panic("sched locks"); panic("sched locks");
if(proc->state == RUNNING) if(proc->state == RUNNING)
......
...@@ -112,18 +112,20 @@ rcu_end_read(void) ...@@ -112,18 +112,20 @@ rcu_end_read(void)
void void
rcu_begin_write(struct spinlock *l) rcu_begin_write(struct spinlock *l)
{ {
rcu_begin_read();
if (l) acquire(l); if (l) acquire(l);
__sync_synchronize(); __sync_synchronize();
rcu_begin_read();
} }
void void
rcu_end_write(struct spinlock *l) rcu_end_write(struct spinlock *l)
{ {
rcu_end_read();
// global_epoch can be bumped anywhere; this seems as good a place as any // global_epoch can be bumped anywhere; this seems as good a place as any
__sync_fetch_and_add(&global_epoch, 1); __sync_fetch_and_add(&global_epoch, 1);
if (l) release(l); if (l) release(l);
rcu_end_read();
} }
...@@ -15,9 +15,11 @@ ...@@ -15,9 +15,11 @@
void void
initlock(struct spinlock *lk, char *name) initlock(struct spinlock *lk, char *name)
{ {
#if SPINLOCK_DEBUG
lk->name = name; lk->name = name;
lk->locked = 0;
lk->cpu = 0; lk->cpu = 0;
#endif
lk->locked = 0;
} }
// Acquire the lock. // Acquire the lock.
...@@ -28,12 +30,19 @@ void ...@@ -28,12 +30,19 @@ void
acquire(struct spinlock *lk) acquire(struct spinlock *lk)
{ {
pushcli(); // disable interrupts to avoid deadlock. pushcli(); // disable interrupts to avoid deadlock.
#if SPINLOCK_DEBUG
if(holding(lk)) if(holding(lk))
panic("acquire"); panic("acquire");
#endif
mtrace_lock_register(RET_EIP(), mtrace_lock_register(RET_EIP(),
lk, lk,
#if SPINLOCK_DEBUG
lk->name ?: "null", lk->name ?: "null",
#else
"unknown",
#endif
mtrace_lockop_acquire, mtrace_lockop_acquire,
0); 0);
...@@ -45,32 +54,46 @@ acquire(struct spinlock *lk) ...@@ -45,32 +54,46 @@ acquire(struct spinlock *lk)
mtrace_lock_register(RET_EIP(), mtrace_lock_register(RET_EIP(),
lk, lk,
#if SPINLOCK_DEBUG
lk->name ?: "null", lk->name ?: "null",
#else
"unknown",
#endif
mtrace_lockop_acquired, mtrace_lockop_acquired,
0); 0);
#if SPINLOCK_DEBUG
// Record info about lock acquisition for debugging. // Record info about lock acquisition for debugging.
lk->cpu = cpu; lk->cpu = cpu;
getcallerpcs(&lk, lk->pcs); getcallerpcs(&lk, lk->pcs);
#endif
} }
// Release the lock. // Release the lock.
void void
release(struct spinlock *lk) release(struct spinlock *lk)
{ {
#if SPINLOCK_DEBUG
if(!holding(lk)) { if(!holding(lk)) {
cprintf("lock: %s\n", lk->name); cprintf("lock: %s\n", lk->name);
panic("release"); panic("release");
} }
#endif
mtrace_lock_register(RET_EIP(), mtrace_lock_register(RET_EIP(),
lk, lk,
#if SPINLOCK_DEBUG
lk->name ?: "null", lk->name ?: "null",
#else
"unknown",
#endif
mtrace_lockop_release, mtrace_lockop_release,
0); 0);
#if SPINLOCK_DEBUG
lk->pcs[0] = 0; lk->pcs[0] = 0;
lk->cpu = 0; lk->cpu = 0;
#endif
// The xchg serializes, so that reads before release are // The xchg serializes, so that reads before release are
// not reordered after it. The 1996 PentiumPro manual (Volume 3, // not reordered after it. The 1996 PentiumPro manual (Volume 3,
...@@ -105,11 +128,13 @@ getcallerpcs(void *v, uint pcs[]) ...@@ -105,11 +128,13 @@ getcallerpcs(void *v, uint pcs[])
} }
// Check whether this cpu is holding the lock. // Check whether this cpu is holding the lock.
#if SPINLOCK_DEBUG
int int
holding(struct spinlock *lock) holding(struct spinlock *lock)
{ {
return lock->locked && lock->cpu == cpu; return lock->locked && lock->cpu == cpu;
} }
#endif
// Pushcli/popcli are like cli/sti except that they are matched: // Pushcli/popcli are like cli/sti except that they are matched:
......
#pragma once #pragma once
#define SPINLOCK_DEBUG 1
// Mutual exclusion lock. // Mutual exclusion lock.
struct spinlock { struct spinlock {
uint locked; // Is the lock held? uint locked; // Is the lock held?
#if SPINLOCK_DEBUG
// For debugging: // For debugging:
char *name; // Name of lock. char *name; // Name of lock.
struct cpu *cpu; // The cpu holding the lock. struct cpu *cpu; // The cpu holding the lock.
uint pcs[10]; // The call stack (an array of program counters) uint pcs[10]; // The call stack (an array of program counters)
// that locked the lock. // that locked the lock.
#endif
}; };
...@@ -486,8 +486,10 @@ vmap_decref(struct vmap *m) ...@@ -486,8 +486,10 @@ vmap_decref(struct vmap *m)
int int
vmap_overlap(struct vmap *m, uint start, uint len) vmap_overlap(struct vmap *m, uint start, uint len)
{ {
#if SPINLOCK_DEBUG
if(holding(&m->lock) == 0) if(holding(&m->lock) == 0)
panic("vmap_overlap no lock"); panic("vmap_overlap no lock");
#endif
if(start + len < start) if(start + len < start)
panic("vmap_overlap bad len"); panic("vmap_overlap bad len");
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论