aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/futex.c
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2010-12-22 01:18:50 -0500
committerSteven Rostedt <rostedt@goodmis.org>2011-03-11 15:09:52 -0500
commit2e12978a9f7a7abd54e8eb9ce70a7718767b8b2c (patch)
treeeb4f298e084b5bcc4922511237cd6ce2e158abdd /kernel/futex.c
parenta5abba989deceb731047425812d268daf7536575 (diff)
futex,plist: Pass the real head of the priority list to plist_del()
Some plist_del()s in kernel/futex.c are passed a faked head of the priority list. It does not fail because the current code does not require the real head in plist_del(). The current code of plist_del() just uses the head for checking, so it will not cause a bad result even when we use a faked head. But it is undocumented usage: /** * plist_del - Remove a @node from plist. * * @node: &struct plist_node pointer - entry to be removed * @head: &struct plist_head pointer - list head */ The document says that the @head is the "list head" head of the priority list. In futex code, several places use "plist_del(&q->list, &q->list.plist);", they pass a fake head. We need to fix them all. Thanks to Darren Hart for many suggestions. Acked-by: Darren Hart <dvhart@linux.intel.com> Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com> LKML-Reference: <4D11984A.5030203@cn.fujitsu.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/futex.c')
-rw-r--r--kernel/futex.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index b766d28accd6..6feeea4f8f15 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -775,6 +775,24 @@ retry:
775 return ret; 775 return ret;
776} 776}
777 777
778/**
779 * __unqueue_futex() - Remove the futex_q from its futex_hash_bucket
780 * @q: The futex_q to unqueue
781 *
782 * The q->lock_ptr must not be NULL and must be held by the caller.
783 */
784static void __unqueue_futex(struct futex_q *q)
785{
786 struct futex_hash_bucket *hb;
787
788 if (WARN_ON(!q->lock_ptr || !spin_is_locked(q->lock_ptr)
789 || plist_node_empty(&q->list)))
790 return;
791
792 hb = container_of(q->lock_ptr, struct futex_hash_bucket, lock);
793 plist_del(&q->list, &hb->chain);
794}
795
778/* 796/*
779 * The hash bucket lock must be held when this is called. 797 * The hash bucket lock must be held when this is called.
780 * Afterwards, the futex_q must not be accessed. 798 * Afterwards, the futex_q must not be accessed.
@@ -792,7 +810,7 @@ static void wake_futex(struct futex_q *q)
792 */ 810 */
793 get_task_struct(p); 811 get_task_struct(p);
794 812
795 plist_del(&q->list, &q->list.plist); 813 __unqueue_futex(q);
796 /* 814 /*
797 * The waiting task can free the futex_q as soon as 815 * The waiting task can free the futex_q as soon as
798 * q->lock_ptr = NULL is written, without taking any locks. A 816 * q->lock_ptr = NULL is written, without taking any locks. A
@@ -1100,8 +1118,7 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
1100 get_futex_key_refs(key); 1118 get_futex_key_refs(key);
1101 q->key = *key; 1119 q->key = *key;
1102 1120
1103 WARN_ON(plist_node_empty(&q->list)); 1121 __unqueue_futex(q);
1104 plist_del(&q->list, &q->list.plist);
1105 1122
1106 WARN_ON(!q->rt_waiter); 1123 WARN_ON(!q->rt_waiter);
1107 q->rt_waiter = NULL; 1124 q->rt_waiter = NULL;
@@ -1504,8 +1521,7 @@ retry:
1504 spin_unlock(lock_ptr); 1521 spin_unlock(lock_ptr);
1505 goto retry; 1522 goto retry;
1506 } 1523 }
1507 WARN_ON(plist_node_empty(&q->list)); 1524 __unqueue_futex(q);
1508 plist_del(&q->list, &q->list.plist);
1509 1525
1510 BUG_ON(q->pi_state); 1526 BUG_ON(q->pi_state);
1511 1527
@@ -1525,8 +1541,7 @@ retry:
1525static void unqueue_me_pi(struct futex_q *q) 1541static void unqueue_me_pi(struct futex_q *q)
1526 __releases(q->lock_ptr) 1542 __releases(q->lock_ptr)
1527{ 1543{
1528 WARN_ON(plist_node_empty(&q->list)); 1544 __unqueue_futex(q);
1529 plist_del(&q->list, &q->list.plist);
1530 1545
1531 BUG_ON(!q->pi_state); 1546 BUG_ON(!q->pi_state);
1532 free_pi_state(q->pi_state); 1547 free_pi_state(q->pi_state);
@@ -2167,7 +2182,7 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
2167 * We were woken prior to requeue by a timeout or a signal. 2182 * We were woken prior to requeue by a timeout or a signal.
2168 * Unqueue the futex_q and determine which it was. 2183 * Unqueue the futex_q and determine which it was.
2169 */ 2184 */
2170 plist_del(&q->list, &q->list.plist); 2185 plist_del(&q->list, &hb->chain);
2171 2186
2172 /* Handle spurious wakeups gracefully */ 2187 /* Handle spurious wakeups gracefully */
2173 ret = -EWOULDBLOCK; 2188 ret = -EWOULDBLOCK;