diff options
author | Darren Hart <dvhltc@us.ibm.com> | 2009-04-08 02:23:50 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2009-04-08 06:58:20 -0400 |
commit | bab5bc9e857638880facef76e4b4c3fa807f8c73 (patch) | |
tree | 8129a3fc18f770021bfe202900ecc2cb144d18c7 | |
parent | 52400ba946759af28442dee6265c5c0180ac7122 (diff) |
futex: fixup unlocked requeue pi case
Thomas's testing caught a problem when the requeue target futex is
unowned and multiple tasks are requeued to it. This patch ensures
the FUTEX_WAITERS bit gets set if futex_requeue() will requeue one
or more tasks in addition to the one acquiring the lock.
Signed-off-by: Darren Hart <dvhltc@us.ibm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | kernel/futex.c | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index 185c981d89e3..041bf3ac4be9 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -565,12 +565,14 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, | |||
565 | 565 | ||
566 | /** | 566 | /** |
567 | * futex_lock_pi_atomic() - atomic work required to acquire a pi aware futex | 567 | * futex_lock_pi_atomic() - atomic work required to acquire a pi aware futex |
568 | * @uaddr: the pi futex user address | 568 | * @uaddr: the pi futex user address |
569 | * @hb: the pi futex hash bucket | 569 | * @hb: the pi futex hash bucket |
570 | * @key: the futex key associated with uaddr and hb | 570 | * @key: the futex key associated with uaddr and hb |
571 | * @ps: the pi_state pointer where we store the result of the lookup | 571 | * @ps: the pi_state pointer where we store the result of the |
572 | * @task: the task to perform the atomic lock work for. This will be | 572 | * lookup |
573 | * "current" except in the case of requeue pi. | 573 | * @task: the task to perform the atomic lock work for. This will |
574 | * be "current" except in the case of requeue pi. | ||
575 | * @set_waiters: force setting the FUTEX_WAITERS bit (1) or not (0) | ||
574 | * | 576 | * |
575 | * Returns: | 577 | * Returns: |
576 | * 0 - ready to wait | 578 | * 0 - ready to wait |
@@ -582,7 +584,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, | |||
582 | static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, | 584 | static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, |
583 | union futex_key *key, | 585 | union futex_key *key, |
584 | struct futex_pi_state **ps, | 586 | struct futex_pi_state **ps, |
585 | struct task_struct *task) | 587 | struct task_struct *task, int set_waiters) |
586 | { | 588 | { |
587 | int lock_taken, ret, ownerdied = 0; | 589 | int lock_taken, ret, ownerdied = 0; |
588 | u32 uval, newval, curval; | 590 | u32 uval, newval, curval; |
@@ -596,6 +598,8 @@ retry: | |||
596 | * the locks. It will most likely not succeed. | 598 | * the locks. It will most likely not succeed. |
597 | */ | 599 | */ |
598 | newval = task_pid_vnr(task); | 600 | newval = task_pid_vnr(task); |
601 | if (set_waiters) | ||
602 | newval |= FUTEX_WAITERS; | ||
599 | 603 | ||
600 | curval = cmpxchg_futex_value_locked(uaddr, 0, newval); | 604 | curval = cmpxchg_futex_value_locked(uaddr, 0, newval); |
601 | 605 | ||
@@ -1004,14 +1008,18 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key) | |||
1004 | 1008 | ||
1005 | /** | 1009 | /** |
1006 | * futex_proxy_trylock_atomic() - Attempt an atomic lock for the top waiter | 1010 | * futex_proxy_trylock_atomic() - Attempt an atomic lock for the top waiter |
1007 | * @pifutex: the user address of the to futex | 1011 | * @pifutex: the user address of the to futex |
1008 | * @hb1: the from futex hash bucket, must be locked by the caller | 1012 | * @hb1: the from futex hash bucket, must be locked by the caller |
1009 | * @hb2: the to futex hash bucket, must be locked by the caller | 1013 | * @hb2: the to futex hash bucket, must be locked by the caller |
1010 | * @key1: the from futex key | 1014 | * @key1: the from futex key |
1011 | * @key2: the to futex key | 1015 | * @key2: the to futex key |
1016 | * @ps: address to store the pi_state pointer | ||
1017 | * @set_waiters: force setting the FUTEX_WAITERS bit (1) or not (0) | ||
1012 | * | 1018 | * |
1013 | * Try and get the lock on behalf of the top waiter if we can do it atomically. | 1019 | * Try and get the lock on behalf of the top waiter if we can do it atomically. |
1014 | * Wake the top waiter if we succeed. hb1 and hb2 must be held by the caller. | 1020 | * Wake the top waiter if we succeed. If the caller specified set_waiters, |
1021 | * then direct futex_lock_pi_atomic() to force setting the FUTEX_WAITERS bit. | ||
1022 | * hb1 and hb2 must be held by the caller. | ||
1015 | * | 1023 | * |
1016 | * Returns: | 1024 | * Returns: |
1017 | * 0 - failed to acquire the lock atomicly | 1025 | * 0 - failed to acquire the lock atomicly |
@@ -1022,15 +1030,23 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex, | |||
1022 | struct futex_hash_bucket *hb1, | 1030 | struct futex_hash_bucket *hb1, |
1023 | struct futex_hash_bucket *hb2, | 1031 | struct futex_hash_bucket *hb2, |
1024 | union futex_key *key1, union futex_key *key2, | 1032 | union futex_key *key1, union futex_key *key2, |
1025 | struct futex_pi_state **ps) | 1033 | struct futex_pi_state **ps, int set_waiters) |
1026 | { | 1034 | { |
1027 | struct futex_q *top_waiter; | 1035 | struct futex_q *top_waiter = NULL; |
1028 | u32 curval; | 1036 | u32 curval; |
1029 | int ret; | 1037 | int ret; |
1030 | 1038 | ||
1031 | if (get_futex_value_locked(&curval, pifutex)) | 1039 | if (get_futex_value_locked(&curval, pifutex)) |
1032 | return -EFAULT; | 1040 | return -EFAULT; |
1033 | 1041 | ||
1042 | /* | ||
1043 | * Find the top_waiter and determine if there are additional waiters. | ||
1044 | * If the caller intends to requeue more than 1 waiter to pifutex, | ||
1045 | * force futex_lock_pi_atomic() to set the FUTEX_WAITERS bit now, | ||
1046 | * as we have means to handle the possible fault. If not, don't set | ||
1047 | * the bit unecessarily as it will force the subsequent unlock to enter | ||
1048 | * the kernel. | ||
1049 | */ | ||
1034 | top_waiter = futex_top_waiter(hb1, key1); | 1050 | top_waiter = futex_top_waiter(hb1, key1); |
1035 | 1051 | ||
1036 | /* There are no waiters, nothing for us to do. */ | 1052 | /* There are no waiters, nothing for us to do. */ |
@@ -1038,10 +1054,12 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex, | |||
1038 | return 0; | 1054 | return 0; |
1039 | 1055 | ||
1040 | /* | 1056 | /* |
1041 | * Either take the lock for top_waiter or set the FUTEX_WAITERS bit. | 1057 | * Try to take the lock for top_waiter. Set the FUTEX_WAITERS bit in |
1042 | * The pi_state is returned in ps in contended cases. | 1058 | * the contended case or if set_waiters is 1. The pi_state is returned |
1059 | * in ps in contended cases. | ||
1043 | */ | 1060 | */ |
1044 | ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task); | 1061 | ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task, |
1062 | set_waiters); | ||
1045 | if (ret == 1) | 1063 | if (ret == 1) |
1046 | requeue_pi_wake_futex(top_waiter, key2); | 1064 | requeue_pi_wake_futex(top_waiter, key2); |
1047 | 1065 | ||
@@ -1146,9 +1164,14 @@ retry_private: | |||
1146 | } | 1164 | } |
1147 | 1165 | ||
1148 | if (requeue_pi && (task_count - nr_wake < nr_requeue)) { | 1166 | if (requeue_pi && (task_count - nr_wake < nr_requeue)) { |
1149 | /* Attempt to acquire uaddr2 and wake the top_waiter. */ | 1167 | /* |
1168 | * Attempt to acquire uaddr2 and wake the top waiter. If we | ||
1169 | * intend to requeue waiters, force setting the FUTEX_WAITERS | ||
1170 | * bit. We force this here where we are able to easily handle | ||
1171 | * faults rather in the requeue loop below. | ||
1172 | */ | ||
1150 | ret = futex_proxy_trylock_atomic(uaddr2, hb1, hb2, &key1, | 1173 | ret = futex_proxy_trylock_atomic(uaddr2, hb1, hb2, &key1, |
1151 | &key2, &pi_state); | 1174 | &key2, &pi_state, nr_requeue); |
1152 | 1175 | ||
1153 | /* | 1176 | /* |
1154 | * At this point the top_waiter has either taken uaddr2 or is | 1177 | * At this point the top_waiter has either taken uaddr2 or is |
@@ -1810,7 +1833,7 @@ retry: | |||
1810 | retry_private: | 1833 | retry_private: |
1811 | hb = queue_lock(&q); | 1834 | hb = queue_lock(&q); |
1812 | 1835 | ||
1813 | ret = futex_lock_pi_atomic(uaddr, hb, &q.key, &q.pi_state, current); | 1836 | ret = futex_lock_pi_atomic(uaddr, hb, &q.key, &q.pi_state, current, 0); |
1814 | if (unlikely(ret)) { | 1837 | if (unlikely(ret)) { |
1815 | switch (ret) { | 1838 | switch (ret) { |
1816 | case 1: | 1839 | case 1: |