Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

locking/mcs: Better differentiate between MCS variants

We have two flavors of the MCS spinlock: standard and cancelable (OSQ).
While each one is independent of the other, we currently mix and match
them. This patch:

- Moves the OSQ code out of mcs_spinlock.h (which only deals with the traditional
version) into include/linux/osq_lock.h. No unnecessary code is added to the
more global header file, anything locks that make use of OSQ must include
it anyway.

- Renames mcs_spinlock.c to osq_lock.c. This file only contains osq code.

- Introduces a CONFIG_LOCK_SPIN_ON_OWNER in order to only build osq_lock
if there is support for it.

Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Jason Low <jason.low2@hp.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mikulas Patocka <mpatocka@redhat.com>
Cc: Waiman Long <Waiman.Long@hp.com>
Link: http://lkml.kernel.org/r/1420573509-24774-5-git-send-email-dave@stgolabs.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Davidlohr Bueso and committed by
Ingo Molnar
d84b6728 4bd19084

+17 -25
+10 -2
include/linux/osq_lock.h
··· 5 5 * An MCS like lock especially tailored for optimistic spinning for sleeping 6 6 * lock implementations (mutex, rwsem, etc). 7 7 */ 8 - 9 - #define OSQ_UNLOCKED_VAL (0) 8 + struct optimistic_spin_node { 9 + struct optimistic_spin_node *next, *prev; 10 + int locked; /* 1 if lock acquired */ 11 + int cpu; /* encoded CPU # + 1 value */ 12 + }; 10 13 11 14 struct optimistic_spin_queue { 12 15 /* ··· 19 16 atomic_t tail; 20 17 }; 21 18 19 + #define OSQ_UNLOCKED_VAL (0) 20 + 22 21 /* Init macro and function. */ 23 22 #define OSQ_LOCK_UNLOCKED { ATOMIC_INIT(OSQ_UNLOCKED_VAL) } 24 23 ··· 28 23 { 29 24 atomic_set(&lock->tail, OSQ_UNLOCKED_VAL); 30 25 } 26 + 27 + extern bool osq_lock(struct optimistic_spin_queue *lock); 28 + extern void osq_unlock(struct optimistic_spin_queue *lock); 31 29 32 30 #endif
+4
kernel/Kconfig.locks
··· 231 231 def_bool y 232 232 depends on SMP && RWSEM_XCHGADD_ALGORITHM && ARCH_SUPPORTS_ATOMIC_RMW 233 233 234 + config LOCK_SPIN_ON_OWNER 235 + def_bool y 236 + depends on MUTEX_SPIN_ON_OWNER || RWSEM_SPIN_ON_OWNER 237 + 234 238 config ARCH_USE_QUEUE_RWLOCK 235 239 bool 236 240
+2 -1
kernel/locking/Makefile
··· 1 1 2 - obj-y += mutex.o semaphore.o rwsem.o mcs_spinlock.o 2 + obj-y += mutex.o semaphore.o rwsem.o 3 3 4 4 ifdef CONFIG_FUNCTION_TRACER 5 5 CFLAGS_REMOVE_lockdep.o = -pg ··· 14 14 obj-$(CONFIG_LOCKDEP) += lockdep_proc.o 15 15 endif 16 16 obj-$(CONFIG_SMP) += spinlock.o 17 + obj-$(CONFIG_LOCK_SPIN_ON_OWNER) += osq_lock.o 17 18 obj-$(CONFIG_SMP) += lglock.o 18 19 obj-$(CONFIG_PROVE_LOCKING) += spinlock.o 19 20 obj-$(CONFIG_RT_MUTEXES) += rtmutex.o
+1 -6
kernel/locking/mcs_spinlock.c kernel/locking/osq_lock.c
··· 1 1 #include <linux/percpu.h> 2 2 #include <linux/sched.h> 3 - #include "mcs_spinlock.h" 4 - 5 - #ifdef CONFIG_SMP 3 + #include <linux/osq_lock.h> 6 4 7 5 /* 8 6 * An MCS like lock especially tailored for optimistic spinning for sleeping ··· 201 203 if (next) 202 204 ACCESS_ONCE(next->locked) = 1; 203 205 } 204 - 205 - #endif 206 -
-16
kernel/locking/mcs_spinlock.h
··· 108 108 arch_mcs_spin_unlock_contended(&next->locked); 109 109 } 110 110 111 - /* 112 - * Cancellable version of the MCS lock above. 113 - * 114 - * Intended for adaptive spinning of sleeping locks: 115 - * mutex_lock()/rwsem_down_{read,write}() etc. 116 - */ 117 - 118 - struct optimistic_spin_node { 119 - struct optimistic_spin_node *next, *prev; 120 - int locked; /* 1 if lock acquired */ 121 - int cpu; /* encoded CPU # value */ 122 - }; 123 - 124 - extern bool osq_lock(struct optimistic_spin_queue *lock); 125 - extern void osq_unlock(struct optimistic_spin_queue *lock); 126 - 127 111 #endif /* __LINUX_MCS_SPINLOCK_H */