{
unsigned int cpu = SPINLOCK_LOCKVAL;
unsigned int owner;
- int count;
+ int count, first_diag;
+ first_diag = 1;
while (1) {
owner = ACCESS_ONCE(lp->lock);
/* Try to get the lock if it is free. */
return;
continue;
}
- /* Check if the lock owner is running. */
- if (!smp_vcpu_scheduled(~owner)) {
+ /* First iteration: check if the lock owner is running. */
+ if (first_diag && !smp_vcpu_scheduled(~owner)) {
smp_yield_cpu(~owner);
+ first_diag = 0;
continue;
}
/* Loop for a while on the lock value. */
continue;
/*
* For multiple layers of hypervisors, e.g. z/VM + LPAR
- * yield the CPU if the lock is still unavailable.
+ * yield the CPU unconditionally. For LPAR rely on the
+ * sense running status.
*/
- if (!MACHINE_IS_LPAR)
+ if (!MACHINE_IS_LPAR || !smp_vcpu_scheduled(~owner)) {
smp_yield_cpu(~owner);
+ first_diag = 0;
+ }
}
}
EXPORT_SYMBOL(arch_spin_lock_wait);
{
unsigned int cpu = SPINLOCK_LOCKVAL;
unsigned int owner;
- int count;
+ int count, first_diag;
local_irq_restore(flags);
+ first_diag = 1;
while (1) {
owner = ACCESS_ONCE(lp->lock);
/* Try to get the lock if it is free. */
local_irq_restore(flags);
}
/* Check if the lock owner is running. */
- if (!smp_vcpu_scheduled(~owner)) {
+ if (first_diag && !smp_vcpu_scheduled(~owner)) {
smp_yield_cpu(~owner);
+ first_diag = 0;
continue;
}
/* Loop for a while on the lock value. */
continue;
/*
* For multiple layers of hypervisors, e.g. z/VM + LPAR
- * yield the CPU if the lock is still unavailable.
+ * yield the CPU unconditionally. For LPAR rely on the
+ * sense running status.
*/
- if (!MACHINE_IS_LPAR)
+ if (!MACHINE_IS_LPAR || !smp_vcpu_scheduled(~owner)) {
smp_yield_cpu(~owner);
+ first_diag = 0;
+ }
}
}
EXPORT_SYMBOL(arch_spin_lock_wait_flags);