This commit was manufactured by cvs2svn to create tag
[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 extern unsigned long __spin_trylock(volatile unsigned long *lock);
69
70 #endif
71
72 /*
73  * Read-write spinlocks, allowing multiple readers
74  * but only one writer.
75  *
76  * NOTE! it is quite common to have readers in interrupts
77  * but no interrupt writers. For those circumstances we
78  * can "mix" irq-safe locks - any writer needs to get a
79  * irq-safe write-lock, but readers can get non-irqsafe
80  * read-locks.
81  */
82 typedef struct {
83         volatile unsigned long lock;
84 #ifdef CONFIG_DEBUG_SPINLOCK
85         volatile unsigned long owner_pc;
86 #endif
87 } rwlock_t;
88
89 #ifdef CONFIG_DEBUG_SPINLOCK
90 #define RWLOCK_DEBUG_INIT     , 0
91 #else
92 #define RWLOCK_DEBUG_INIT     /* */
93 #endif
94
95 #define RW_LOCK_UNLOCKED (rwlock_t) { 0 RWLOCK_DEBUG_INIT }
96 #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
97
98 #define rwlock_is_locked(x)     ((x)->lock != 0)
99
100 #ifndef CONFIG_DEBUG_SPINLOCK
101
102 static __inline__ void _raw_read_lock(rwlock_t *rw)
103 {
104         unsigned int tmp;
105
106         __asm__ __volatile__(
107         "b      2f              # read_lock\n\
108 1:      lwzx    %0,0,%1\n\
109         cmpwi   0,%0,0\n\
110         blt+    1b\n\
111 2:      lwarx   %0,0,%1\n\
112         addic.  %0,%0,1\n\
113         ble-    1b\n"
114         PPC405_ERR77(0,%1)
115 "       stwcx.  %0,0,%1\n\
116         bne-    2b\n\
117         isync"
118         : "=&r"(tmp)
119         : "r"(&rw->lock)
120         : "cr0", "memory");
121 }
122
123 static __inline__ void _raw_read_unlock(rwlock_t *rw)
124 {
125         unsigned int tmp;
126
127         __asm__ __volatile__(
128         "eieio                  # read_unlock\n\
129 1:      lwarx   %0,0,%1\n\
130         addic   %0,%0,-1\n"
131         PPC405_ERR77(0,%1)
132 "       stwcx.  %0,0,%1\n\
133         bne-    1b"
134         : "=&r"(tmp)
135         : "r"(&rw->lock)
136         : "cr0", "memory");
137 }
138
139 static __inline__ void _raw_write_lock(rwlock_t *rw)
140 {
141         unsigned int tmp;
142
143         __asm__ __volatile__(
144         "b      2f              # write_lock\n\
145 1:      lwzx    %0,0,%1\n\
146         cmpwi   0,%0,0\n\
147         bne+    1b\n\
148 2:      lwarx   %0,0,%1\n\
149         cmpwi   0,%0,0\n\
150         bne-    1b\n"
151         PPC405_ERR77(0,%1)
152 "       stwcx.  %2,0,%1\n\
153         bne-    2b\n\
154         isync"
155         : "=&r"(tmp)
156         : "r"(&rw->lock), "r"(-1)
157         : "cr0", "memory");
158 }
159
160 static __inline__ void _raw_write_unlock(rwlock_t *rw)
161 {
162         __asm__ __volatile__("eieio             # write_unlock": : :"memory");
163         rw->lock = 0;
164 }
165
166 #else
167
168 extern void _raw_read_lock(rwlock_t *rw);
169 extern void _raw_read_unlock(rwlock_t *rw);
170 extern void _raw_write_lock(rwlock_t *rw);
171 extern void _raw_write_unlock(rwlock_t *rw);
172
173 #endif
174
175 #endif /* __ASM_SPINLOCK_H */
176 #endif /* __KERNEL__ */