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