1#ifndef _ALPHA_SPINLOCK_H
2#define _ALPHA_SPINLOCK_H
3
4#include <linux/kernel.h>
5#include <asm/current.h>
6
7/*
8 * Simple spin lock operations.  There are two variants, one clears IRQ's
9 * on the local processor, one does not.
10 *
11 * We make no fairness assumptions. They have a cost.
12 */
13
14#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
15#define arch_spin_is_locked(x)	((x)->lock != 0)
16#define arch_spin_unlock_wait(x) \
17		do { cpu_relax(); } while ((x)->lock)
18
19static inline void arch_spin_unlock(arch_spinlock_t * lock)
20{
21	mb();
22	lock->lock = 0;
23}
24
25static inline void arch_spin_lock(arch_spinlock_t * lock)
26{
27	long tmp;
28
29	__asm__ __volatile__(
30	"1:	ldl_l	%0,%1\n"
31	"	bne	%0,2f\n"
32	"	lda	%0,1\n"
33	"	stl_c	%0,%1\n"
34	"	beq	%0,2f\n"
35	"	mb\n"
36	".subsection 2\n"
37	"2:	ldl	%0,%1\n"
38	"	bne	%0,2b\n"
39	"	br	1b\n"
40	".previous"
41	: "=&r" (tmp), "=m" (lock->lock)
42	: "m"(lock->lock) : "memory");
43}
44
45static inline int arch_spin_trylock(arch_spinlock_t *lock)
46{
47	return !test_and_set_bit(0, &lock->lock);
48}
49
50/***********************************************************/
51
52static inline int arch_read_can_lock(arch_rwlock_t *lock)
53{
54	return (lock->lock & 1) == 0;
55}
56
57static inline int arch_write_can_lock(arch_rwlock_t *lock)
58{
59	return lock->lock == 0;
60}
61
62static inline void arch_read_lock(arch_rwlock_t *lock)
63{
64	long regx;
65
66	__asm__ __volatile__(
67	"1:	ldl_l	%1,%0\n"
68	"	blbs	%1,6f\n"
69	"	subl	%1,2,%1\n"
70	"	stl_c	%1,%0\n"
71	"	beq	%1,6f\n"
72	"	mb\n"
73	".subsection 2\n"
74	"6:	ldl	%1,%0\n"
75	"	blbs	%1,6b\n"
76	"	br	1b\n"
77	".previous"
78	: "=m" (*lock), "=&r" (regx)
79	: "m" (*lock) : "memory");
80}
81
82static inline void arch_write_lock(arch_rwlock_t *lock)
83{
84	long regx;
85
86	__asm__ __volatile__(
87	"1:	ldl_l	%1,%0\n"
88	"	bne	%1,6f\n"
89	"	lda	%1,1\n"
90	"	stl_c	%1,%0\n"
91	"	beq	%1,6f\n"
92	"	mb\n"
93	".subsection 2\n"
94	"6:	ldl	%1,%0\n"
95	"	bne	%1,6b\n"
96	"	br	1b\n"
97	".previous"
98	: "=m" (*lock), "=&r" (regx)
99	: "m" (*lock) : "memory");
100}
101
102static inline int arch_read_trylock(arch_rwlock_t * lock)
103{
104	long regx;
105	int success;
106
107	__asm__ __volatile__(
108	"1:	ldl_l	%1,%0\n"
109	"	lda	%2,0\n"
110	"	blbs	%1,2f\n"
111	"	subl	%1,2,%2\n"
112	"	stl_c	%2,%0\n"
113	"	beq	%2,6f\n"
114	"2:	mb\n"
115	".subsection 2\n"
116	"6:	br	1b\n"
117	".previous"
118	: "=m" (*lock), "=&r" (regx), "=&r" (success)
119	: "m" (*lock) : "memory");
120
121	return success;
122}
123
124static inline int arch_write_trylock(arch_rwlock_t * lock)
125{
126	long regx;
127	int success;
128
129	__asm__ __volatile__(
130	"1:	ldl_l	%1,%0\n"
131	"	lda	%2,0\n"
132	"	bne	%1,2f\n"
133	"	lda	%2,1\n"
134	"	stl_c	%2,%0\n"
135	"	beq	%2,6f\n"
136	"2:	mb\n"
137	".subsection 2\n"
138	"6:	br	1b\n"
139	".previous"
140	: "=m" (*lock), "=&r" (regx), "=&r" (success)
141	: "m" (*lock) : "memory");
142
143	return success;
144}
145
146static inline void arch_read_unlock(arch_rwlock_t * lock)
147{
148	long regx;
149	__asm__ __volatile__(
150	"	mb\n"
151	"1:	ldl_l	%1,%0\n"
152	"	addl	%1,2,%1\n"
153	"	stl_c	%1,%0\n"
154	"	beq	%1,6f\n"
155	".subsection 2\n"
156	"6:	br	1b\n"
157	".previous"
158	: "=m" (*lock), "=&r" (regx)
159	: "m" (*lock) : "memory");
160}
161
162static inline void arch_write_unlock(arch_rwlock_t * lock)
163{
164	mb();
165	lock->lock = 0;
166}
167
168#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
169#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
170
171#endif /* _ALPHA_SPINLOCK_H */
172