|
@@ -1781,13 +1781,14 @@ static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
|
|
*
|
|
*
|
|
* The basic logical guarantee of a futex is that it blocks ONLY
|
|
* The basic logical guarantee of a futex is that it blocks ONLY
|
|
* if cond(var) is known to be true at the time of blocking, for
|
|
* if cond(var) is known to be true at the time of blocking, for
|
|
- * any cond. If we queued after testing *uaddr, that would open
|
|
|
|
- * a race condition where we could block indefinitely with
|
|
|
|
|
|
+ * any cond. If we locked the hash-bucket after testing *uaddr, that
|
|
|
|
+ * would open a race condition where we could block indefinitely with
|
|
* cond(var) false, which would violate the guarantee.
|
|
* cond(var) false, which would violate the guarantee.
|
|
*
|
|
*
|
|
- * A consequence is that futex_wait() can return zero and absorb
|
|
|
|
- * a wakeup when *uaddr != val on entry to the syscall. This is
|
|
|
|
- * rare, but normal.
|
|
|
|
|
|
+ * On the other hand, we insert q and release the hash-bucket only
|
|
|
|
+ * after testing *uaddr. This guarantees that futex_wait() will NOT
|
|
|
|
+ * absorb a wakeup if *uaddr does not match the desired values
|
|
|
|
+ * while the syscall executes.
|
|
*/
|
|
*/
|
|
retry:
|
|
retry:
|
|
ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key);
|
|
ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key);
|