1
2#ifndef _ALPHA_RWSEM_H
3#define _ALPHA_RWSEM_H
4
5
6
7
8
9
10#ifndef _LINUX_RWSEM_H
11#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
12#endif
13
14#ifdef __KERNEL__
15
16#include <linux/compiler.h>
17
18#define RWSEM_UNLOCKED_VALUE 0x0000000000000000L
19#define RWSEM_ACTIVE_BIAS 0x0000000000000001L
20#define RWSEM_ACTIVE_MASK 0x00000000ffffffffL
21#define RWSEM_WAITING_BIAS (-0x0000000100000000L)
22#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
23#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
24
25static inline int ___down_read(struct rw_semaphore *sem)
26{
27 long oldcount;
28#ifndef CONFIG_SMP
29 oldcount = sem->count.counter;
30 sem->count.counter += RWSEM_ACTIVE_READ_BIAS;
31#else
32 long temp;
33 __asm__ __volatile__(
34 "1: ldq_l %0,%1\n"
35 " addq %0,%3,%2\n"
36 " stq_c %2,%1\n"
37 " beq %2,2f\n"
38 " mb\n"
39 ".subsection 2\n"
40 "2: br 1b\n"
41 ".previous"
42 :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
43 :"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
44#endif
45 return (oldcount < 0);
46}
47
48static inline void __down_read(struct rw_semaphore *sem)
49{
50 if (unlikely(___down_read(sem)))
51 rwsem_down_read_failed(sem);
52}
53
54static inline int __down_read_killable(struct rw_semaphore *sem)
55{
56 if (unlikely(___down_read(sem)))
57 if (IS_ERR(rwsem_down_read_failed_killable(sem)))
58 return -EINTR;
59
60 return 0;
61}
62
63
64
65
66static inline int __down_read_trylock(struct rw_semaphore *sem)
67{
68 long old, new, res;
69
70 res = atomic_long_read(&sem->count);
71 do {
72 new = res + RWSEM_ACTIVE_READ_BIAS;
73 if (new <= 0)
74 break;
75 old = res;
76 res = atomic_long_cmpxchg(&sem->count, old, new);
77 } while (res != old);
78 return res >= 0 ? 1 : 0;
79}
80
81static inline long ___down_write(struct rw_semaphore *sem)
82{
83 long oldcount;
84#ifndef CONFIG_SMP
85 oldcount = sem->count.counter;
86 sem->count.counter += RWSEM_ACTIVE_WRITE_BIAS;
87#else
88 long temp;
89 __asm__ __volatile__(
90 "1: ldq_l %0,%1\n"
91 " addq %0,%3,%2\n"
92 " stq_c %2,%1\n"
93 " beq %2,2f\n"
94 " mb\n"
95 ".subsection 2\n"
96 "2: br 1b\n"
97 ".previous"
98 :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
99 :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
100#endif
101 return oldcount;
102}
103
104static inline void __down_write(struct rw_semaphore *sem)
105{
106 if (unlikely(___down_write(sem)))
107 rwsem_down_write_failed(sem);
108}
109
110static inline int __down_write_killable(struct rw_semaphore *sem)
111{
112 if (unlikely(___down_write(sem))) {
113 if (IS_ERR(rwsem_down_write_failed_killable(sem)))
114 return -EINTR;
115 }
116
117 return 0;
118}
119
120
121
122
123static inline int __down_write_trylock(struct rw_semaphore *sem)
124{
125 long ret = atomic_long_cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
126 RWSEM_ACTIVE_WRITE_BIAS);
127 if (ret == RWSEM_UNLOCKED_VALUE)
128 return 1;
129 return 0;
130}
131
132static inline void __up_read(struct rw_semaphore *sem)
133{
134 long oldcount;
135#ifndef CONFIG_SMP
136 oldcount = sem->count.counter;
137 sem->count.counter -= RWSEM_ACTIVE_READ_BIAS;
138#else
139 long temp;
140 __asm__ __volatile__(
141 " mb\n"
142 "1: ldq_l %0,%1\n"
143 " subq %0,%3,%2\n"
144 " stq_c %2,%1\n"
145 " beq %2,2f\n"
146 ".subsection 2\n"
147 "2: br 1b\n"
148 ".previous"
149 :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
150 :"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
151#endif
152 if (unlikely(oldcount < 0))
153 if ((int)oldcount - RWSEM_ACTIVE_READ_BIAS == 0)
154 rwsem_wake(sem);
155}
156
157static inline void __up_write(struct rw_semaphore *sem)
158{
159 long count;
160#ifndef CONFIG_SMP
161 sem->count.counter -= RWSEM_ACTIVE_WRITE_BIAS;
162 count = sem->count.counter;
163#else
164 long temp;
165 __asm__ __volatile__(
166 " mb\n"
167 "1: ldq_l %0,%1\n"
168 " subq %0,%3,%2\n"
169 " stq_c %2,%1\n"
170 " beq %2,2f\n"
171 " subq %0,%3,%0\n"
172 ".subsection 2\n"
173 "2: br 1b\n"
174 ".previous"
175 :"=&r" (count), "=m" (sem->count), "=&r" (temp)
176 :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
177#endif
178 if (unlikely(count))
179 if ((int)count == 0)
180 rwsem_wake(sem);
181}
182
183
184
185
186static inline void __downgrade_write(struct rw_semaphore *sem)
187{
188 long oldcount;
189#ifndef CONFIG_SMP
190 oldcount = sem->count.counter;
191 sem->count.counter -= RWSEM_WAITING_BIAS;
192#else
193 long temp;
194 __asm__ __volatile__(
195 "1: ldq_l %0,%1\n"
196 " addq %0,%3,%2\n"
197 " stq_c %2,%1\n"
198 " beq %2,2f\n"
199 " mb\n"
200 ".subsection 2\n"
201 "2: br 1b\n"
202 ".previous"
203 :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
204 :"Ir" (-RWSEM_WAITING_BIAS), "m" (sem->count) : "memory");
205#endif
206 if (unlikely(oldcount < 0))
207 rwsem_downgrade_wake(sem);
208}
209
210#endif
211#endif
212