1 #ifndef _ASM_M32R_SPINLOCK_H
2 #define _ASM_M32R_SPINLOCK_H
5 * linux/include/asm-m32r/spinlock.h
8 * Copyright (C) 2001, 2002 Hitoshi Yamamoto
9 * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
12 #include <linux/config.h> /* CONFIG_DEBUG_SPINLOCK, CONFIG_SMP */
13 #include <linux/compiler.h>
14 #include <asm/atomic.h>
17 extern int printk(const char * fmt, ...)
18 __attribute__ ((format (printf, 1, 2)));
20 #define RW_LOCK_BIAS 0x01000000
21 #define RW_LOCK_BIAS_STR "0x01000000"
24 * Your basic SMP spinlocks, allowing only a single CPU anywhere
29 #ifdef CONFIG_DEBUG_SPINLOCK
33 unsigned int break_lock;
37 #define SPINLOCK_MAGIC 0xdead4ead
39 #ifdef CONFIG_DEBUG_SPINLOCK
40 #define SPINLOCK_MAGIC_INIT , SPINLOCK_MAGIC
42 #define SPINLOCK_MAGIC_INIT /* */
45 #define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
47 #define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
50 * Simple spin lock operations. There are two variants, one clears IRQ's
51 * on the local processor, one does not.
53 * We make no fairness assumptions. They have a cost.
56 #define spin_is_locked(x) (*(volatile int *)(&(x)->slock) <= 0)
57 #define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
58 #define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
61 * _raw_spin_trylock - Try spin lock and return a result
62 * @lock: Pointer to the lock variable
64 * _raw_spin_trylock() tries to get the lock and returns a result.
65 * On the m32r, the result value is 1 (= Success) or 0 (= Failure).
67 static inline int _raw_spin_trylock(spinlock_t *lock)
70 unsigned long tmp1, tmp2;
73 * lock->slock : =1 : unlock
76 * oldval = lock->slock; <--+ need atomic operation
77 * lock->slock = 0; <--+
80 __asm__ __volatile__ (
84 "clrpsw #0x40 -> nop; \n\t"
85 DCACHE_CLEAR("%0", "r6", "%3")
87 "unlock %1, @%3; \n\t"
89 : "=&r" (oldval), "=&r" (tmp1), "=&r" (tmp2)
92 #ifdef CONFIG_CHIP_M32700_TS1
94 #endif /* CONFIG_CHIP_M32700_TS1 */
100 static inline void _raw_spin_lock(spinlock_t *lock)
102 unsigned long tmp0, tmp1;
104 #ifdef CONFIG_DEBUG_SPINLOCK
105 if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
106 printk("pc: %p\n", __builtin_return_address(0));
111 * lock->slock : =1 : unlock
115 * lock->slock -= 1; <-- need atomic operation
116 * if (lock->slock == 0) break;
117 * for ( ; lock->slock <= 0 ; );
120 __asm__ __volatile__ (
125 "clrpsw #0x40 -> nop; \n\t"
126 DCACHE_CLEAR("%0", "r6", "%2")
129 "unlock %0, @%2; \n\t"
132 LOCK_SECTION_START(".balign 4 \n\t")
139 : "=&r" (tmp0), "=&r" (tmp1)
142 #ifdef CONFIG_CHIP_M32700_TS1
144 #endif /* CONFIG_CHIP_M32700_TS1 */
148 static inline void _raw_spin_unlock(spinlock_t *lock)
150 #ifdef CONFIG_DEBUG_SPINLOCK
151 BUG_ON(lock->magic != SPINLOCK_MAGIC);
152 BUG_ON(!spin_is_locked(lock));
159 * Read-write spinlocks, allowing multiple readers
160 * but only one writer.
162 * NOTE! it is quite common to have readers in interrupts
163 * but no interrupt writers. For those circumstances we
164 * can "mix" irq-safe locks - any writer needs to get a
165 * irq-safe write-lock, but readers can get non-irqsafe
170 #ifdef CONFIG_DEBUG_SPINLOCK
173 #ifdef CONFIG_PREEMPT
174 unsigned int break_lock;
178 #define RWLOCK_MAGIC 0xdeaf1eed
180 #ifdef CONFIG_DEBUG_SPINLOCK
181 #define RWLOCK_MAGIC_INIT , RWLOCK_MAGIC
183 #define RWLOCK_MAGIC_INIT /* */
186 #define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
188 #define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
191 * read_can_lock - would read_trylock() succeed?
192 * @lock: the rwlock in question.
194 #define read_can_lock(x) ((int)(x)->lock > 0)
197 * write_can_lock - would write_trylock() succeed?
198 * @lock: the rwlock in question.
200 #define write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
203 * On x86, we implement read-write locks as a 32-bit counter
204 * with the high bit (sign) being the "contended" bit.
206 * The inline assembly is non-obvious. Think about it.
208 * Changed to use the same technique as rw semaphores. See
209 * semaphore.h for details. -ben
211 /* the spinlock helpers are in arch/i386/kernel/semaphore.c */
213 static inline void _raw_read_lock(rwlock_t *rw)
215 unsigned long tmp0, tmp1;
217 #ifdef CONFIG_DEBUG_SPINLOCK
218 BUG_ON(rw->magic != RWLOCK_MAGIC);
221 * rw->lock : >0 : unlock
225 * rw->lock -= 1; <-- need atomic operation
226 * if (rw->lock >= 0) break;
227 * rw->lock += 1; <-- need atomic operation
228 * for ( ; rw->lock <= 0 ; );
231 __asm__ __volatile__ (
236 "clrpsw #0x40 -> nop; \n\t"
237 DCACHE_CLEAR("%0", "r6", "%2")
240 "unlock %0, @%2; \n\t"
243 LOCK_SECTION_START(".balign 4 \n\t")
246 "clrpsw #0x40 -> nop; \n\t"
247 DCACHE_CLEAR("%0", "r6", "%2")
250 "unlock %0, @%2; \n\t"
258 : "=&r" (tmp0), "=&r" (tmp1)
261 #ifdef CONFIG_CHIP_M32700_TS1
263 #endif /* CONFIG_CHIP_M32700_TS1 */
267 static inline void _raw_write_lock(rwlock_t *rw)
269 unsigned long tmp0, tmp1, tmp2;
271 #ifdef CONFIG_DEBUG_SPINLOCK
272 BUG_ON(rw->magic != RWLOCK_MAGIC);
275 * rw->lock : =RW_LOCK_BIAS_STR : unlock
276 * : !=RW_LOCK_BIAS_STR : lock
279 * rw->lock -= RW_LOCK_BIAS_STR; <-- need atomic operation
280 * if (rw->lock == 0) break;
281 * rw->lock += RW_LOCK_BIAS_STR; <-- need atomic operation
282 * for ( ; rw->lock != RW_LOCK_BIAS_STR ; ) ;
285 __asm__ __volatile__ (
287 "seth %1, #high(" RW_LOCK_BIAS_STR "); \n\t"
288 "or3 %1, %1, #low(" RW_LOCK_BIAS_STR "); \n\t"
292 "clrpsw #0x40 -> nop; \n\t"
293 DCACHE_CLEAR("%0", "r7", "%3")
296 "unlock %0, @%3; \n\t"
299 LOCK_SECTION_START(".balign 4 \n\t")
302 "clrpsw #0x40 -> nop; \n\t"
303 DCACHE_CLEAR("%0", "r7", "%3")
306 "unlock %0, @%3; \n\t"
311 "beq %0, %1, 1b; \n\t"
314 : "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
317 #ifdef CONFIG_CHIP_M32700_TS1
319 #endif /* CONFIG_CHIP_M32700_TS1 */
323 static inline void _raw_read_unlock(rwlock_t *rw)
325 unsigned long tmp0, tmp1;
327 __asm__ __volatile__ (
330 "clrpsw #0x40 -> nop; \n\t"
331 DCACHE_CLEAR("%0", "r6", "%2")
334 "unlock %0, @%2; \n\t"
336 : "=&r" (tmp0), "=&r" (tmp1)
339 #ifdef CONFIG_CHIP_M32700_TS1
341 #endif /* CONFIG_CHIP_M32700_TS1 */
345 static inline void _raw_write_unlock(rwlock_t *rw)
347 unsigned long tmp0, tmp1, tmp2;
349 __asm__ __volatile__ (
350 "# write_unlock \n\t"
351 "seth %1, #high(" RW_LOCK_BIAS_STR "); \n\t"
352 "or3 %1, %1, #low(" RW_LOCK_BIAS_STR "); \n\t"
354 "clrpsw #0x40 -> nop; \n\t"
355 DCACHE_CLEAR("%0", "r7", "%3")
358 "unlock %0, @%3; \n\t"
360 : "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
363 #ifdef CONFIG_CHIP_M32700_TS1
365 #endif /* CONFIG_CHIP_M32700_TS1 */
369 #define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
371 static inline int _raw_write_trylock(rwlock_t *lock)
373 atomic_t *count = (atomic_t *)lock;
374 if (atomic_sub_and_test(RW_LOCK_BIAS, count))
376 atomic_add(RW_LOCK_BIAS, count);
380 #endif /* _ASM_M32R_SPINLOCK_H */