aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2014-09-22 10:25:25 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-09-25 04:52:12 -0400
commit94232a4332de3bc210e7067fd43521b3eb12336a (patch)
treec89dddb5957396d5ae1b9814496064ad6135fa9a /arch/s390
parent2684e73a861fe7b2ab763f442207025a1d9bb6a6 (diff)
s390/rwlock: improve writer fairness
Set the write-lock bit in the out-of-line rwlock code to indicate that a writer is waiting. Additional readers will no be able to get the lock until at least one writer got the lock. Additional writers have to wait for the first writer to release the lock again. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/lib/spinlock.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index c717f4a4c63e..01f29bb9c71b 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -149,9 +149,10 @@ EXPORT_SYMBOL(_raw_read_trylock_retry);
149 149
150void _raw_write_lock_wait(arch_rwlock_t *rw) 150void _raw_write_lock_wait(arch_rwlock_t *rw)
151{ 151{
152 unsigned int owner, old; 152 unsigned int owner, old, prev;
153 int count = spin_retry; 153 int count = spin_retry;
154 154
155 prev = 0x80000000;
155 owner = 0; 156 owner = 0;
156 while (1) { 157 while (1) {
157 if (count-- <= 0) { 158 if (count-- <= 0) {
@@ -161,10 +162,13 @@ void _raw_write_lock_wait(arch_rwlock_t *rw)
161 } 162 }
162 old = ACCESS_ONCE(rw->lock); 163 old = ACCESS_ONCE(rw->lock);
163 owner = ACCESS_ONCE(rw->owner); 164 owner = ACCESS_ONCE(rw->owner);
164 if (old) 165 if ((int) old >= 0 &&
165 continue; 166 _raw_compare_and_swap(&rw->lock, old, old | 0x80000000))
166 if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000)) 167 prev = old;
167 return; 168 else
169 smp_rmb();
170 if ((old & 0x7fffffff) == 0 && (int) prev >= 0)
171 break;
168 } 172 }
169} 173}
170EXPORT_SYMBOL(_raw_write_lock_wait); 174EXPORT_SYMBOL(_raw_write_lock_wait);