summaryrefslogtreecommitdiff
path: root/arch/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2014-09-22 14:25:25 (GMT)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-09-25 08:52:12 (GMT)
commit94232a4332de3bc210e7067fd43521b3eb12336a (patch)
treec89dddb5957396d5ae1b9814496064ad6135fa9a /arch/s390
parent2684e73a861fe7b2ab763f442207025a1d9bb6a6 (diff)
downloadlinux-94232a4332de3bc210e7067fd43521b3eb12336a.tar.xz
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 c717f4a..01f29bb 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -149,9 +149,10 @@ EXPORT_SYMBOL(_raw_read_trylock_retry);
void _raw_write_lock_wait(arch_rwlock_t *rw)
{
- unsigned int owner, old;
+ unsigned int owner, old, prev;
int count = spin_retry;
+ prev = 0x80000000;
owner = 0;
while (1) {
if (count-- <= 0) {
@@ -161,10 +162,13 @@ void _raw_write_lock_wait(arch_rwlock_t *rw)
}
old = ACCESS_ONCE(rw->lock);
owner = ACCESS_ONCE(rw->owner);
- if (old)
- continue;
- if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000))
- return;
+ if ((int) old >= 0 &&
+ _raw_compare_and_swap(&rw->lock, old, old | 0x80000000))
+ prev = old;
+ else
+ smp_rmb();
+ if ((old & 0x7fffffff) == 0 && (int) prev >= 0)
+ break;
}
}
EXPORT_SYMBOL(_raw_write_lock_wait);