Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 99b60ce6 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Ingo Molnar
Browse files

futexes: Document multiprocessor ordering guarantees



That's essential, if you want to hack on futexes.

Reviewed-by: default avatarDarren Hart <dvhart@linux.intel.com>
Reviewed-by: default avatarPeter Zijlstra <peterz@infradead.org>
Reviewed-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarDavidlohr 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: default avatarIngo Molnar <mingo@kernel.org>
parent a52b89eb
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -69,6 +69,63 @@

#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;

/*