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