diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2014-05-15 05:00:44 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2014-05-20 02:58:53 -0400 |
commit | bae8f567344a7cb6a23ca6e13096ba785c69eb42 (patch) | |
tree | a0d91d9abf8405646ffbd5201d8c1b7f2627563c /arch/s390/lib | |
parent | 2bf29df7460f4038f84ac5dea3cbe582d6d4af82 (diff) |
s390/spinlock,rwlock: always to a load-and-test first
In case a lock is contended it is better to do a load-and-test first
before trying to get the lock with compare-and-swap. This helps to avoid
unnecessary cache invalidations of the cacheline for the lock if the
CPU has to wait for the lock. For an uncontended lock doing the
compare-and-swap directly is a bit better, if the CPU does not have the
cacheline in its cache yet the compare-and-swap will get it read-write
immediately while a load-and-test would get it read-only first.
Always to the load-and-test first to avoid the cacheline invalidations
for the contended case outweight the potential read-only to read-write
cacheline upgrade for the uncontended case.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/lib')
-rw-r--r-- | arch/s390/lib/spinlock.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 3f0e682b7e62..284d879a9b8c 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c | |||
@@ -100,12 +100,9 @@ int arch_spin_trylock_retry(arch_spinlock_t *lp) | |||
100 | { | 100 | { |
101 | int count; | 101 | int count; |
102 | 102 | ||
103 | for (count = spin_retry; count > 0; count--) { | 103 | for (count = spin_retry; count > 0; count--) |
104 | if (arch_spin_is_locked(lp)) | ||
105 | continue; | ||
106 | if (arch_spin_trylock_once(lp)) | 104 | if (arch_spin_trylock_once(lp)) |
107 | return 1; | 105 | return 1; |
108 | } | ||
109 | return 0; | 106 | return 0; |
110 | } | 107 | } |
111 | EXPORT_SYMBOL(arch_spin_trylock_retry); | 108 | EXPORT_SYMBOL(arch_spin_trylock_retry); |
@@ -120,9 +117,9 @@ void _raw_read_lock_wait(arch_rwlock_t *rw) | |||
120 | smp_yield(); | 117 | smp_yield(); |
121 | count = spin_retry; | 118 | count = spin_retry; |
122 | } | 119 | } |
123 | if (!arch_read_can_lock(rw)) | 120 | old = ACCESS_ONCE(rw->lock); |
121 | if ((int) old < 0) | ||
124 | continue; | 122 | continue; |
125 | old = rw->lock & 0x7fffffffU; | ||
126 | if (_raw_compare_and_swap(&rw->lock, old, old + 1)) | 123 | if (_raw_compare_and_swap(&rw->lock, old, old + 1)) |
127 | return; | 124 | return; |
128 | } | 125 | } |
@@ -140,9 +137,9 @@ void _raw_read_lock_wait_flags(arch_rwlock_t *rw, unsigned long flags) | |||
140 | smp_yield(); | 137 | smp_yield(); |
141 | count = spin_retry; | 138 | count = spin_retry; |
142 | } | 139 | } |
143 | if (!arch_read_can_lock(rw)) | 140 | old = ACCESS_ONCE(rw->lock); |
141 | if ((int) old < 0) | ||
144 | continue; | 142 | continue; |
145 | old = rw->lock & 0x7fffffffU; | ||
146 | local_irq_disable(); | 143 | local_irq_disable(); |
147 | if (_raw_compare_and_swap(&rw->lock, old, old + 1)) | 144 | if (_raw_compare_and_swap(&rw->lock, old, old + 1)) |
148 | return; | 145 | return; |
@@ -156,9 +153,9 @@ int _raw_read_trylock_retry(arch_rwlock_t *rw) | |||
156 | int count = spin_retry; | 153 | int count = spin_retry; |
157 | 154 | ||
158 | while (count-- > 0) { | 155 | while (count-- > 0) { |
159 | if (!arch_read_can_lock(rw)) | 156 | old = ACCESS_ONCE(rw->lock); |
157 | if ((int) old < 0) | ||
160 | continue; | 158 | continue; |
161 | old = rw->lock & 0x7fffffffU; | ||
162 | if (_raw_compare_and_swap(&rw->lock, old, old + 1)) | 159 | if (_raw_compare_and_swap(&rw->lock, old, old + 1)) |
163 | return 1; | 160 | return 1; |
164 | } | 161 | } |
@@ -168,6 +165,7 @@ EXPORT_SYMBOL(_raw_read_trylock_retry); | |||
168 | 165 | ||
169 | void _raw_write_lock_wait(arch_rwlock_t *rw) | 166 | void _raw_write_lock_wait(arch_rwlock_t *rw) |
170 | { | 167 | { |
168 | unsigned int old; | ||
171 | int count = spin_retry; | 169 | int count = spin_retry; |
172 | 170 | ||
173 | while (1) { | 171 | while (1) { |
@@ -175,7 +173,8 @@ void _raw_write_lock_wait(arch_rwlock_t *rw) | |||
175 | smp_yield(); | 173 | smp_yield(); |
176 | count = spin_retry; | 174 | count = spin_retry; |
177 | } | 175 | } |
178 | if (!arch_write_can_lock(rw)) | 176 | old = ACCESS_ONCE(rw->lock); |
177 | if (old) | ||
179 | continue; | 178 | continue; |
180 | if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000)) | 179 | if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000)) |
181 | return; | 180 | return; |
@@ -185,6 +184,7 @@ EXPORT_SYMBOL(_raw_write_lock_wait); | |||
185 | 184 | ||
186 | void _raw_write_lock_wait_flags(arch_rwlock_t *rw, unsigned long flags) | 185 | void _raw_write_lock_wait_flags(arch_rwlock_t *rw, unsigned long flags) |
187 | { | 186 | { |
187 | unsigned int old; | ||
188 | int count = spin_retry; | 188 | int count = spin_retry; |
189 | 189 | ||
190 | local_irq_restore(flags); | 190 | local_irq_restore(flags); |
@@ -193,7 +193,8 @@ void _raw_write_lock_wait_flags(arch_rwlock_t *rw, unsigned long flags) | |||
193 | smp_yield(); | 193 | smp_yield(); |
194 | count = spin_retry; | 194 | count = spin_retry; |
195 | } | 195 | } |
196 | if (!arch_write_can_lock(rw)) | 196 | old = ACCESS_ONCE(rw->lock); |
197 | if (old) | ||
197 | continue; | 198 | continue; |
198 | local_irq_disable(); | 199 | local_irq_disable(); |
199 | if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000)) | 200 | if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000)) |
@@ -204,10 +205,12 @@ EXPORT_SYMBOL(_raw_write_lock_wait_flags); | |||
204 | 205 | ||
205 | int _raw_write_trylock_retry(arch_rwlock_t *rw) | 206 | int _raw_write_trylock_retry(arch_rwlock_t *rw) |
206 | { | 207 | { |
208 | unsigned int old; | ||
207 | int count = spin_retry; | 209 | int count = spin_retry; |
208 | 210 | ||
209 | while (count-- > 0) { | 211 | while (count-- > 0) { |
210 | if (!arch_write_can_lock(rw)) | 212 | old = ACCESS_ONCE(rw->lock); |
213 | if (old) | ||
211 | continue; | 214 | continue; |
212 | if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000)) | 215 | if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000)) |
213 | return 1; | 216 | return 1; |