aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/spinlock.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-10-23 11:53:52 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-10-23 11:53:52 +0100
commit10f097660035cec88e5f385e7f01d2902d639a4d (patch)
tree0f81b979fc01c36c2408870e8e9fdb9879f0ed16 /xen/common/spinlock.c
parent33d21c38e4aa82c075c75e70bca94040d096fb9e (diff)
downloadxen-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.c52
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;
}