ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[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
31 #ifndef CONFIG_DEBUG_SPINLOCK
32
33 static inline void _raw_spin_lock(spinlock_t *lock)
34 {
35         unsigned long tmp;
36
37         __asm__ __volatile__(
38         "b      1f              # spin_lock\n\
39 2:      lwzx    %0,0,%1\n\
40         cmpwi   0,%0,0\n\
41         bne+    2b\n\
42 1:      lwarx   %0,0,%1\n\
43         cmpwi   0,%0,0\n\
44         bne-    2b\n"
45         PPC405_ERR77(0,%1)
46 "       stwcx.  %2,0,%1\n\
47         bne-    2b\n\
48         isync"
49         : "=&r"(tmp)
50         : "r"(&lock->lock), "r"(1)
51         : "cr0", "memory");
52 }
53
54 static inline void _raw_spin_unlock(spinlock_t *lock)
55 {
56         __asm__ __volatile__("eieio             # spin_unlock": : :"memory");
57         lock->lock = 0;
58 }
59
60 #define _raw_spin_trylock(l) (!test_and_set_bit(0,&(l)->lock))
61
62 #else
63
64 extern void _raw_spin_lock(spinlock_t *lock);
65 extern void _raw_spin_unlock(spinlock_t *lock);
66 extern int _raw_spin_trylock(spinlock_t *lock);
67 extern unsigned long __spin_trylock(volatile unsigned long *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__ void _raw_write_lock(rwlock_t *rw)
139 {
140         unsigned int tmp;
141
142         __asm__ __volatile__(
143         "b      2f              # write_lock\n\
144 1:      lwzx    %0,0,%1\n\
145         cmpwi   0,%0,0\n\
146         bne+    1b\n\
147 2:      lwarx   %0,0,%1\n\
148         cmpwi   0,%0,0\n\
149         bne-    1b\n"
150         PPC405_ERR77(0,%1)
151 "       stwcx.  %2,0,%1\n\
152         bne-    2b\n\
153         isync"
154         : "=&r"(tmp)
155         : "r"(&rw->lock), "r"(-1)
156         : "cr0", "memory");
157 }
158
159 static __inline__ void _raw_write_unlock(rwlock_t *rw)
160 {
161         __asm__ __volatile__("eieio             # write_unlock": : :"memory");
162         rw->lock = 0;
163 }
164
165 #else
166
167 extern void _raw_read_lock(rwlock_t *rw);
168 extern void _raw_read_unlock(rwlock_t *rw);
169 extern void _raw_write_lock(rwlock_t *rw);
170 extern void _raw_write_unlock(rwlock_t *rw);
171
172 #endif
173
174 #endif /* __ASM_SPINLOCK_H */
175 #endif /* __KERNEL__ */