MIPS: Select CONFIG_ARCH_USE_CMPXCHG_LOCKREF for MIPS64
authorPaul Burton <paul.burton@imgtec.com>
Thu, 30 Jul 2015 15:16:10 +0000 (08:16 -0700)
committerRalf Baechle <ralf@linux-mips.org>
Thu, 3 Sep 2015 10:08:01 +0000 (12:08 +0200)
On MIPS64 we have spinlocks that are 32b in size and an efficient
cmpxchg64 implementation, so we qualify to make use of cmpxchg backed
lockrefs. Select the ARCH_USE_CMPXCHG_LOCKREF Kconfig symbol and provide
a trivial implementation of arch_spin_value_unlocked to satisfy the
lockref code.

Using Linus' simple testcase from
http://article.gmane.org/gmane.linux.file-systems/77466 on a dual core
system with an in-development MIPS64 CPU running on FPGA I see around an
8% gain:

Pre-patch:
    Total loops: 252698
    Total loops: 251482
    Total loops: 250806
    Total loops: 252885
    Total loops: 251666

Post-patch:
    Total loops: 273728
    Total loops: 269932
    Total loops: 269341
    Total loops: 275004
    Total loops: 270208

[ralf@linux-mips.org: Fixed conflict.]

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
Cc: linux-kernel@vger.kernel.org
Cc: Maciej W. Rozycki <macro@codesourcery.com>
Cc: Markos Chandras <markos.chandras@imgtec.com>
Patchwork: https://patchwork.linux-mips.org/patch/10810/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/Kconfig
arch/mips/include/asm/spinlock.h

index 3c2e4c87d489e734e9e724a530c91af864113f12..449f840d5a7f9a76e081e17e868cda86822eddbc 100644 (file)
@@ -3,6 +3,7 @@ config MIPS
        default y
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
+       select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
        select HAVE_CONTEXT_TRACKING
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_IDE
index 9de4ba43dcd11aa9a9e029b936e7f1a488977f53..40196bebe849a0c825cc8a61e40b03440d14f31e 100644 (file)
@@ -42,6 +42,11 @@ static inline int arch_spin_is_locked(arch_spinlock_t *lock)
        return ((counters >> 16) ^ counters) & 0xffff;
 }
 
+static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+       return lock.h.serving_now == lock.h.ticket;
+}
+
 #define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
 #define arch_spin_unlock_wait(x) \
        while (arch_spin_is_locked(x)) { cpu_relax(); }