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