1 /* spinlock.h: 32-bit Sparc spinlock support.
3 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
6 #ifndef __SPARC_SPINLOCK_H
7 #define __SPARC_SPINLOCK_H
12 #include <asm/barrier.h>
13 #include <asm/processor.h> /* for cpu_relax */
15 #define arch_spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0)
17 static inline void arch_spin_unlock_wait(arch_spinlock_t
*lock
)
19 smp_cond_load_acquire(&lock
->lock
, !VAL
);
22 static inline void arch_spin_lock(arch_spinlock_t
*lock
)
26 "ldstub [%0], %%g2\n\t"
27 "orcc %%g2, 0x0, %%g0\n\t"
29 " ldub [%0], %%g2\n\t"
32 "orcc %%g2, 0x0, %%g0\n\t"
34 " ldub [%0], %%g2\n\t"
39 : "g2", "memory", "cc");
42 static inline int arch_spin_trylock(arch_spinlock_t
*lock
)
45 __asm__
__volatile__("ldstub [%1], %0"
52 static inline void arch_spin_unlock(arch_spinlock_t
*lock
)
54 __asm__
__volatile__("stb %%g0, [%0]" : : "r" (lock
) : "memory");
57 /* Read-write spinlocks, allowing multiple readers
58 * but only one writer.
60 * NOTE! it is quite common to have readers in interrupts
61 * but no interrupt writers. For those circumstances we
62 * can "mix" irq-safe locks - any writer needs to get a
63 * irq-safe write-lock, but readers can get non-irqsafe
66 * XXX This might create some problems with my dual spinlock
67 * XXX scheme, deadlocks etc. -DaveM
69 * Sort of like atomic_t's on Sparc, but even more clever.
71 * ------------------------------------
72 * | 24-bit counter | wlock | arch_rwlock_t
73 * ------------------------------------
76 * wlock signifies the one writer is in or somebody is updating
77 * counter. For a writer, if he successfully acquires the wlock,
78 * but counter is non-zero, he has to release the lock and wait,
79 * till both counter and wlock are zero.
81 * Unfortunately this scheme limits us to ~16,000,000 cpus.
83 static inline void __arch_read_lock(arch_rwlock_t
*rw
)
85 register arch_rwlock_t
*lp
asm("g1");
89 "call ___rw_read_enter\n\t"
90 " ldstub [%%g1 + 3], %%g2\n"
93 : "g2", "g4", "memory", "cc");
96 #define arch_read_lock(lock) \
97 do { unsigned long flags; \
98 local_irq_save(flags); \
99 __arch_read_lock(lock); \
100 local_irq_restore(flags); \
103 static inline void __arch_read_unlock(arch_rwlock_t
*rw
)
105 register arch_rwlock_t
*lp
asm("g1");
107 __asm__
__volatile__(
109 "call ___rw_read_exit\n\t"
110 " ldstub [%%g1 + 3], %%g2\n"
113 : "g2", "g4", "memory", "cc");
116 #define arch_read_unlock(lock) \
117 do { unsigned long flags; \
118 local_irq_save(flags); \
119 __arch_read_unlock(lock); \
120 local_irq_restore(flags); \
123 static inline void arch_write_lock(arch_rwlock_t
*rw
)
125 register arch_rwlock_t
*lp
asm("g1");
127 __asm__
__volatile__(
129 "call ___rw_write_enter\n\t"
130 " ldstub [%%g1 + 3], %%g2\n"
133 : "g2", "g4", "memory", "cc");
134 *(volatile __u32
*)&lp
->lock
= ~0U;
137 static void inline arch_write_unlock(arch_rwlock_t
*lock
)
139 __asm__
__volatile__(
146 static inline int arch_write_trylock(arch_rwlock_t
*rw
)
150 __asm__
__volatile__("ldstub [%1 + 3], %0"
156 val
= rw
->lock
& ~0xff;
158 ((volatile u8
*)&rw
->lock
)[3] = 0;
160 *(volatile u32
*)&rw
->lock
= ~0U;
166 static inline int __arch_read_trylock(arch_rwlock_t
*rw
)
168 register arch_rwlock_t
*lp
asm("g1");
169 register int res
asm("o0");
171 __asm__
__volatile__(
173 "call ___rw_read_try\n\t"
174 " ldstub [%%g1 + 3], %%g2\n"
177 : "g2", "g4", "memory", "cc");
181 #define arch_read_trylock(lock) \
182 ({ unsigned long flags; \
184 local_irq_save(flags); \
185 res = __arch_read_trylock(lock); \
186 local_irq_restore(flags); \
190 #define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
191 #define arch_read_lock_flags(rw, flags) arch_read_lock(rw)
192 #define arch_write_lock_flags(rw, flags) arch_write_lock(rw)
194 #define arch_spin_relax(lock) cpu_relax()
195 #define arch_read_relax(lock) cpu_relax()
196 #define arch_write_relax(lock) cpu_relax()
198 #define arch_read_can_lock(rw) (!((rw)->lock & 0xff))
199 #define arch_write_can_lock(rw) (!(rw)->lock)
201 #endif /* !(__ASSEMBLY__) */
203 #endif /* __SPARC_SPINLOCK_H */