License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[linux-block.git] / arch / metag / include / asm / spinlock_lock1.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __ASM_SPINLOCK_LOCK1_H
3 #define __ASM_SPINLOCK_LOCK1_H
4
5 #include <asm/bug.h>
6 #include <asm/global_lock.h>
7
8 static inline int arch_spin_is_locked(arch_spinlock_t *lock)
9 {
10         int ret;
11
12         barrier();
13         ret = lock->lock;
14         WARN_ON(ret != 0 && ret != 1);
15         return ret;
16 }
17
18 static inline void arch_spin_lock(arch_spinlock_t *lock)
19 {
20         unsigned int we_won = 0;
21         unsigned long flags;
22
23 again:
24         __global_lock1(flags);
25         if (lock->lock == 0) {
26                 fence();
27                 lock->lock = 1;
28                 we_won = 1;
29         }
30         __global_unlock1(flags);
31         if (we_won == 0)
32                 goto again;
33         WARN_ON(lock->lock != 1);
34 }
35
36 /* Returns 0 if failed to acquire lock */
37 static inline int arch_spin_trylock(arch_spinlock_t *lock)
38 {
39         unsigned long flags;
40         unsigned int ret;
41
42         __global_lock1(flags);
43         ret = lock->lock;
44         if (ret == 0) {
45                 fence();
46                 lock->lock = 1;
47         }
48         __global_unlock1(flags);
49         return (ret == 0);
50 }
51
52 static inline void arch_spin_unlock(arch_spinlock_t *lock)
53 {
54         barrier();
55         WARN_ON(!lock->lock);
56         lock->lock = 0;
57 }
58
59 /*
60  * RWLOCKS
61  *
62  *
63  * Write locks are easy - we just set bit 31.  When unlocking, we can
64  * just write zero since the lock is exclusively held.
65  */
66
67 static inline void arch_write_lock(arch_rwlock_t *rw)
68 {
69         unsigned long flags;
70         unsigned int we_won = 0;
71
72 again:
73         __global_lock1(flags);
74         if (rw->lock == 0) {
75                 fence();
76                 rw->lock = 0x80000000;
77                 we_won = 1;
78         }
79         __global_unlock1(flags);
80         if (we_won == 0)
81                 goto again;
82         WARN_ON(rw->lock != 0x80000000);
83 }
84
85 static inline int arch_write_trylock(arch_rwlock_t *rw)
86 {
87         unsigned long flags;
88         unsigned int ret;
89
90         __global_lock1(flags);
91         ret = rw->lock;
92         if (ret == 0) {
93                 fence();
94                 rw->lock = 0x80000000;
95         }
96         __global_unlock1(flags);
97
98         return (ret == 0);
99 }
100
101 static inline void arch_write_unlock(arch_rwlock_t *rw)
102 {
103         barrier();
104         WARN_ON(rw->lock != 0x80000000);
105         rw->lock = 0;
106 }
107
108 /* write_can_lock - would write_trylock() succeed? */
109 static inline int arch_write_can_lock(arch_rwlock_t *rw)
110 {
111         unsigned int ret;
112
113         barrier();
114         ret = rw->lock;
115         return (ret == 0);
116 }
117
118 /*
119  * Read locks are a bit more hairy:
120  *  - Exclusively load the lock value.
121  *  - Increment it.
122  *  - Store new lock value if positive, and we still own this location.
123  *    If the value is negative, we've already failed.
124  *  - If we failed to store the value, we want a negative result.
125  *  - If we failed, try again.
126  * Unlocking is similarly hairy.  We may have multiple read locks
127  * currently active.  However, we know we won't have any write
128  * locks.
129  */
130 static inline void arch_read_lock(arch_rwlock_t *rw)
131 {
132         unsigned long flags;
133         unsigned int we_won = 0, ret;
134
135 again:
136         __global_lock1(flags);
137         ret = rw->lock;
138         if (ret < 0x80000000) {
139                 fence();
140                 rw->lock = ret + 1;
141                 we_won = 1;
142         }
143         __global_unlock1(flags);
144         if (!we_won)
145                 goto again;
146 }
147
148 static inline void arch_read_unlock(arch_rwlock_t *rw)
149 {
150         unsigned long flags;
151         unsigned int ret;
152
153         __global_lock1(flags);
154         fence();
155         ret = rw->lock--;
156         __global_unlock1(flags);
157         WARN_ON(ret == 0);
158 }
159
160 static inline int arch_read_trylock(arch_rwlock_t *rw)
161 {
162         unsigned long flags;
163         unsigned int ret;
164
165         __global_lock1(flags);
166         ret = rw->lock;
167         if (ret < 0x80000000) {
168                 fence();
169                 rw->lock = ret + 1;
170         }
171         __global_unlock1(flags);
172         return (ret < 0x80000000);
173 }
174
175 /* read_can_lock - would read_trylock() succeed? */
176 static inline int arch_read_can_lock(arch_rwlock_t *rw)
177 {
178         unsigned int ret;
179
180         barrier();
181         ret = rw->lock;
182         return (ret < 0x80000000);
183 }
184
185 #endif /* __ASM_SPINLOCK_LOCK1_H */