Sophie

Sophie

distrib > Mandriva > current > x86_64 > by-pkgid > d41cc2729f5f0fbbd2607b14a49457f3 > files > 46

kernel-xen-2.6.32.11-2mdv2010.1.src.rpm

From: jbeulich@novell.com
Subject: Go into polling mode early if lock owner is not running
Patch-mainline: n/a

This could be merged into the original ticket spinlock code once
validated, if there wasn't the dependency on smp-processor-id.h, which
only gets introduced in the 2.6.32 merge.

--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/spinlock.h	2010-02-23 14:24:59.000000000 +0100
+++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/spinlock.h	2010-02-23 14:28:29.000000000 +0100
@@ -41,6 +41,10 @@
 #ifdef TICKET_SHIFT
 
 #include <asm/irqflags.h>
+#include <asm/smp-processor-id.h>
+#include <xen/interface/vcpu.h>
+
+DECLARE_PER_CPU(struct vcpu_runstate_info, runstate);
 
 int xen_spinlock_init(unsigned int cpu);
 void xen_spinlock_cleanup(unsigned int cpu);
@@ -113,6 +117,9 @@ static __always_inline int __ticket_spin
 	    :
 	    : "memory", "cc");
 
+	if (tmp)
+		lock->owner = raw_smp_processor_id();
+
 	return tmp;
 }
 #elif TICKET_SHIFT == 16
@@ -179,10 +186,17 @@ static __always_inline int __ticket_spin
 	    :
 	    : "memory", "cc");
 
+	if (tmp)
+		lock->owner = raw_smp_processor_id();
+
 	return tmp;
 }
 #endif
 
+#define __ticket_spin_count(lock) \
+	(per_cpu(runstate.state, (lock)->owner) == RUNSTATE_running \
+	 ? 1 << 10 : 1)
+
 static inline int __ticket_spin_is_locked(raw_spinlock_t *lock)
 {
 	int tmp = ACCESS_ONCE(lock->slock);
@@ -204,16 +218,18 @@ static __always_inline void __ticket_spi
 	bool free;
 
 	__ticket_spin_lock_preamble;
-	if (likely(free)) {
+	if (likely(free))
+		raw_local_irq_restore(flags);
+	else {
+		token = xen_spin_adjust(lock, token);
 		raw_local_irq_restore(flags);
-		return;
+		do {
+			count = __ticket_spin_count(lock);
+			__ticket_spin_lock_body;
+		} while (unlikely(!count)
+			 && !xen_spin_wait(lock, &token, flags));
 	}
-	token = xen_spin_adjust(lock, token);
-	raw_local_irq_restore(flags);
-	do {
-		count = 1 << 10;
-		__ticket_spin_lock_body;
-	} while (unlikely(!count) && !xen_spin_wait(lock, &token, flags));
+	lock->owner = raw_smp_processor_id();
 }
 
 static __always_inline void __ticket_spin_lock_flags(raw_spinlock_t *lock,
@@ -223,13 +239,15 @@ static __always_inline void __ticket_spi
 	bool free;
 
 	__ticket_spin_lock_preamble;
-	if (likely(free))
-		return;
-	token = xen_spin_adjust(lock, token);
-	do {
-		count = 1 << 10;
-		__ticket_spin_lock_body;
-	} while (unlikely(!count) && !xen_spin_wait(lock, &token, flags));
+	if (unlikely(!free)) {
+		token = xen_spin_adjust(lock, token);
+		do {
+			count = __ticket_spin_count(lock);
+			__ticket_spin_lock_body;
+		} while (unlikely(!count)
+			 && !xen_spin_wait(lock, &token, flags));
+	}
+	lock->owner = raw_smp_processor_id();
 }
 
 static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock)
@@ -246,6 +264,7 @@ static __always_inline void __ticket_spi
 #undef __ticket_spin_lock_preamble
 #undef __ticket_spin_lock_body
 #undef __ticket_spin_unlock_body
+#undef __ticket_spin_count
 #endif
 
 #define __raw_spin(n) __ticket_spin_##n
--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/spinlock_types.h	2010-01-18 16:52:32.000000000 +0100
+++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/spinlock_types.h	2010-01-26 09:48:51.000000000 +0100
@@ -24,6 +24,11 @@ typedef union {
 # define TICKET_SHIFT 16
 		u16 cur, seq;
 #endif
+#if CONFIG_NR_CPUS <= 256
+		u8 owner;
+#else
+		u16 owner;
+#endif
 #else
 /*
  * This differs from the pre-2.6.24 spinlock by always using xchgb
--- sle11sp1-2010-03-22.orig/arch/x86/kernel/time-xen.c	2010-03-01 14:46:13.000000000 +0100
+++ sle11sp1-2010-03-22/arch/x86/kernel/time-xen.c	2010-02-04 09:43:52.000000000 +0100
@@ -64,7 +64,7 @@ static DEFINE_PER_CPU(u64, processed_sto
 static DEFINE_PER_CPU(u64, processed_blocked_time);
 
 /* Current runstate of each CPU (updated automatically by the hypervisor). */
-static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
+DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
 
 /* Must be signed, as it's compared with s64 quantities which can be -ve. */
 #define NS_PER_TICK (1000000000LL/HZ)
--- sle11sp1-2010-03-22.orig/drivers/xen/core/spinlock.c	2010-02-23 12:31:40.000000000 +0100
+++ sle11sp1-2010-03-22/drivers/xen/core/spinlock.c	2010-03-22 12:58:39.000000000 +0100
@@ -38,6 +38,8 @@ int __cpuinit xen_spinlock_init(unsigned
 	};
 	int rc;
 
+	setup_runstate_area(cpu);
+
 	rc = bind_ipi_to_irqaction(SPIN_UNLOCK_VECTOR,
 				   cpu,
 				   &spinlock_action);
@@ -85,6 +87,7 @@ unsigned int xen_spin_adjust(const raw_s
 bool xen_spin_wait(raw_spinlock_t *lock, unsigned int *ptok,
                    unsigned int flags)
 {
+	unsigned int cpu = raw_smp_processor_id();
 	int irq = spinlock_irq;
 	bool rc;
 	typeof(vcpu_info(0)->evtchn_upcall_mask) upcall_mask;
@@ -92,7 +95,7 @@ bool xen_spin_wait(raw_spinlock_t *lock,
 	struct spinning spinning, *other;
 
 	/* If kicker interrupt not initialized yet, just spin. */
-	if (unlikely(irq < 0) || unlikely(!cpu_online(raw_smp_processor_id())))
+	if (unlikely(irq < 0) || unlikely(!cpu_online(cpu)))
 		return false;
 
 	/* announce we're spinning */
@@ -113,6 +116,7 @@ bool xen_spin_wait(raw_spinlock_t *lock,
 		 * we weren't looking.
 		 */
 		if (lock->cur == spinning.ticket) {
+			lock->owner = cpu;
 			/*
 			 * If we interrupted another spinlock while it was
 			 * blocking, make sure it doesn't block (again)
@@ -206,6 +210,8 @@ bool xen_spin_wait(raw_spinlock_t *lock,
 			if (!free)
 				token = spin_adjust(other->prev, lock, token);
 			other->ticket = token >> TICKET_SHIFT;
+			if (lock->cur == other->ticket)
+				lock->owner = cpu;
 		}
 	raw_local_irq_restore(upcall_mask);