diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-10-23 11:53:52 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-10-23 11:53:52 +0100 |
commit | 10f097660035cec88e5f385e7f01d2902d639a4d (patch) | |
tree | 0f81b979fc01c36c2408870e8e9fdb9879f0ed16 /xen/common/spinlock.c | |
parent | 33d21c38e4aa82c075c75e70bca94040d096fb9e (diff) | |
download | xen-10f097660035cec88e5f385e7f01d2902d639a4d.tar.gz xen-10f097660035cec88e5f385e7f01d2902d639a4d.tar.bz2 xen-10f097660035cec88e5f385e7f01d2902d639a4d.zip |
spinlock: Add debug-build checks for IRQ-safe spinlocks.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/common/spinlock.c')
-rw-r--r-- | xen/common/spinlock.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/xen/common/spinlock.c b/xen/common/spinlock.c index 438e51deb8..95affbde01 100644 --- a/xen/common/spinlock.c +++ b/xen/common/spinlock.c @@ -1,9 +1,48 @@ #include <xen/config.h> +#include <xen/irq.h> #include <xen/smp.h> #include <xen/spinlock.h> +#ifndef NDEBUG + +static atomic_t spin_debug __read_mostly = ATOMIC_INIT(0); + +static void check_lock(struct lock_debug *debug) +{ + int irq_safe = !local_irq_is_enabled(); + + if ( unlikely(atomic_read(&spin_debug) <= 0) ) + return; + + /* A few places take liberties with this. */ + /* BUG_ON(in_irq() && !irq_safe); */ + + if ( unlikely(debug->irq_safe != irq_safe) ) + { + int seen = cmpxchg(&debug->irq_safe, -1, irq_safe); + BUG_ON(seen == !irq_safe); + } +} + +void spin_debug_enable(void) +{ + atomic_inc(&spin_debug); +} + +void spin_debug_disable(void) +{ + atomic_dec(&spin_debug); +} + +#else /* defined(NDEBUG) */ + +#define check_lock(l) ((void)0) + +#endif + void _spin_lock(spinlock_t *lock) { + check_lock(&lock->debug); _raw_spin_lock(&lock->raw); } @@ -11,6 +50,7 @@ void _spin_lock_irq(spinlock_t *lock) { ASSERT(local_irq_is_enabled()); local_irq_disable(); + check_lock(&lock->debug); _raw_spin_lock(&lock->raw); } @@ -18,6 +58,7 @@ unsigned long _spin_lock_irqsave(spinlock_t *lock) { unsigned long flags; local_irq_save(flags); + check_lock(&lock->debug); _raw_spin_lock(&lock->raw); return flags; } @@ -41,16 +82,19 @@ void _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) int _spin_is_locked(spinlock_t *lock) { + check_lock(&lock->debug); return _raw_spin_is_locked(&lock->raw); } int _spin_trylock(spinlock_t *lock) { + check_lock(&lock->debug); return _raw_spin_trylock(&lock->raw); } void _spin_barrier(spinlock_t *lock) { + check_lock(&lock->debug); do { mb(); } while ( _raw_spin_is_locked(&lock->raw) ); mb(); } @@ -70,6 +114,8 @@ void _spin_lock_recursive(spinlock_t *lock) /* Don't allow overflow of recurse_cpu field. */ BUILD_BUG_ON(NR_CPUS > 0xfffu); + check_lock(&lock->debug); + if ( likely(lock->recurse_cpu != cpu) ) { spin_lock(lock); @@ -92,6 +138,7 @@ void _spin_unlock_recursive(spinlock_t *lock) void _read_lock(rwlock_t *lock) { + check_lock(&lock->debug); _raw_read_lock(&lock->raw); } @@ -99,6 +146,7 @@ void _read_lock_irq(rwlock_t *lock) { ASSERT(local_irq_is_enabled()); local_irq_disable(); + check_lock(&lock->debug); _raw_read_lock(&lock->raw); } @@ -106,6 +154,7 @@ unsigned long _read_lock_irqsave(rwlock_t *lock) { unsigned long flags; local_irq_save(flags); + check_lock(&lock->debug); _raw_read_lock(&lock->raw); return flags; } @@ -129,6 +178,7 @@ void _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags) void _write_lock(rwlock_t *lock) { + check_lock(&lock->debug); _raw_write_lock(&lock->raw); } @@ -136,6 +186,7 @@ void _write_lock_irq(rwlock_t *lock) { ASSERT(local_irq_is_enabled()); local_irq_disable(); + check_lock(&lock->debug); _raw_write_lock(&lock->raw); } @@ -143,6 +194,7 @@ unsigned long _write_lock_irqsave(rwlock_t *lock) { unsigned long flags; local_irq_save(flags); + check_lock(&lock->debug); _raw_write_lock(&lock->raw); return flags; } |