All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeremy Fitzhardinge <jeremy@goop.org>
To: "H. Peter Anvin" <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@elte.hu>,
	the arch/x86 maintainers <x86@kernel.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Nick Piggin <npiggin@kernel.dk>,
	Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Subject: [PATCH 02/15] x86/ticketlock: convert spin loop to C
Date: Mon, 22 Aug 2011 16:14:58 -0700	[thread overview]
Message-ID: <f04120629b8b1cfa1c306373e34320687305a518.1314054734.git.jeremy.fitzhardinge@citrix.com> (raw)
In-Reply-To: <cover.1314045780.git.jeremy.fitzhardinge@citrix.com>
In-Reply-To: <cover.1314054734.git.jeremy.fitzhardinge@citrix.com>

From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>

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>
---
 arch/x86/include/asm/spinlock.h |   58 +++++++++++++++++++-------------------
 1 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
index d6d5784..f48a6e3 100644
--- a/arch/x86/include/asm/spinlock.h
+++ b/arch/x86/include/asm/spinlock.h
@@ -58,21 +58,21 @@
 #if (NR_CPUS < 256)
 static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
 {
-	unsigned short inc = 1 << TICKET_SHIFT;
-
-	asm volatile (
-		LOCK_PREFIX "xaddw %w0, %1\n"
-		"1:\t"
-		"cmpb %h0, %b0\n\t"
-		"je 2f\n\t"
-		"rep ; nop\n\t"
-		"movb %1, %b0\n\t"
-		/* don't need lfence here, because loads are in-order */
-		"jmp 1b\n"
-		"2:"
-		: "+Q" (inc), "+m" (lock->slock)
-		:
-		: "memory", "cc");
+	register union {
+		struct __raw_tickets tickets;
+		unsigned short slock;
+	} inc = { .slock = 1 << TICKET_SHIFT };
+
+	asm volatile (LOCK_PREFIX "xaddw %w0, %1\n"
+		      : "+Q" (inc), "+m" (lock->slock) : : "memory", "cc");
+
+	for (;;) {
+		if (inc.tickets.head == inc.tickets.tail)
+			goto out;
+		cpu_relax();
+		inc.tickets.head = ACCESS_ONCE(lock->tickets.head);
+	}
+out:	barrier();		/* make sure nothing creeps before the lock is taken */
 }
 
 static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
@@ -105,22 +105,22 @@ static __always_inline void __ticket_spin_unlock(arch_spinlock_t *lock)
 static __always_inline void __ticket_spin_lock(arch_spinlock_t *lock)
 {
 	unsigned inc = 1 << TICKET_SHIFT;
-	unsigned tmp;
+	__ticket_t tmp;
 
-	asm volatile(LOCK_PREFIX "xaddl %0, %1\n"
-		     "movzwl %w0, %2\n\t"
-		     "shrl $16, %0\n\t"
-		     "1:\t"
-		     "cmpl %0, %2\n\t"
-		     "je 2f\n\t"
-		     "rep ; nop\n\t"
-		     "movzwl %1, %2\n\t"
-		     /* don't need lfence here, because loads are in-order */
-		     "jmp 1b\n"
-		     "2:"
-		     : "+r" (inc), "+m" (lock->slock), "=&r" (tmp)
-		     :
-		     : "memory", "cc");
+	asm volatile(LOCK_PREFIX "xaddl %0, %1\n\t"
+		     : "+r" (inc), "+m" (lock->slock)
+		     : : "memory", "cc");
+
+	tmp = inc;
+	inc >>= TICKET_SHIFT;
+
+	for (;;) {
+		if ((__ticket_t)inc == tmp)
+			goto out;
+		cpu_relax();
+		tmp = ACCESS_ONCE(lock->tickets.head);
+	}
+out:	barrier();		/* make sure nothing creeps before the lock is taken */
 }
 
 static __always_inline int __ticket_spin_trylock(arch_spinlock_t *lock)
-- 
1.7.6


  parent reply	other threads:[~2011-08-22 23:15 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-08-22 23:14 [PATCH 00/12] x86: Ticket lock cleanup Jeremy Fitzhardinge
     [not found] ` <cover.1314054734.git.jeremy.fitzhardinge@citrix.com>
2011-08-22 23:14   ` [PATCH 01/15] x86/ticketlock: clean up types and accessors Jeremy Fitzhardinge
2011-08-22 23:14   ` Jeremy Fitzhardinge [this message]
2011-08-22 23:14   ` [PATCH 03/15] x86/ticketlock: Use C for __ticket_spin_unlock Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 04/15] x86/ticketlock: make large and small ticket versions of spin_lock the same Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 05/15] x86/ticketlock: make __ticket_spin_lock common Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 06/15] x86/ticketlock: make __ticket_spin_trylock common Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 07/15] x86: add xadd helper macro Jeremy Fitzhardinge
2011-08-22 23:29     ` H. Peter Anvin
2011-08-22 23:43       ` Jeremy Fitzhardinge
2011-08-23  4:41         ` H. Peter Anvin
2011-08-23 10:59     ` Peter Zijlstra
2011-08-23 16:34       ` Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 08/15] x86/ticketlock: use xadd helper Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 09/15] x86/cmpxchg: linux/alternative.h has LOCK_PREFIX Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 10/15] x86/cmpxchg: move 32-bit __cmpxchg_wrong_size to match 64 bit Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 11/15] x86/cmpxchg: move 64-bit set64_bit() to match 32-bit Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 12/15] x86/cmpxchg: unify cmpxchg into cmpxchg.h Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 13/15] x86: add cmpxchg_flag() variant Jeremy Fitzhardinge
2011-08-23 19:01     ` Christoph Lameter
2011-08-23 19:22       ` H. Peter Anvin
2011-08-23 19:52         ` Christoph Lameter
2011-08-23 21:03           ` H. Peter Anvin
2011-08-23 19:53       ` Jeremy Fitzhardinge
2011-08-23 20:45         ` H. Peter Anvin
2011-08-23 22:15           ` Jeremy Fitzhardinge
2011-08-23 22:43             ` H. Peter Anvin
2011-08-24 13:54               ` Christoph Lameter
2011-08-24 13:53             ` Christoph Lameter
2011-08-24 16:33               ` Jeremy Fitzhardinge
2011-08-24 19:27                 ` Christoph Lameter
2011-08-24 20:15                   ` Jeremy Fitzhardinge
2011-08-24 20:31                   ` H. Peter Anvin
2011-08-24 20:38                     ` Jeremy Fitzhardinge
2011-08-24 23:04                       ` H. Peter Anvin
2011-08-24 23:11                         ` Linus Torvalds
2011-08-24 23:19                           ` Jeremy Fitzhardinge
2011-08-25 14:07                             ` Christoph Lameter
2011-08-22 23:15   ` [PATCH 14/15] x86/ticketlocks: use cmpxchg_flag for trylock Jeremy Fitzhardinge
2011-08-22 23:15   ` [PATCH 15/15] x86: use cmpxchg_flag() where applicable Jeremy Fitzhardinge

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f04120629b8b1cfa1c306373e34320687305a518.1314054734.git.jeremy.fitzhardinge@citrix.com \
    --to=jeremy@goop.org \
    --cc=hpa@zytor.com \
    --cc=jeremy.fitzhardinge@citrix.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=npiggin@kernel.dk \
    --cc=peterz@infradead.org \
    --cc=torvalds@linux-foundation.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.