Skip to content

Commit

Permalink
s390/spinlock: fix system hang with spin_retry <= 0
Browse files Browse the repository at this point in the history
On LPAR, when spin_retry is set to <= 0, arch_spin_lock_wait() and
arch_spin_lock_wait_flags() may end up in a while(1) loop w/o doing
any compare and swap operation. To fix this, use do/while instead of
for loop.

Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Gerald Schaefer authored and Martin Schwidefsky committed May 20, 2014
1 parent f1a8582 commit 2e4006b
Showing 1 changed file with 8 additions and 6 deletions.
14 changes: 8 additions & 6 deletions arch/s390/lib/spinlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,20 @@ __setup("spin_retry=", spin_retry_setup);

void arch_spin_lock_wait(arch_spinlock_t *lp)
{
int count = spin_retry;
unsigned int cpu = SPINLOCK_LOCKVAL;
unsigned int owner;
int count;

while (1) {
owner = lp->lock;
if (!owner || smp_vcpu_scheduled(~owner)) {
for (count = spin_retry; count > 0; count--) {
count = spin_retry;
do {
if (arch_spin_is_locked(lp))
continue;
if (_raw_compare_and_swap(&lp->lock, 0, cpu))
return;
}
} while (count-- > 0);
if (MACHINE_IS_LPAR)
continue;
}
Expand All @@ -53,22 +54,23 @@ EXPORT_SYMBOL(arch_spin_lock_wait);

void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
{
int count = spin_retry;
unsigned int cpu = SPINLOCK_LOCKVAL;
unsigned int owner;
int count;

local_irq_restore(flags);
while (1) {
owner = lp->lock;
if (!owner || smp_vcpu_scheduled(~owner)) {
for (count = spin_retry; count > 0; count--) {
count = spin_retry;
do {
if (arch_spin_is_locked(lp))
continue;
local_irq_disable();
if (_raw_compare_and_swap(&lp->lock, 0, cpu))
return;
local_irq_restore(flags);
}
} while (count-- > 0);
if (MACHINE_IS_LPAR)
continue;
}
Expand Down

0 comments on commit 2e4006b

Please sign in to comment.