aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/lib
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2015-01-14 11:52:33 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2015-01-23 09:17:04 -0500
commit2c72a44ecdf2a7ceac73844226e97ed2d5dd1e82 (patch)
treea8475e1252115402a27b4c9a822943782085b151 /arch/s390/lib
parent55b5eb75e7ccdfe94b6ea1be6bba0c21149abecf (diff)
s390/spinlock: add compare-and-delay to lock wait loops
Add the compare-and-delay instruction to the spin-lock and rw-lock retry loops. A CPU executing the compare-and-delay instruction stops until the lock value has changed. This is done to make the locking code for contended locks to behave better in regard to the multi- hreading facility. A thread of a core executing a compare-and-delay will allow the other threads of a core to get a larger share of the core resources. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/lib')
-rw-r--r--arch/s390/lib/spinlock.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index 034a35a3e9c1..d6c9991f7797 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -12,7 +12,15 @@
12#include <linux/smp.h> 12#include <linux/smp.h>
13#include <asm/io.h> 13#include <asm/io.h>
14 14
15int spin_retry = 1000; 15int spin_retry = -1;
16
17static int __init spin_retry_init(void)
18{
19 if (spin_retry < 0)
20 spin_retry = MACHINE_HAS_CAD ? 10 : 1000;
21 return 0;
22}
23early_initcall(spin_retry_init);
16 24
17/** 25/**
18 * spin_retry= parameter 26 * spin_retry= parameter
@@ -24,6 +32,11 @@ static int __init spin_retry_setup(char *str)
24} 32}
25__setup("spin_retry=", spin_retry_setup); 33__setup("spin_retry=", spin_retry_setup);
26 34
35static inline void _raw_compare_and_delay(unsigned int *lock, unsigned int old)
36{
37 asm(".insn rsy,0xeb0000000022,%0,0,%1" : : "d" (old), "Q" (*lock));
38}
39
27void arch_spin_lock_wait(arch_spinlock_t *lp) 40void arch_spin_lock_wait(arch_spinlock_t *lp)
28{ 41{
29 unsigned int cpu = SPINLOCK_LOCKVAL; 42 unsigned int cpu = SPINLOCK_LOCKVAL;
@@ -46,6 +59,8 @@ void arch_spin_lock_wait(arch_spinlock_t *lp)
46 /* Loop for a while on the lock value. */ 59 /* Loop for a while on the lock value. */
47 count = spin_retry; 60 count = spin_retry;
48 do { 61 do {
62 if (MACHINE_HAS_CAD)
63 _raw_compare_and_delay(&lp->lock, owner);
49 owner = ACCESS_ONCE(lp->lock); 64 owner = ACCESS_ONCE(lp->lock);
50 } while (owner && count-- > 0); 65 } while (owner && count-- > 0);
51 if (!owner) 66 if (!owner)
@@ -84,6 +99,8 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
84 /* Loop for a while on the lock value. */ 99 /* Loop for a while on the lock value. */
85 count = spin_retry; 100 count = spin_retry;
86 do { 101 do {
102 if (MACHINE_HAS_CAD)
103 _raw_compare_and_delay(&lp->lock, owner);
87 owner = ACCESS_ONCE(lp->lock); 104 owner = ACCESS_ONCE(lp->lock);
88 } while (owner && count-- > 0); 105 } while (owner && count-- > 0);
89 if (!owner) 106 if (!owner)
@@ -100,11 +117,19 @@ EXPORT_SYMBOL(arch_spin_lock_wait_flags);
100 117
101int arch_spin_trylock_retry(arch_spinlock_t *lp) 118int arch_spin_trylock_retry(arch_spinlock_t *lp)
102{ 119{
120 unsigned int cpu = SPINLOCK_LOCKVAL;
121 unsigned int owner;
103 int count; 122 int count;
104 123
105 for (count = spin_retry; count > 0; count--) 124 for (count = spin_retry; count > 0; count--) {
106 if (arch_spin_trylock_once(lp)) 125 owner = ACCESS_ONCE(lp->lock);
107 return 1; 126 /* Try to get the lock if it is free. */
127 if (!owner) {
128 if (_raw_compare_and_swap(&lp->lock, 0, cpu))
129 return 1;
130 } else if (MACHINE_HAS_CAD)
131 _raw_compare_and_delay(&lp->lock, owner);
132 }
108 return 0; 133 return 0;
109} 134}
110EXPORT_SYMBOL(arch_spin_trylock_retry); 135EXPORT_SYMBOL(arch_spin_trylock_retry);
@@ -126,8 +151,11 @@ void _raw_read_lock_wait(arch_rwlock_t *rw)
126 } 151 }
127 old = ACCESS_ONCE(rw->lock); 152 old = ACCESS_ONCE(rw->lock);
128 owner = ACCESS_ONCE(rw->owner); 153 owner = ACCESS_ONCE(rw->owner);
129 if ((int) old < 0) 154 if ((int) old < 0) {
155 if (MACHINE_HAS_CAD)
156 _raw_compare_and_delay(&rw->lock, old);
130 continue; 157 continue;
158 }
131 if (_raw_compare_and_swap(&rw->lock, old, old + 1)) 159 if (_raw_compare_and_swap(&rw->lock, old, old + 1))
132 return; 160 return;
133 } 161 }
@@ -141,8 +169,11 @@ int _raw_read_trylock_retry(arch_rwlock_t *rw)
141 169
142 while (count-- > 0) { 170 while (count-- > 0) {
143 old = ACCESS_ONCE(rw->lock); 171 old = ACCESS_ONCE(rw->lock);
144 if ((int) old < 0) 172 if ((int) old < 0) {
173 if (MACHINE_HAS_CAD)
174 _raw_compare_and_delay(&rw->lock, old);
145 continue; 175 continue;
176 }
146 if (_raw_compare_and_swap(&rw->lock, old, old + 1)) 177 if (_raw_compare_and_swap(&rw->lock, old, old + 1))
147 return 1; 178 return 1;
148 } 179 }
@@ -173,6 +204,8 @@ void _raw_write_lock_wait(arch_rwlock_t *rw, unsigned int prev)
173 } 204 }
174 if ((old & 0x7fffffff) == 0 && (int) prev >= 0) 205 if ((old & 0x7fffffff) == 0 && (int) prev >= 0)
175 break; 206 break;
207 if (MACHINE_HAS_CAD)
208 _raw_compare_and_delay(&rw->lock, old);
176 } 209 }
177} 210}
178EXPORT_SYMBOL(_raw_write_lock_wait); 211EXPORT_SYMBOL(_raw_write_lock_wait);
@@ -201,6 +234,8 @@ void _raw_write_lock_wait(arch_rwlock_t *rw)
201 smp_rmb(); 234 smp_rmb();
202 if ((old & 0x7fffffff) == 0 && (int) prev >= 0) 235 if ((old & 0x7fffffff) == 0 && (int) prev >= 0)
203 break; 236 break;
237 if (MACHINE_HAS_CAD)
238 _raw_compare_and_delay(&rw->lock, old);
204 } 239 }
205} 240}
206EXPORT_SYMBOL(_raw_write_lock_wait); 241EXPORT_SYMBOL(_raw_write_lock_wait);
@@ -214,8 +249,11 @@ int _raw_write_trylock_retry(arch_rwlock_t *rw)
214 249
215 while (count-- > 0) { 250 while (count-- > 0) {
216 old = ACCESS_ONCE(rw->lock); 251 old = ACCESS_ONCE(rw->lock);
217 if (old) 252 if (old) {
253 if (MACHINE_HAS_CAD)
254 _raw_compare_and_delay(&rw->lock, old);
218 continue; 255 continue;
256 }
219 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000)) 257 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000))
220 return 1; 258 return 1;
221 } 259 }