MCS Lock: MCS lock code cleanup and optimizations
A message that is not in the archive (sent off-list or not yet received): [email protected]
v2 cover MCS Lock: MCS lock code cleanup and optimizations
In this patch series, we separated out the MCS lock code which was previously embedded in the mutex.c. This allows for easier reuse of MCS lock in other places like rwsem and qrwlock. We also did some micro optimizations and barrier cleanup.
This patches were previously part of the rwsem optimization patch series but now we spearate them out.
Tim Chen
v2:
1. change export mcs_spin_lock as a GPL export symbol
2. corrected mcs_spin_lock to references
Jason Low (2):
MCS Lock: optimizations and extra comments
MCS Lock: Barrier corrections
Tim Chen (1):
MCS Lock: Restructure the MCS lock defines and locking code into its
own file
Waiman Long (1):
MCS Lock: Make mcs_spinlock.h includable in other files
include/linux/mcs_spinlock.h | 99 ++++++++++++++++++++++++++++++++++++++++++ include/linux/mutex.h | 5 +- kernel/Makefile | 6 +- kernel/mcs_spinlock.c | 21 +++++++++ kernel/mutex.c | 60 +++---------------------- 5 files changed, 133 insertions(+), 58 deletions(-) create mode 100644 include/linux/mcs_spinlock.h create mode 100644 kernel/mcs_spinlock.c
Signature · 1 line
1.7.4.4
Quoted 25 lines · Tim Chen
In this patch series, we separated out the MCS lock code which was previously embedded in the
mutex.c. This allows for easier reuse of MCS lock in other places like rwsem and qrwlock. We also did some micro optimizations and barrier cleanup.This patches were previously part of the rwsem optimization patch series but now we spearate them out.
Tim Chen
v2:
1. change exportmcs_spin_lockas a GPL export symbol
2. correctedmcs_spin_lockto referencesJason Low (2):
MCS Lock: optimizations and extra comments
MCS Lock: Barrier correctionsTim Chen (1):
MCS Lock: Restructure the MCS lock defines and locking code into its
own fileWaiman Long (1):
MCS Lock: Makemcs_spinlock.hincludable in other files
Quoted 8 lines
include/linux/mcs_spinlock.h | 99 ++++++++++++++++++++++++++++++++++++++++++ include/linux/mutex.h | 5 +- kernel/Makefile | 6 +- kernel/mcs_spinlock.c | 21 +++++++++ kernel/mutex.c | 60 +++---------------------- 5 files changed, 133 insertions(+), 58 deletions(-) create mode 100644 include/linux/mcs_spinlock.h create mode 100644 kernel/mcs_spinlock.c
What base kernel does this apply over ?
Signature · 2 lines
Michel "Walken" Lespinasse A program is never fully debugged until the last user dies.
Quoted 35 lines · Michel Lespinasse
Quoted 25 lines · Tim Chen
In this patch series, we separated out the MCS lock code which was previously embedded in the
mutex.c. This allows for easier reuse of MCS lock in other places like rwsem and qrwlock. We also did some micro optimizations and barrier cleanup.This patches were previously part of the rwsem optimization patch series but now we spearate them out.
Tim Chen
v2:
1. change exportmcs_spin_lockas a GPL export symbol
2. correctedmcs_spin_lockto referencesJason Low (2):
MCS Lock: optimizations and extra comments
MCS Lock: Barrier correctionsTim Chen (1):
MCS Lock: Restructure the MCS lock defines and locking code into its
own fileWaiman Long (1):
MCS Lock: Makemcs_spinlock.hincludable in other filesQuoted 8 lines
include/linux/mcs_spinlock.h | 99 ++++++++++++++++++++++++++++++++++++++++++ include/linux/mutex.h | 5 +- kernel/Makefile | 6 +- kernel/mcs_spinlock.c | 21 +++++++++ kernel/mutex.c | 60 +++---------------------- 5 files changed, 133 insertions(+), 58 deletions(-) create mode 100644 include/linux/mcs_spinlock.h create mode 100644 kernel/mcs_spinlock.c
Quoted 2 lines
What base kernel does this apply over ?
Should be applicable on latest v3.12-rc7.
Tim
PATCH v2 1/4 MCS Lock: Restructure the MCS lock defines and locking code into its own file
In reply to a message not in the archiveWe will need the MCS lock code for doing optimistic spinning for rwsem. Extracting the MCS code from mutex.c and put into its own file allow us to reuse this code easily for rwsem.
--- include/linux/mcs_spinlock.h | 64 ++++++++++++++++++++++++++++++++++++++++++ include/linux/mutex.h | 5 ++- kernel/mutex.c | 60 ++++---------------------------------- 3 files changed, 74 insertions(+), 55 deletions(-) create mode 100644 include/linux/mcs_spinlock.h
include/linux/mcs_spinlock.h new file +64 -0
@@ -0,0 +1,64 @@ +/* +* MCS lock defines +* +* This file contains the main data structure and API definitions of MCS lock. +* +* The MCS lock (proposed by Mellor-Crummey and Scott) is a simple spin-lock +* with the desirable properties of being fair, and with each cpu trying +* to acquire the lock spinning on a local variable. +* It avoids expensive cache bouncings that common test-and-set spin-lock +* implementations incur. +*/ +#ifndef __LINUX_MCS_SPINLOCK_H +#define __LINUX_MCS_SPINLOCK_H + +struct mcs_spinlock { +struct mcs_spinlock *next; +int locked;/* 1 if lock acquired */ +}; + +/* +* We don't inline mcs_spin_lock() so that perf can correctly account for the +* time spent in this lock function. +*/ +static noinline +void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) +{ +struct mcs_spinlock *prev; + +/* Init node */ + node->locked =0 ; + node->next =NULL ; + + prev =xchg (lock, node); +if (likely (prev ==NULL )) { +/* Lock acquired */ + node->locked =1 ; +return ; + } +ACCESS_ONCE (prev->next) = node; +smp_wmb (); +/* Wait until the lock holder passes the lock down */ +while (!ACCESS_ONCE (node->locked)) +arch_mutex_cpu_relax (); +} + +static void mcs_spin_unlock (struct mcs_spinlock **lock,struct mcs_spinlock *node) +{ +struct mcs_spinlock *next =ACCESS_ONCE (node->next); + +if (likely (!next)) { +/* +* Release the lock by setting it to NULL +*/ +if (cmpxchg (lock, node,NULL ) == node) +return ; +/* Wait until the next pointer is set */ +while (!(next =ACCESS_ONCE (node->next))) +arch_mutex_cpu_relax (); + } +ACCESS_ONCE (next->locked) =1 ; +smp_wmb (); +} + +#endif /* __LINUX_MCS_SPINLOCK_H */
include/linux/mutex.h +3 -2
@@ -46,6 +46,7 @@* - detects multi-task circular deadlocks and prints out all affected * locks and tasks (and only those tasks) */ +struct mcs_spinlock ;struct mutex {/* 1: unlocked, 0: locked, negative: locked, possible waiters */ atomic_t count;
@@ -55,7 +56,7 @@ struct mutex {struct task_struct *owner;#endif #ifdef CONFIG_MUTEX_SPIN_ON_OWNER -void *spin_mlock;/* Spinner MCS lock */ +struct mcs_spinlock *mcs_lock;/* Spinner MCS lock */ #endif #ifdef CONFIG_DEBUG_MUTEXES const char *name;
@@ -179,4 +180,4 @@ extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);#define arch_mutex_cpu_relax () cpu_relax()#endif -#endif +#endif /* __LINUX_MUTEX_H */
kernel/mutex.c +7 -53
102 lines not on this page · raw message
Signature · 9 lines
1.7.4.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v2 2/4 MCS Lock: optimizations and extra comments
In reply to a message not in the archiveRemove unnecessary operation and make the cmpxchg(lock, node, NULL) == node check in mcs_spin_unlock() likely() as it is likely that a race did not occur most of the time.
Also add in more comments describing how the local node is used in MCS locks.
--- include/linux/mcs_spinlock.h | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)
include/linux/mcs_spinlock.h +11 -2
@@ -18,6 +18,12 @@ struct mcs_spinlock { };/* +* In order to acquire the lock, the caller should declare a local node and +* pass a reference of the node to this function in addition to the lock. +* If the lock has already been acquired, then this will proceed to spin +* on this node->locked until the previous lock holder sets the node->locked +* in mcs_spin_unlock(). +* * We don't inline mcs_spin_lock() so that perf can correctly account for the * time spent in this lock function. */
@@ -33,7 +39,6 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */ - node->locked =1 ;return ; }ACCESS_ONCE (prev->next) = node;
@@ -43,6 +48,10 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node)arch_mutex_cpu_relax (); } +/* +* Releases the lock. The caller should pass in the corresponding node that +* was used to acquire the lock. +*/ static void mcs_spin_unlock (struct mcs_spinlock **lock,struct mcs_spinlock *node) {struct mcs_spinlock *next =ACCESS_ONCE (node->next);
@@ -51,7 +60,7 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod/* * Release the lock by setting it to NULL */ -if (cmpxchg (lock, node,NULL ) == node) +if (likely (cmpxchg (lock, node,NULL ) == node))return ;/* Wait until the next pointer is set */ while (!(next =ACCESS_ONCE (node->next)))
Signature · 9 lines
1.7.4.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v2 3/4 MCS Lock: Barrier corrections
In reply to a message not in the archiveThis patch corrects the way memory barriers are used in the MCS lock and removes ones that are not needed. Also add comments on all barriers.
--- include/linux/mcs_spinlock.h | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)
include/linux/mcs_spinlock.h +11 -2
@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */ return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */ +smp_rmb (); }/*
@@ -58,6 +61,7 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nodif (likely (!next)) {/* +* cmpxchg() provides a memory barrier. * Release the lock by setting it to NULL */ if (likely (cmpxchg (lock, node,NULL ) == node))
@@ -65,9 +69,14 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod/* Wait until the next pointer is set */ while (!(next =ACCESS_ONCE (node->next))) arch_mutex_cpu_relax(); + }else { +/* +* Make sure all operations within the critical section +* happen before the lock is released. +*/ +smp_wmb (); }ACCESS_ONCE (next->locked) =1 ; -smp_wmb (); }#endif /* __LINUX_MCS_SPINLOCK_H */
Signature · 9 lines
1.7.4.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/4] MCS Lock: Barrier corrections
Quoted 2 lines · Tim Chen
This patch corrects the way memory barriers are used in the MCS lock and removes ones that are not needed. Also add comments on all barriers.
Hmm, I see that you're fixing up the barriers, but I still don't completely understand how what you have is correct. Hopefully you can help me out :)
Quoted 19 lines
Reviewed-by Paul E. McKenney <[email protected]>Reviewed-by Tim Chen <[email protected]>Signed-off-by Jason Low <[email protected]>--- include/linux/mcs_spinlock.h | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)include/linux/mcs_spinlock.h +1
-0@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */
include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) · line 51
Quoted 10 lines
include/linux/mcs_spinlock.h +3
-1return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */ +smp_rmb ();
Ok, so this is an smp_rmb() because we assume that stores aren't speculated, right? (i.e. the control dependency above is enough for stores to be ordered with respect to taking the lock)...
Quoted 12 lines
include/linux/mcs_spinlock.h +1
-0}/* @@ -58,6 +61,7 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nodif (likely (!next)) {/* +* cmpxchg() provides a memory barrier. * Release the lock by setting it to NULL */ if (likely (cmpxchg (lock, node,NULL ) == node))
include/linux/mcs_spinlock.h static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod · line 77
Quoted 9 lines
include/linux/mcs_spinlock.h +6
-0@@ -65,9 +69,14 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod/* Wait until the next pointer is set */ while (!(next =ACCESS_ONCE (node->next)))arch_mutex_cpu_relax (); + }else { +/* +* Make sure all operations within the critical section +* happen before the lock is released. +*/ +smp_wmb ();
...but I don't see what prevents reads inside the critical section from moving across the smp_wmb() here.
What am I missing?
Will
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/4] MCS Lock: Barrier corrections
Quoted 57 lines · Will Deacon
Quoted 2 lines · Tim Chen
This patch corrects the way memory barriers are used in the MCS lock and removes ones that are not needed. Also add comments on all barriers.
Hmm, I see that you're fixing up the barriers, but I still don't completely understand how what you have is correct. Hopefully you can help me out :)
Quoted 19 lines
Reviewed-by Paul E. McKenney <[email protected]>Reviewed-by Tim Chen <[email protected]>Signed-off-by Jason Low <[email protected]>--- include/linux/mcs_spinlock.h | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)include/linux/mcs_spinlock.h +1
-0@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */ include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) · line 51
Quoted 10 lines
include/linux/mcs_spinlock.h +3
-1return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */ +smp_rmb ();Ok, so this is an
smp_rmb()because we assume that stores aren't speculated, right? (i.e. the control dependency above is enough for stores to be ordered with respect to taking the lock)...Quoted 16 lines
include/linux/mcs_spinlock.h +2
-0}/* @@ -58,6 +61,7 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nodif (likely (!next)) {/* +* cmpxchg() provides a memory barrier. * Release the lock by setting it to NULL */ if (likely (cmpxchg (lock, node,NULL ) == node))@@ -65,9 +69,14 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod/* Wait until the next pointer is set */ while (!(next =ACCESS_ONCE (node->next)))arch_mutex_cpu_relax (); + }else {
Quoted 8 lines
include/linux/mcs_spinlock.h static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod · line 77
Quoted 5 lines
include/linux/mcs_spinlock.h +5
-0+/* +* Make sure all operations within the critical section +* happen before the lock is released. +*/ +smp_wmb ();...but I don't see what prevents reads inside the critical section from moving across the
smp_wmb()here.
This is to prevent any read in next critical section from creeping up before write in the previous critical section has completed
e.g.
CPU 1 execute
mcs_lock
x = 1;
...
x = 2;
mcs_unlockand CPU 2 execute
mcs_lock
y = x;
...
mcs_unlockWe expect y to be 2 after the "y = x" assignment. Without the proper rmb in lock and wmb in unlock, y could be 1 for CPU 2 with speculative read (i.e. before the x=2 assignment is completed).
Tim
Quoted 4 lines
What am I missing?
Will
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Peter Zijlstra
maintainerRe: [PATCH v2 3/4] MCS Lock: Barrier corrections
Quoted 33 lines · Tim Chen
Quoted 32 lines · Will Deacon
Quoted 2 lines · Tim Chen
This patch corrects the way memory barriers are used in the MCS lock and removes ones that are not needed. Also add comments on all barriers.
Hmm, I see that you're fixing up the barriers, but I still don't completely understand how what you have is correct. Hopefully you can help me out :)
Quoted 25 lines
Reviewed-by Paul E. McKenney <[email protected]>Reviewed-by Tim Chen <[email protected]>Signed-off-by Jason Low <[email protected]>--- include/linux/mcs_spinlock.h | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)include/linux/mcs_spinlock.h +1
-1@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */ return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))
Quoted 8 lines
Quoted 8 lines
include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) · line 51
Quoted 4 lines
include/linux/mcs_spinlock.h +3
-0arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */ +smp_rmb ();Ok, so this is an
smp_rmb()because we assume that stores aren't speculated, right? (i.e. the control dependency above is enough for stores to be ordered with respect to taking the lock)...
PaulMck completely confused me a few days ago with control dependencies etc.. Pretty much saying that C/C++ doesn't do those.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/4] MCS Lock: Barrier corrections
Quoted 34 lines · Peter Zijlstra
Quoted 33 lines · Tim Chen
Quoted 32 lines · Will Deacon
Quoted 2 lines · Tim Chen
This patch corrects the way memory barriers are used in the MCS lock and removes ones that are not needed. Also add comments on all barriers.
Hmm, I see that you're fixing up the barriers, but I still don't completely understand how what you have is correct. Hopefully you can help me out :)
Quoted 25 lines
Reviewed-by Paul E. McKenney <[email protected]>Reviewed-by Tim Chen <[email protected]>Signed-off-by Jason Low <[email protected]>--- include/linux/mcs_spinlock.h | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)include/linux/mcs_spinlock.h +1
-1@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */ return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))
Quoted 9 lines
Quoted 8 lines
Quoted 8 lines
include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) · line 51
Quoted 4 lines
include/linux/mcs_spinlock.h +3
-0arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */ +smp_rmb ();Ok, so this is an
smp_rmb()because we assume that stores aren't speculated, right? (i.e. the control dependency above is enough for stores to be ordered with respect to taking the lock)...
The smp_rmb was put in to make sure that the lock
is indeed set before we start doing speculative reads in next critical section.
Wonder if your concern is about the possibility of write in next critical section bleeding into read in previous critical section?
If reads and writes are re-ordered in previous critical section before mcs_spin_unlock, it may be possible that the previous critical section is still
reading when it set the lock for the next mcs in mcs_spin_unlock.
This allows the next critical section to start writing prematurely, before previous critical section finished all reads.
If this concern is valid, we should change the smp_wmb() to smp_mb() in the unlock function, to make sure previous critical section has completed all operations before next section starts.
Quoted 2 lines
PaulMck completely confused me a few days ago with control dependencies etc.. Pretty much saying that C/C++ doesn't do those.
Will appreciate feedback getting the barriers right.
Thanks.
Tim
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/4] MCS Lock: Barrier corrections
Quoted 45 lines · Tim Chen
Quoted 34 lines · Peter Zijlstra
Quoted 33 lines · Tim Chen
Quoted 32 lines · Will Deacon
Quoted 2 lines · Tim Chen
This patch corrects the way memory barriers are used in the MCS lock and removes ones that are not needed. Also add comments on all barriers.
Hmm, I see that you're fixing up the barriers, but I still don't completely understand how what you have is correct. Hopefully you can help me out :)
Quoted 25 lines
Reviewed-by Paul E. McKenney <[email protected]>Reviewed-by Tim Chen <[email protected]>Signed-off-by Jason Low <[email protected]>--- include/linux/mcs_spinlock.h | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)include/linux/mcs_spinlock.h +1
-1@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */ return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))Quoted 9 lines
Quoted 8 lines
Quoted 8 lines
include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) · line 51
Quoted 4 lines
include/linux/mcs_spinlock.h +3
-0arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */ +smp_rmb ();Ok, so this is an
smp_rmb()because we assume that stores aren't speculated, right? (i.e. the control dependency above is enough for stores to be ordered with respect to taking the lock)...
Quoted 6 lines
The
smp_rmbwas put in to make sure that the lock
is indeed set before we start doing speculative reads in next critical section.Wonder if your concern is about the possibility of write in next critical section bleeding into read in previous critical section?
Correct. You want to ensure that all accesses (reads and writes) that occur in program order after taking the lock occur inside the critical section.
Quoted 9 lines
If reads and writes are re-ordered in previous critical section before
mcs_spin_unlock, it may be possible that the previous critical section is still
reading when it set the lock for the next mcs inmcs_spin_unlock.
This allows the next critical section to start writing prematurely, before previous critical section finished all reads.If this concern is valid, we should change the
smp_wmb()tosmp_mb()in the unlock function, to make sure previous critical section has completed all operations before next section starts.
smp_rmb() is defined only to order reads against reads, so relying on the control dependency feels fragile. (On arm64, an smp_rmb() actually orders reads against reads/writes).
Quoted 4 lines
Quoted 2 lines
PaulMck completely confused me a few days ago with control dependencies etc.. Pretty much saying that C/C++ doesn't do those.
Will appreciate feedback getting the barriers right.
I'm not up to speed with C11, but an smp_mb() is certainly clearer to me, especially if you change the smb_wmb() in the unlock code into an smp_mb too.
Will
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/4] MCS Lock: Barrier corrections
In reply to Peter ZijlstraQuoted 43 lines · Peter Zijlstra
Quoted 33 lines · Tim Chen
Quoted 32 lines · Will Deacon
Quoted 2 lines · Tim Chen
This patch corrects the way memory barriers are used in the MCS lock and removes ones that are not needed. Also add comments on all barriers.
Hmm, I see that you're fixing up the barriers, but I still don't completely understand how what you have is correct. Hopefully you can help me out :)
Quoted 25 lines
Reviewed-by Paul E. McKenney <[email protected]>Reviewed-by Tim Chen <[email protected]>Signed-off-by Jason Low <[email protected]>--- include/linux/mcs_spinlock.h | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)include/linux/mcs_spinlock.h +1
-1@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */ return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))Quoted 8 lines
Quoted 8 lines
include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) · line 51
Quoted 4 lines
include/linux/mcs_spinlock.h +3
-0arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */ +smp_rmb ();Ok, so this is an
smp_rmb()because we assume that stores aren't speculated, right? (i.e. the control dependency above is enough for stores to be ordered with respect to taking the lock)...
Quoted 2 lines
PaulMck completely confused me a few days ago with control dependencies etc.. Pretty much saying that C/C++ doesn't do those.
I remember that there was a subtlety here, but don't remember what it was...
And while I do remember reviewing this code, I don't find any evidence that I gave my "Reviewed-by". Tim/Jason, if I fat-fingered this, please forward that email back to me.
Thanx, Paul
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/4] MCS Lock: Barrier corrections
Quoted 44 lines · Paul E. McKenney
Quoted 43 lines · Peter Zijlstra
Quoted 41 lines · Tim Chen
Quoted 40 lines · Will Deacon
Quoted 2 lines · Tim Chen
This patch corrects the way memory barriers are used in the MCS lock and removes ones that are not needed. Also add comments on all barriers.
Hmm, I see that you're fixing up the barriers, but I still don't completely understand how what you have is correct. Hopefully you can help me out :)
Quoted 19 lines
Reviewed-by Paul E. McKenney <[email protected]>Reviewed-by Tim Chen <[email protected]>Signed-off-by Jason Low <[email protected]>--- include/linux/mcs_spinlock.h | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)include/linux/mcs_spinlock.h +1
-0@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */ include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) · line 51
Quoted 10 lines
include/linux/mcs_spinlock.h +3
-1return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */ +smp_rmb ();Ok, so this is an
smp_rmb()because we assume that stores aren't speculated, right? (i.e. the control dependency above is enough for stores to be ordered with respect to taking the lock)...
Quoted 8 lines
Quoted 2 lines
PaulMck completely confused me a few days ago with control dependencies etc.. Pretty much saying that C/C++ doesn't do those.
I remember that there was a subtlety here, but don't remember what it was...
And while I do remember reviewing this code, I don't find any evidence that I gave my "Reviewed-by". Tim/Jason, if I fat-fingered this, please forward that email back to me.
Yes Paul, you didn't explicitly gave the Reviewed-by. I put it in there because you have given valuable comments on the potential critical section bleeding when reviewing initial version of the code.
I'll take it out now till you have explicitly given it. Appreciate if you can provide your feedback on the current version of code.
Thanks.
Tim
Quoted 3 lines
Thanx, Paul
Re: [PATCH v2 3/4] MCS Lock: Barrier corrections
Tim,
I have just sent out a patch as an addendum to your patch series. Hopefully that will address the memory barrier issue.
-Longman
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/4] MCS Lock: Barrier corrections
In reply to Tim Chen2013/11/6 Tim Chen <[email protected]>
Quoted 90 lines · Will Deacon
Quoted 3 lines · Tim Chen
Quoted 2 lines
This patch corrects the way memory barriers are used in the MCS lock and removes ones that are not needed. Also add comments on all
barriers.
Quoted 2 lines
Hmm, I see that you're fixing up the barriers, but I still don't
completely
Quoted 10 lines
understand how what you have is correct. Hopefully you can help me out :)
Review
Quoted 8 lines
Reviewed-by Paul E. McKenney <[email protected]>Reviewed-by Tim Chen <[email protected]>Signed-off-by Jason Low <[email protected]>--- include/linux/mcs_spinlock.h | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)(quoted diff) +0
-0
b/include/linux/mcs_spinlock.hQuoted 4 lines
include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock,
Quoted 4 lines
index 96f14299..93d445d 100644
include/linux/mcs_spinlock.h +0
-0@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock,struct
mcs_spinlock*node)Quoted 16 lines
Quoted 6 lines
include/linux/mcs_spinlock.h +1
-0node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
Quoted 10 lines
include/linux/mcs_spinlock.h +2
-1/* Lock acquired */ return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */
Quoted 3 lines
include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) · line 51
Quoted 1 line
include/linux/mcs_spinlock.h +1
-0+smp_rmb ();Ok, so this is an
smp_rmb()because we assume that stores aren'tspeculated,
Quoted 1 line
right? (i.e. the control dependency above is enough for stores to be
ordered
Quoted 6 lines
with respect to taking the lock)...
include/linux/mcs_spinlock.h static void mcs_spin_unlock(struct mcs_spinlock
Quoted 4 lines
include/linux/mcs_spinlock.h +0
-0}/* @@ -58,6 +61,7 @@ static void mcs_spin_unlock(struct mcs_spinlock**lock, struct
mcs_spinlock*nodQuoted 8 lines
include/linux/mcs_spinlock.h static void mcs_spin_unlock(struct mcs_spinlock
Quoted 8 lines
include/linux/mcs_spinlock.h +1
-0if (likely (!next)) {/* +* cmpxchg() provides a memory barrier. * Release the lock by setting it to NULL */ if (likely (cmpxchg (lock, node,NULL ) == node))@@ -65,9 +69,14 @@ static void mcs_spin_unlock(struct mcs_spinlock**lock, struct
mcs_spinlock*nodQuoted 10 lines
include/linux/mcs_spinlock.h static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod · line 77
Quoted 9 lines
include/linux/mcs_spinlock.h +6
-0/* Wait until the next pointer is set */ while (!(next =ACCESS_ONCE (node->next)))arch_mutex_cpu_relax (); + }else { +/* +* Make sure all operations within the critical section +* happen before the lock is released. +*/ +smp_wmb ();Quoted 2 lines
...but I don't see what prevents reads inside the critical section from moving across the
smp_wmb()here.This is to prevent any read in next critical section from creeping up before write in the previous critical section has completed
e.g.
CPU 1 executemcs_lock x = 1; ... x = 2; mcs_unlockand CPU 2 execute
Quoted 9 lines
mcs_lock y = x; ... mcs_unlockWe expect y to be 2 after the "y = x" assignment. Without the proper rmb in lock and wmb in unlock, y could be 1 for CPU 2 with speculative read (i.e. before the x=2 assignment is completed).
is it not a good example ?
why CPU2 will be waited the "x" set to "2" ? Maybe "y=x" assignment will be executed firstly than CPU1 in pipeline
because of out-of-reorder.
e.g.
CPU 1 execute
mcs_lock
x = 1;
...
x = 2;
flags = true;
mcs_unlockand CPU 2 execute
while (flags) {
mcs_lock
y = x;
...
mcs_unlock
}Re: [PATCH v2 3/4] MCS Lock: Barrier corrections
Quoted 55 lines · Figo.zhang
2013/11/6 Tim Chen <[email protected]<mailto:[email protected]>>
Quoted 44 lines · Will Deacon
Quoted 12 lines · Tim Chen
include/linux/mcs_spinlock.h +1
-0@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */ include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) · line 51
Quoted 10 lines
include/linux/mcs_spinlock.h +3
-1return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */ +smp_rmb ();Ok, so this is an
smp_rmb()because we assume that stores aren't speculated, right? (i.e. the control dependency above is enough for stores to be ordered with respect to taking the lock)...Quoted 16 lines
include/linux/mcs_spinlock.h +2
-0}/* @@ -58,6 +61,7 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nodif (likely (!next)) {/* +* cmpxchg() provides a memory barrier. * Release the lock by setting it to NULL */ if (likely (cmpxchg (lock, node,NULL ) == node))@@ -65,9 +69,14 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod/* Wait until the next pointer is set */ while (!(next =ACCESS_ONCE (node->next)))arch_mutex_cpu_relax (); + }else {Quoted 8 lines
include/linux/mcs_spinlock.h static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod · line 77
Quoted 5 lines
include/linux/mcs_spinlock.h +5
-0+/* +* Make sure all operations within the critical section +* happen before the lock is released. +*/ +smp_wmb ();...but I don't see what prevents reads inside the critical section from moving across the
smp_wmb()here.
Quoted 3 lines
This is to prevent any read in next critical section from creeping up before write in the previous critical section has completed
Understood, but an smp_wmb() doesn't provide any ordering guarantees with respect to reads, hence why I think you need an smp_mb() here.
Quoted 15 lines
e.g.
CPU 1 executemcs_lock x = 1; ... x = 2; mcs_unlockand CPU 2 execute
mcs_lock y = x; ... mcs_unlock
Quoted 5 lines
We expect y to be 2 after the "y = x" assignment. Without the proper rmb in lock and wmb in unlock, y could be 1 for CPU 2 with speculative read (i.e. before the x=2 assignment is completed).
is it not a good example ?
I think you need reads and writes by both CPUs to show the problem:
// x, y are zero-initialised memory locations // a, b are registers
CPU 1:
mcs_lock a = x y = 1 mcs_unlock
CPU 2:
mcs_lock b = y x = 1 mcs_unlock
In this case, you would hope that you can't observe a = b = 1.
However, given the current barriers, I think you could end up with something equivalent to:
CPU 1:
y = 1 // Moved over read-barrier
mcs_lock // smp_rmb
mcs_unlock // smp_wmb
a = x // Moved over write-barrier
CPU 2:
x = 1 // Moved over read-barrier
mcs_lock // smp_rmb
mcs_unlock // smp_wmb
b = y // Moved over write-barrier
which would permit a = b = 1, as well as other orderings.
Will
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 3/4] MCS Lock: Barrier corrections
Quoted 53 lines · Will Deacon
Quoted 52 lines · Figo.zhang
2013/11/6 Tim Chen<[email protected]<mailto:[email protected]>>
Quoted 50 lines · Will Deacon
Quoted 12 lines · Tim Chen
include/linux/mcs_spinlock.h +1
-0@@ -36,16 +36,19 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) node->locked =0 ; node->next =NULL ; +/* xchg() provides a memory barrier */ prev =xchg (lock, node);if (likely (prev ==NULL )) {/* Lock acquired */ include/linux/mcs_spinlock.h void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) · line 51
Quoted 10 lines
include/linux/mcs_spinlock.h +3
-1return ; }ACCESS_ONCE (prev->next) = node; -smp_wmb ();/* Wait until the lock holder passes the lock down */ while (!ACCESS_ONCE (node->locked))arch_mutex_cpu_relax (); + +/* Make sure subsequent operations happen after the lock is acquired */ +smp_rmb ();Ok, so this is an
smp_rmb()because we assume that stores aren't speculated, right? (i.e. the control dependency above is enough for stores to be ordered with respect to taking the lock)...Quoted 12 lines
include/linux/mcs_spinlock.h +1
-0}/* @@ -58,6 +61,7 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nodif (likely (!next)) {/* +* cmpxchg() provides a memory barrier. * Release the lock by setting it to NULL */ if (likely (cmpxchg (lock, node,NULL ) == node))include/linux/mcs_spinlock.h static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod · line 77
Quoted 9 lines
include/linux/mcs_spinlock.h +6
-0@@ -65,9 +69,14 @@ static void mcs_spin_unlock(struct mcs_spinlock **lock, struct mcs_spinlock *nod/* Wait until the next pointer is set */ while (!(next =ACCESS_ONCE (node->next)))arch_mutex_cpu_relax (); + }else { +/* +* Make sure all operations within the critical section +* happen before the lock is released. +*/ +smp_wmb ();...but I don't see what prevents reads inside the critical section from moving across the
smp_wmb()here.
Quoted 5 lines
Quoted 3 lines
This is to prevent any read in next critical section from creeping up before write in the previous critical section has completed
Understood, but an
smp_wmb()doesn't provide any ordering guarantees with respect to reads, hence why I think you need ansmp_mb()here.
A major reason for the current design is to avoid overhead of a full memory barrier in x86 which doesn't need that. I do agree that the current code may not be enough for other architectures. I would like to propose that the following changes:
1) Move the lock/unlock functions to mcs_spinlock.c.
2) Define a set of primitives - smp_mb__before_critical_section(), smp_mb_after_critical_section() that will fall back to smp_mb() if they are not defined in asm/processor.h, for example.
3) Use the new primitives instead of the current smp_rmb() and smp_wmb() memory barrier.
That will allow each architecture to tailor what sort of memory barrier do they want to use.
Regards,
Longman
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH v2 4/4 MCS Lock: Make mcs_spinlock.h includable in other files
In reply to a message not in the archiveThe following changes are made to enable mcs_spinlock.h file to be widely included in other files without causing problem:
1) Include a number of prerequisite header files and define arch_mutex_cpu_relax(), if not previously defined.
2) Make mcs_spin_unlock() an inlined function and rename mcs_spin_lock() to _raw_mcs_spin_lock() which is also an inlined function.
3) Create a new mcs_spinlock.c file to contain the non-inlined mcs_spin_lock() function.
--- include/linux/mcs_spinlock.h | 27 ++++++++++++++++++++++----- kernel/Makefile | 6 +++--- kernel/mcs_spinlock.c | 21 +++++++++++++++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 kernel/mcs_spinlock.c
include/linux/mcs_spinlock.h +22 -5
@@ -12,11 +12,27 @@#ifndef __LINUX_MCS_SPINLOCK_H#define __LINUX_MCS_SPINLOCK_H +/* +* asm/processor.h may define arch_mutex_cpu_relax(). +* If it is not defined, cpu_relax() will be used. +*/ +#include <asm/barrier.h> +#include <asm/cmpxchg.h> +#include <asm/processor.h> +#include <linux/compiler.h> + +#ifndef arch_mutex_cpu_relax +# define arch_mutex_cpu_relax () cpu_relax() +#endif +struct mcs_spinlock {struct mcs_spinlock *next;int locked;/* 1 if lock acquired */ }; +extern +void mcs_spin_lock (struct mcs_spinlock **lock,struct mcs_spinlock *node); +/* * In order to acquire the lock, the caller should declare a local node and * pass a reference of the node to this function in addition to the lock.
@@ -24,11 +40,11 @@ struct mcs_spinlock {* on this node->locked until the previous lock holder sets the node->locked * in mcs_spin_unlock(). * -* We don't inline mcs_spin_lock() so that perf can correctly account for the -* time spent in this lock function. +* The _raw_mcs_spin_lock() function should not be called directly. Instead, +* users should call mcs_spin_lock(). */ -static noinline -void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) +static inline +void _raw_mcs_spin_lock (struct mcs_spinlock **lock,struct mcs_spinlock *node) {struct mcs_spinlock *prev;
@@ -55,7 +71,8 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node)* Releases the lock. The caller should pass in the corresponding node that * was used to acquire the lock. */ -static void mcs_spin_unlock (struct mcs_spinlock **lock,struct mcs_spinlock *node) +static inline +void mcs_spin_unlock (struct mcs_spinlock **lock,struct mcs_spinlock *node) {struct mcs_spinlock *next =ACCESS_ONCE (node->next);
kernel/Makefile +3 -3
@@ -50,9 +50,9 @@ obj-$(CONFIG_SMP) += smp.o ifneq ($(CONFIG_SMP),y) obj-y += up.o endif -obj-$(CONFIG_SMP) += spinlock.o -obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o -obj-$(CONFIG_PROVE_LOCKING) += spinlock.o +obj-$(CONFIG_SMP) += spinlock.o mcs_spinlock.o +obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o mcs_spinlock.o +obj-$(CONFIG_PROVE_LOCKING) += spinlock.o mcs_spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o
kernel/mcs_spinlock.c new file +21 -0
@@ -0,0 +1,21 @@ +/* +* MCS lock +* +* The MCS lock (proposed by Mellor-Crummey and Scott) is a simple spin-lock +* with the desirable properties of being fair, and with each cpu trying +* to acquire the lock spinning on a local variable. +* It avoids expensive cache bouncings that common test-and-set spin-lock +* implementations incur. +*/ +#include <linux/mcs_spinlock.h> +#include <linux/export.h> + +/* +* We don't inline mcs_spin_lock() so that perf can correctly account for the +* time spent in this lock function. +*/ +void mcs_spin_lock (struct mcs_spinlock **lock,struct mcs_spinlock *node) +{ +_raw_mcs_spin_lock (lock, node); +} +EXPORT_SYMBOL_GPL (mcs_spin_lock);
Signature · 8 lines
1.7.4.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Peter Zijlstra
maintainerRe: [PATCH v2 4/4] MCS Lock: Make mcs_spinlock.h includable in other files
include/linux/mcs_spinlock.h struct mcs_spinlock { · line 49
Quoted 10 lines · Tim Chen
+ * The
_raw_mcs_spin_lock()function should not be called directly. Instead,
+ * users should callmcs_spin_lock().
*/include/linux/mcs_spinlock.h +2
-2-static noinline -void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) +static inline +void _raw_mcs_spin_lock (struct mcs_spinlock **lock,struct mcs_spinlock *node) {struct mcs_spinlock *prev;
So why keep it in the header at all?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 4/4] MCS Lock: Make mcs_spinlock.h includable in other files
Quoted 13 lines · Peter Zijlstra
include/linux/mcs_spinlock.h struct mcs_spinlock { · line 49
Quoted 10 lines · Tim Chen
+ * The
_raw_mcs_spin_lock()function should not be called directly. Instead,
+ * users should callmcs_spin_lock().
*/include/linux/mcs_spinlock.h +2
-2-static noinline -void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) +static inline +void _raw_mcs_spin_lock (struct mcs_spinlock **lock,struct mcs_spinlock *node) {struct mcs_spinlock *prev;So why keep it in the header at all?
I also made the suggestion originally of keeping both lock and unlock in mcs_spinlock.c. Wonder if Waiman decides to keep them in header because in-lining the unlock function makes execution a bit faster?
Tim
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 4/4] MCS Lock: Make mcs_spinlock.h includable in other files
Quoted 13 lines · Tim Chen
Quoted 12 lines · Peter Zijlstra
include/linux/mcs_spinlock.h struct mcs_spinlock { · line 49
Quoted 10 lines · Tim Chen
+ * The
_raw_mcs_spin_lock()function should not be called directly. Instead,
+ * users should callmcs_spin_lock().
*/include/linux/mcs_spinlock.h +2
-2-static noinline -void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) +static inline +void _raw_mcs_spin_lock (struct mcs_spinlock **lock,struct mcs_spinlock *node) {struct mcs_spinlock *prev;So why keep it in the header at all?
Quoted 6 lines
I also made the suggestion originally of keeping both lock and unlock in
mcs_spinlock.c. Wonder if Waiman decides to keep them in header because in-lining the unlock function makes execution a bit faster?Tim
I was following the example of the spinlock code where the lock function is not inlined, but the unlock function is. I have no objection to make them both as non-inlined functions, if you think that is the right move.
Regards,
Longman
Peter Zijlstra
maintainerRe: [PATCH v2 4/4] MCS Lock: Make mcs_spinlock.h includable in other files
Quoted 18 lines · Waiman Long
Quoted 17 lines · Tim Chen
Quoted 12 lines · Peter Zijlstra
include/linux/mcs_spinlock.h struct mcs_spinlock { · line 49
Quoted 10 lines · Tim Chen
+ * The
_raw_mcs_spin_lock()function should not be called directly. Instead,
+ * users should callmcs_spin_lock().
*/include/linux/mcs_spinlock.h +2
-2-static noinline -void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node) +static inline +void _raw_mcs_spin_lock (struct mcs_spinlock **lock,struct mcs_spinlock *node) {struct mcs_spinlock *prev;So why keep it in the header at all?
I also made the suggestion originally of keeping both lock and unlock in
mcs_spinlock.c. Wonder if Waiman decides to keep them in header because in-lining the unlock function makes execution a bit faster?
Quoted 6 lines
Quoted 2 lines
Tim
I was following the example of the spinlock code where the lock function is not inlined, but the unlock function is. I have no objection to make them both as non-inlined functions, if you think that is the right move.
I don't care, what I do find odd is the existence of _raw_mcs_spin_lock(). If you want to out-of-line it, just move the entire thing into a .c file already.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>