License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[linux-2.6-block.git] / arch / alpha / include / asm / rwsem.h
CommitLineData
b2441318 1/* SPDX-License-Identifier: GPL-2.0 */
1da177e4
LT
2#ifndef _ALPHA_RWSEM_H
3#define _ALPHA_RWSEM_H
4
5/*
6 * Written by Ivan Kokshaysky <ink@jurassic.park.msu.ru>, 2001.
7 * Based on asm-alpha/semaphore.h and asm-i386/rwsem.h
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>
1da177e4 17
1da177e4
LT
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)
1da177e4 24
1da177e4
LT
25static inline void __down_read(struct rw_semaphore *sem)
26{
27 long oldcount;
28#ifndef CONFIG_SMP
8ee62b18
JL
29 oldcount = sem->count.counter;
30 sem->count.counter += RWSEM_ACTIVE_READ_BIAS;
1da177e4
LT
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 if (unlikely(oldcount < 0))
46 rwsem_down_read_failed(sem);
47}
48
49/*
50 * trylock for reading -- returns 1 if successful, 0 if contention
51 */
52static inline int __down_read_trylock(struct rw_semaphore *sem)
53{
54 long old, new, res;
55
8ee62b18 56 res = atomic_long_read(&sem->count);
1da177e4
LT
57 do {
58 new = res + RWSEM_ACTIVE_READ_BIAS;
59 if (new <= 0)
60 break;
61 old = res;
8ee62b18 62 res = atomic_long_cmpxchg(&sem->count, old, new);
1da177e4
LT
63 } while (res != old);
64 return res >= 0 ? 1 : 0;
65}
66
7deb5eeb 67static inline long ___down_write(struct rw_semaphore *sem)
1da177e4
LT
68{
69 long oldcount;
70#ifndef CONFIG_SMP
8ee62b18
JL
71 oldcount = sem->count.counter;
72 sem->count.counter += RWSEM_ACTIVE_WRITE_BIAS;
1da177e4
LT
73#else
74 long temp;
75 __asm__ __volatile__(
76 "1: ldq_l %0,%1\n"
77 " addq %0,%3,%2\n"
78 " stq_c %2,%1\n"
79 " beq %2,2f\n"
80 " mb\n"
81 ".subsection 2\n"
82 "2: br 1b\n"
83 ".previous"
84 :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
85 :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
86#endif
7deb5eeb
MH
87 return oldcount;
88}
89
90static inline void __down_write(struct rw_semaphore *sem)
91{
92 if (unlikely(___down_write(sem)))
1da177e4
LT
93 rwsem_down_write_failed(sem);
94}
95
7deb5eeb
MH
96static inline int __down_write_killable(struct rw_semaphore *sem)
97{
98 if (unlikely(___down_write(sem)))
99 if (IS_ERR(rwsem_down_write_failed_killable(sem)))
100 return -EINTR;
101
102 return 0;
103}
104
1da177e4
LT
105/*
106 * trylock for writing -- returns 1 if successful, 0 if contention
107 */
108static inline int __down_write_trylock(struct rw_semaphore *sem)
109{
8ee62b18 110 long ret = atomic_long_cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
1da177e4
LT
111 RWSEM_ACTIVE_WRITE_BIAS);
112 if (ret == RWSEM_UNLOCKED_VALUE)
113 return 1;
114 return 0;
115}
116
117static inline void __up_read(struct rw_semaphore *sem)
118{
119 long oldcount;
120#ifndef CONFIG_SMP
8ee62b18
JL
121 oldcount = sem->count.counter;
122 sem->count.counter -= RWSEM_ACTIVE_READ_BIAS;
1da177e4
LT
123#else
124 long temp;
125 __asm__ __volatile__(
126 " mb\n"
127 "1: ldq_l %0,%1\n"
128 " subq %0,%3,%2\n"
129 " stq_c %2,%1\n"
130 " beq %2,2f\n"
131 ".subsection 2\n"
132 "2: br 1b\n"
133 ".previous"
134 :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
135 :"Ir" (RWSEM_ACTIVE_READ_BIAS), "m" (sem->count) : "memory");
136#endif
137 if (unlikely(oldcount < 0))
138 if ((int)oldcount - RWSEM_ACTIVE_READ_BIAS == 0)
139 rwsem_wake(sem);
140}
141
142static inline void __up_write(struct rw_semaphore *sem)
143{
144 long count;
145#ifndef CONFIG_SMP
8ee62b18
JL
146 sem->count.counter -= RWSEM_ACTIVE_WRITE_BIAS;
147 count = sem->count.counter;
1da177e4
LT
148#else
149 long temp;
150 __asm__ __volatile__(
151 " mb\n"
152 "1: ldq_l %0,%1\n"
153 " subq %0,%3,%2\n"
154 " stq_c %2,%1\n"
155 " beq %2,2f\n"
156 " subq %0,%3,%0\n"
157 ".subsection 2\n"
158 "2: br 1b\n"
159 ".previous"
160 :"=&r" (count), "=m" (sem->count), "=&r" (temp)
161 :"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
162#endif
163 if (unlikely(count))
164 if ((int)count == 0)
165 rwsem_wake(sem);
166}
167
168/*
169 * downgrade write lock to read lock
170 */
171static inline void __downgrade_write(struct rw_semaphore *sem)
172{
173 long oldcount;
174#ifndef CONFIG_SMP
8ee62b18
JL
175 oldcount = sem->count.counter;
176 sem->count.counter -= RWSEM_WAITING_BIAS;
1da177e4
LT
177#else
178 long temp;
179 __asm__ __volatile__(
180 "1: ldq_l %0,%1\n"
181 " addq %0,%3,%2\n"
182 " stq_c %2,%1\n"
183 " beq %2,2f\n"
184 " mb\n"
185 ".subsection 2\n"
186 "2: br 1b\n"
187 ".previous"
188 :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
189 :"Ir" (-RWSEM_WAITING_BIAS), "m" (sem->count) : "memory");
190#endif
191 if (unlikely(oldcount < 0))
192 rwsem_downgrade_wake(sem);
193}
194
1da177e4
LT
195#endif /* __KERNEL__ */
196#endif /* _ALPHA_RWSEM_H */