|
@@ -41,8 +41,9 @@ void arch_spin_lock_wait(arch_spinlock_t *lp)
|
|
|
{
|
|
|
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. */
|
|
@@ -51,9 +52,10 @@ void arch_spin_lock_wait(arch_spinlock_t *lp)
|
|
|
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. */
|
|
@@ -67,10 +69,13 @@ void arch_spin_lock_wait(arch_spinlock_t *lp)
|
|
|
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);
|
|
@@ -79,9 +84,10 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
|
|
|
{
|
|
|
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. */
|
|
@@ -92,8 +98,9 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
|
|
|
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. */
|
|
@@ -107,10 +114,13 @@ void arch_spin_lock_wait_flags(arch_spinlock_t *lp, unsigned long flags)
|
|
|
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);
|