File: /usr/src/linux/include/asm-ppc/spinlock.h
1 /*
2 * BK Id: SCCS/s.spinlock.h 1.9 08/21/01 16:07:48 trini
3 */
4 #ifndef __ASM_SPINLOCK_H
5 #define __ASM_SPINLOCK_H
6
7 #include <asm/system.h>
8
9 #undef SPINLOCK_DEBUG
10
11 /*
12 * Simple spin lock operations.
13 */
14
15 typedef struct {
16 volatile unsigned long lock;
17 #ifdef SPINLOCK_DEBUG
18 volatile unsigned long owner_pc;
19 volatile unsigned long owner_cpu;
20 #endif
21 } spinlock_t;
22
23 #ifdef __KERNEL__
24 #if SPINLOCK_DEBUG
25 #define SPINLOCK_DEBUG_INIT , 0, 0
26 #else
27 #define SPINLOCK_DEBUG_INIT /* */
28 #endif
29
30 #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 SPINLOCK_DEBUG_INIT }
31
32 #define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
33 #define spin_is_locked(x) ((x)->lock != 0)
34 #define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
35
36 #ifndef SPINLOCK_DEBUG
37
38 static inline void spin_lock(spinlock_t *lock)
39 {
40 unsigned long tmp;
41
42 __asm__ __volatile__(
43 "b 1f # spin_lock\n\
44 2: lwzx %0,0,%1\n\
45 cmpwi 0,%0,0\n\
46 bne+ 2b\n\
47 1: lwarx %0,0,%1\n\
48 cmpwi 0,%0,0\n\
49 bne- 2b\n\
50 stwcx. %2,0,%1\n\
51 bne- 2b\n\
52 isync"
53 : "=&r"(tmp)
54 : "r"(&lock->lock), "r"(1)
55 : "cr0", "memory");
56 }
57
58 static inline void spin_unlock(spinlock_t *lock)
59 {
60 __asm__ __volatile__("eieio # spin_unlock": : :"memory");
61 lock->lock = 0;
62 }
63
64 #define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
65
66 #else
67
68 extern void _spin_lock(spinlock_t *lock);
69 extern void _spin_unlock(spinlock_t *lock);
70 extern int spin_trylock(spinlock_t *lock);
71 extern unsigned long __spin_trylock(volatile unsigned long *lock);
72
73 #define spin_lock(lp) _spin_lock(lp)
74 #define spin_unlock(lp) _spin_unlock(lp)
75
76 #endif
77
78 /*
79 * Read-write spinlocks, allowing multiple readers
80 * but only one writer.
81 *
82 * NOTE! it is quite common to have readers in interrupts
83 * but no interrupt writers. For those circumstances we
84 * can "mix" irq-safe locks - any writer needs to get a
85 * irq-safe write-lock, but readers can get non-irqsafe
86 * read-locks.
87 */
88 typedef struct {
89 volatile unsigned long lock;
90 #ifdef SPINLOCK_DEBUG
91 volatile unsigned long owner_pc;
92 #endif
93 } rwlock_t;
94
95 #if SPINLOCK_DEBUG
96 #define RWLOCK_DEBUG_INIT , 0
97 #else
98 #define RWLOCK_DEBUG_INIT /* */
99 #endif
100
101 #define RW_LOCK_UNLOCKED (rwlock_t) { 0 RWLOCK_DEBUG_INIT }
102 #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
103
104 #ifndef SPINLOCK_DEBUG
105
106 static __inline__ void read_lock(rwlock_t *rw)
107 {
108 unsigned int tmp;
109
110 __asm__ __volatile__(
111 "b 2f # read_lock\n\
112 1: lwzx %0,0,%1\n\
113 cmpwi 0,%0,0\n\
114 blt+ 1b\n\
115 2: lwarx %0,0,%1\n\
116 addic. %0,%0,1\n\
117 ble- 1b\n\
118 stwcx. %0,0,%1\n\
119 bne- 2b\n\
120 isync"
121 : "=&r"(tmp)
122 : "r"(&rw->lock)
123 : "cr0", "memory");
124 }
125
126 static __inline__ void read_unlock(rwlock_t *rw)
127 {
128 unsigned int tmp;
129
130 __asm__ __volatile__(
131 "eieio # read_unlock\n\
132 1: lwarx %0,0,%1\n\
133 addic %0,%0,-1\n\
134 stwcx. %0,0,%1\n\
135 bne- 1b"
136 : "=&r"(tmp)
137 : "r"(&rw->lock)
138 : "cr0", "memory");
139 }
140
141 static __inline__ void write_lock(rwlock_t *rw)
142 {
143 unsigned int tmp;
144
145 __asm__ __volatile__(
146 "b 2f # write_lock\n\
147 1: lwzx %0,0,%1\n\
148 cmpwi 0,%0,0\n\
149 bne+ 1b\n\
150 2: lwarx %0,0,%1\n\
151 cmpwi 0,%0,0\n\
152 bne- 1b\n\
153 stwcx. %2,0,%1\n\
154 bne- 2b\n\
155 isync"
156 : "=&r"(tmp)
157 : "r"(&rw->lock), "r"(-1)
158 : "cr0", "memory");
159 }
160
161 static __inline__ void write_unlock(rwlock_t *rw)
162 {
163 __asm__ __volatile__("eieio # write_unlock": : :"memory");
164 rw->lock = 0;
165 }
166
167 #else
168
169 extern void _read_lock(rwlock_t *rw);
170 extern void _read_unlock(rwlock_t *rw);
171 extern void _write_lock(rwlock_t *rw);
172 extern void _write_unlock(rwlock_t *rw);
173
174 #define read_lock(rw) _read_lock(rw)
175 #define write_lock(rw) _write_lock(rw)
176 #define write_unlock(rw) _write_unlock(rw)
177 #define read_unlock(rw) _read_unlock(rw)
178
179 #endif
180
181 #endif /* __ASM_SPINLOCK_H */
182 #endif /* __KERNEL__ */
183