aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/include/asm/spinlock.h
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2010-07-02 20:06:04 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2011-08-29 16:45:43 -0400
commitc576a3ea905c25d50339503e0e5c7fef724e0147 (patch)
treecce69d03234f842428f42518aca329a38862207c /arch/x86/include/asm/spinlock.h
parent84eb950db13ca40a0572ce9957e14723500943d6 (diff)
x86, ticketlock: Convert spin loop to C
The inner loop of __ticket_spin_lock isn't doing anything very special, so reimplement it in C. For the 8 bit ticket lock variant, we use a register union to get direct access to the lower and upper bytes in the tickets, but unfortunately gcc won't generate a direct comparison between the two halves of the register, so the generated asm isn't quite as pretty as the hand-coded version. However benchmarking shows that this is actually a small improvement in runtime performance on some benchmarks, and never a slowdown. We also need to make sure there's a barrier at the end of the lock loop to make sure that the compiler doesn't move any instructions from within the locked region into the region where we don't yet own the lock. Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Link: http://lkml.kernel.org/r/4E5BCC40.3030501@goop.org Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/include/asm/spinlock.h')
-rw-r--r--arch/x86/include/asm/spinlock.h60
1 files changed, 30 insertions, 30 deletions
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
index ea2a04f69ca9..5240cdefa683 100644
--- a/arch/x86/include/asm/spinlock.h
+++ b/arch/x86/include/asm/spinlock.h
@@ -57,21 +57,21 @@
57#if (NR_CPUS < 256) 57#if (NR_CPUS < 256)
58static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock) 58static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
59{ 59{
60 unsigned short inc = 1 << TICKET_SHIFT; 60 register union {
61 61 struct __raw_tickets tickets;
62 asm volatile ( 62 unsigned short slock;
63 LOCK_PREFIX "xaddw %w0, %1\n" 63 } inc = { .slock = 1 << TICKET_SHIFT };
64 "1:\t" 64
65 "cmpb %h0, %b0\n\t" 65 asm volatile (LOCK_PREFIX "xaddw %w0, %1\n"
66 "je 2f\n\t" 66 : "+Q" (inc), "+m" (lock->slock) : : "memory", "cc");
67 "rep ; nop\n\t" 67
68 "movb %1, %b0\n\t" 68 for (;;) {
69 /* don't need lfence here, because loads are in-order */ 69 if (inc.tickets.head == inc.tickets.tail)
70 "jmp 1b\n" 70 break;
71 "2:" 71 cpu_relax();
72 : "+Q" (inc), "+m" (lock->slock) 72 inc.tickets.head = ACCESS_ONCE(lock->tickets.head);
73 : 73 }
74 : "memory", "cc"); 74 barrier(); /* make sure nothing creeps before the lock is taken */
75} 75}
76 76
77static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock) 77static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
@@ -104,22 +104,22 @@ static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
104static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock) 104static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
105{ 105{
106 unsigned inc = 1 << TICKET_SHIFT; 106 unsigned inc = 1 << TICKET_SHIFT;
107 unsigned tmp; 107 __ticket_t tmp;
108 108
109 asm volatile(LOCK_PREFIX "xaddl %0, %1\n" 109 asm volatile(LOCK_PREFIX "xaddl %0, %1\n\t"
110 "movzwl %w0, %2\n\t" 110 : "+r" (inc), "+m" (lock->slock)
111 "shrl $16, %0\n\t" 111 : : "memory", "cc");
112 "1:\t" 112
113 "cmpl %0, %2\n\t" 113 tmp = inc;
114 "je 2f\n\t" 114 inc >>= TICKET_SHIFT;
115 "rep ; nop\n\t" 115
116 "movzwl %1, %2\n\t" 116 for (;;) {
117 /* don't need lfence here, because loads are in-order */ 117 if ((__ticket_t)inc == tmp)
118 "jmp 1b\n" 118 break;
119 "2:" 119 cpu_relax();
120 : "+r" (inc), "+m" (lock->slock), "=&r" (tmp) 120 tmp = ACCESS_ONCE(lock->tickets.head);
121 : 121 }
122 : "memory", "cc"); 122 barrier(); /* make sure nothing creeps before the lock is taken */
123} 123}
124 124
125static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock) 125static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)