ia64/xen-unstable

view xen/common/spinlock.c @ 18714:0358305c6883

spinlock: Add debug-build checks for IRQ-safe spinlocks.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Oct 23 11:53:52 2008 +0100 (2008-10-23)
parents ad39300ca063
children e767f80d4bcc
line source
1 #include <xen/config.h>
2 #include <xen/irq.h>
3 #include <xen/smp.h>
4 #include <xen/spinlock.h>
6 #ifndef NDEBUG
8 static atomic_t spin_debug __read_mostly = ATOMIC_INIT(0);
10 static void check_lock(struct lock_debug *debug)
11 {
12 int irq_safe = !local_irq_is_enabled();
14 if ( unlikely(atomic_read(&spin_debug) <= 0) )
15 return;
17 /* A few places take liberties with this. */
18 /* BUG_ON(in_irq() && !irq_safe); */
20 if ( unlikely(debug->irq_safe != irq_safe) )
21 {
22 int seen = cmpxchg(&debug->irq_safe, -1, irq_safe);
23 BUG_ON(seen == !irq_safe);
24 }
25 }
27 void spin_debug_enable(void)
28 {
29 atomic_inc(&spin_debug);
30 }
32 void spin_debug_disable(void)
33 {
34 atomic_dec(&spin_debug);
35 }
37 #else /* defined(NDEBUG) */
39 #define check_lock(l) ((void)0)
41 #endif
43 void _spin_lock(spinlock_t *lock)
44 {
45 check_lock(&lock->debug);
46 _raw_spin_lock(&lock->raw);
47 }
49 void _spin_lock_irq(spinlock_t *lock)
50 {
51 ASSERT(local_irq_is_enabled());
52 local_irq_disable();
53 check_lock(&lock->debug);
54 _raw_spin_lock(&lock->raw);
55 }
57 unsigned long _spin_lock_irqsave(spinlock_t *lock)
58 {
59 unsigned long flags;
60 local_irq_save(flags);
61 check_lock(&lock->debug);
62 _raw_spin_lock(&lock->raw);
63 return flags;
64 }
66 void _spin_unlock(spinlock_t *lock)
67 {
68 _raw_spin_unlock(&lock->raw);
69 }
71 void _spin_unlock_irq(spinlock_t *lock)
72 {
73 _raw_spin_unlock(&lock->raw);
74 local_irq_enable();
75 }
77 void _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
78 {
79 _raw_spin_unlock(&lock->raw);
80 local_irq_restore(flags);
81 }
83 int _spin_is_locked(spinlock_t *lock)
84 {
85 check_lock(&lock->debug);
86 return _raw_spin_is_locked(&lock->raw);
87 }
89 int _spin_trylock(spinlock_t *lock)
90 {
91 check_lock(&lock->debug);
92 return _raw_spin_trylock(&lock->raw);
93 }
95 void _spin_barrier(spinlock_t *lock)
96 {
97 check_lock(&lock->debug);
98 do { mb(); } while ( _raw_spin_is_locked(&lock->raw) );
99 mb();
100 }
102 void _spin_barrier_irq(spinlock_t *lock)
103 {
104 unsigned long flags;
105 local_irq_save(flags);
106 _spin_barrier(lock);
107 local_irq_restore(flags);
108 }
110 void _spin_lock_recursive(spinlock_t *lock)
111 {
112 int cpu = smp_processor_id();
114 /* Don't allow overflow of recurse_cpu field. */
115 BUILD_BUG_ON(NR_CPUS > 0xfffu);
117 check_lock(&lock->debug);
119 if ( likely(lock->recurse_cpu != cpu) )
120 {
121 spin_lock(lock);
122 lock->recurse_cpu = cpu;
123 }
125 /* We support only fairly shallow recursion, else the counter overflows. */
126 ASSERT(lock->recurse_cnt < 0xfu);
127 lock->recurse_cnt++;
128 }
130 void _spin_unlock_recursive(spinlock_t *lock)
131 {
132 if ( likely(--lock->recurse_cnt == 0) )
133 {
134 lock->recurse_cpu = 0xfffu;
135 spin_unlock(lock);
136 }
137 }
139 void _read_lock(rwlock_t *lock)
140 {
141 check_lock(&lock->debug);
142 _raw_read_lock(&lock->raw);
143 }
145 void _read_lock_irq(rwlock_t *lock)
146 {
147 ASSERT(local_irq_is_enabled());
148 local_irq_disable();
149 check_lock(&lock->debug);
150 _raw_read_lock(&lock->raw);
151 }
153 unsigned long _read_lock_irqsave(rwlock_t *lock)
154 {
155 unsigned long flags;
156 local_irq_save(flags);
157 check_lock(&lock->debug);
158 _raw_read_lock(&lock->raw);
159 return flags;
160 }
162 void _read_unlock(rwlock_t *lock)
163 {
164 _raw_read_unlock(&lock->raw);
165 }
167 void _read_unlock_irq(rwlock_t *lock)
168 {
169 _raw_read_unlock(&lock->raw);
170 local_irq_enable();
171 }
173 void _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
174 {
175 _raw_read_unlock(&lock->raw);
176 local_irq_restore(flags);
177 }
179 void _write_lock(rwlock_t *lock)
180 {
181 check_lock(&lock->debug);
182 _raw_write_lock(&lock->raw);
183 }
185 void _write_lock_irq(rwlock_t *lock)
186 {
187 ASSERT(local_irq_is_enabled());
188 local_irq_disable();
189 check_lock(&lock->debug);
190 _raw_write_lock(&lock->raw);
191 }
193 unsigned long _write_lock_irqsave(rwlock_t *lock)
194 {
195 unsigned long flags;
196 local_irq_save(flags);
197 check_lock(&lock->debug);
198 _raw_write_lock(&lock->raw);
199 return flags;
200 }
202 void _write_unlock(rwlock_t *lock)
203 {
204 _raw_write_unlock(&lock->raw);
205 }
207 void _write_unlock_irq(rwlock_t *lock)
208 {
209 _raw_write_unlock(&lock->raw);
210 local_irq_enable();
211 }
213 void _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)
214 {
215 _raw_write_unlock(&lock->raw);
216 local_irq_restore(flags);
217 }