futexes: Document multiprocessor ordering guarantees
That's essential, if you want to hack on futexes. Reviewed-by: Darren Hart <dvhart@linux.intel.com> Reviewed-by: Peter Zijlstra <peterz@infradead.org> Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Jeff Mahoney <jeffm@suse.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Scott Norton <scott.norton@hp.com> Cc: Tom Vaden <tom.vaden@hp.com> Cc: Aswin Chandramouleeswaran <aswin@hp.com> Cc: Waiman Long <Waiman.Long@hp.com> Cc: Jason Low <jason.low2@hp.com> Cc: Andrew Morton <akpm@linux-foundation.org> Link: http://lkml.kernel.org/r/1389569486-25487-4-git-send-email-davidlohr@hp.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
a52b89ebb6
commit
99b60ce697
@ -69,6 +69,63 @@
|
|||||||
|
|
||||||
#include "locking/rtmutex_common.h"
|
#include "locking/rtmutex_common.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Basic futex operation and ordering guarantees:
|
||||||
|
*
|
||||||
|
* The waiter reads the futex value in user space and calls
|
||||||
|
* futex_wait(). This function computes the hash bucket and acquires
|
||||||
|
* the hash bucket lock. After that it reads the futex user space value
|
||||||
|
* again and verifies that the data has not changed. If it has not
|
||||||
|
* changed it enqueues itself into the hash bucket, releases the hash
|
||||||
|
* bucket lock and schedules.
|
||||||
|
*
|
||||||
|
* The waker side modifies the user space value of the futex and calls
|
||||||
|
* futex_wake(). This functions computes the hash bucket and acquires
|
||||||
|
* the hash bucket lock. Then it looks for waiters on that futex in the
|
||||||
|
* hash bucket and wakes them.
|
||||||
|
*
|
||||||
|
* Note that the spin_lock serializes waiters and wakers, so that the
|
||||||
|
* following scenario is avoided:
|
||||||
|
*
|
||||||
|
* CPU 0 CPU 1
|
||||||
|
* val = *futex;
|
||||||
|
* sys_futex(WAIT, futex, val);
|
||||||
|
* futex_wait(futex, val);
|
||||||
|
* uval = *futex;
|
||||||
|
* *futex = newval;
|
||||||
|
* sys_futex(WAKE, futex);
|
||||||
|
* futex_wake(futex);
|
||||||
|
* if (queue_empty())
|
||||||
|
* return;
|
||||||
|
* if (uval == val)
|
||||||
|
* lock(hash_bucket(futex));
|
||||||
|
* queue();
|
||||||
|
* unlock(hash_bucket(futex));
|
||||||
|
* schedule();
|
||||||
|
*
|
||||||
|
* This would cause the waiter on CPU 0 to wait forever because it
|
||||||
|
* missed the transition of the user space value from val to newval
|
||||||
|
* and the waker did not find the waiter in the hash bucket queue.
|
||||||
|
* The spinlock serializes that:
|
||||||
|
*
|
||||||
|
* CPU 0 CPU 1
|
||||||
|
* val = *futex;
|
||||||
|
* sys_futex(WAIT, futex, val);
|
||||||
|
* futex_wait(futex, val);
|
||||||
|
* lock(hash_bucket(futex));
|
||||||
|
* uval = *futex;
|
||||||
|
* *futex = newval;
|
||||||
|
* sys_futex(WAKE, futex);
|
||||||
|
* futex_wake(futex);
|
||||||
|
* lock(hash_bucket(futex));
|
||||||
|
* if (uval == val)
|
||||||
|
* queue();
|
||||||
|
* unlock(hash_bucket(futex));
|
||||||
|
* schedule(); if (!queue_empty())
|
||||||
|
* wake_waiters(futex);
|
||||||
|
* unlock(hash_bucket(futex));
|
||||||
|
*/
|
||||||
|
|
||||||
int __read_mostly futex_cmpxchg_enabled;
|
int __read_mostly futex_cmpxchg_enabled;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user