]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.4/futex-rt_mutex-restructure-rt_mutex_finish_proxy_lock.patch
drop perf-trace-support-multiple-vfs_getname-probes.patch from 4.4 and 4.9 queues
[thirdparty/kernel/stable-queue.git] / queue-4.4 / futex-rt_mutex-restructure-rt_mutex_finish_proxy_lock.patch
1 From 38d589f2fd08f1296aea3ce62bebd185125c6d81 Mon Sep 17 00:00:00 2001
2 From: Peter Zijlstra <peterz@infradead.org>
3 Date: Wed, 22 Mar 2017 11:35:57 +0100
4 Subject: futex,rt_mutex: Restructure rt_mutex_finish_proxy_lock()
5
6 From: Peter Zijlstra <peterz@infradead.org>
7
8 commit 38d589f2fd08f1296aea3ce62bebd185125c6d81 upstream.
9
10 With the ultimate goal of keeping rt_mutex wait_list and futex_q waiters
11 consistent it's necessary to split 'rt_mutex_futex_lock()' into finer
12 parts, such that only the actual blocking can be done without hb->lock
13 held.
14
15 Split split_mutex_finish_proxy_lock() into two parts, one that does the
16 blocking and one that does remove_waiter() when the lock acquire failed.
17
18 When the rtmutex was acquired successfully the waiter can be removed in the
19 acquisiton path safely, since there is no concurrency on the lock owner.
20
21 This means that, except for futex_lock_pi(), all wait_list modifications
22 are done with both hb->lock and wait_lock held.
23
24 [bigeasy@linutronix.de: fix for futex_requeue_pi_signal_restart]
25
26 Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
27 Cc: juri.lelli@arm.com
28 Cc: bigeasy@linutronix.de
29 Cc: xlpang@redhat.com
30 Cc: rostedt@goodmis.org
31 Cc: mathieu.desnoyers@efficios.com
32 Cc: jdesfossez@efficios.com
33 Cc: dvhart@infradead.org
34 Cc: bristot@redhat.com
35 Link: http://lkml.kernel.org/r/20170322104152.001659630@infradead.org
36 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
37 Signed-off-by: Zubin Mithra <zsm@chromium.org>
38 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
39
40 ---
41 kernel/futex.c | 7 +++--
42 kernel/locking/rtmutex.c | 52 ++++++++++++++++++++++++++++++++++------
43 kernel/locking/rtmutex_common.h | 8 +++---
44 3 files changed, 55 insertions(+), 12 deletions(-)
45
46 --- a/kernel/futex.c
47 +++ b/kernel/futex.c
48 @@ -2923,10 +2923,13 @@ static int futex_wait_requeue_pi(u32 __u
49 */
50 WARN_ON(!q.pi_state);
51 pi_mutex = &q.pi_state->pi_mutex;
52 - ret = rt_mutex_finish_proxy_lock(pi_mutex, to, &rt_waiter);
53 - debug_rt_mutex_free_waiter(&rt_waiter);
54 + ret = rt_mutex_wait_proxy_lock(pi_mutex, to, &rt_waiter);
55
56 spin_lock(q.lock_ptr);
57 + if (ret && !rt_mutex_cleanup_proxy_lock(pi_mutex, &rt_waiter))
58 + ret = 0;
59 +
60 + debug_rt_mutex_free_waiter(&rt_waiter);
61 /*
62 * Fixup the pi_state owner and possibly acquire the lock if we
63 * haven't already.
64 --- a/kernel/locking/rtmutex.c
65 +++ b/kernel/locking/rtmutex.c
66 @@ -1712,21 +1712,23 @@ struct task_struct *rt_mutex_next_owner(
67 }
68
69 /**
70 - * rt_mutex_finish_proxy_lock() - Complete lock acquisition
71 + * rt_mutex_wait_proxy_lock() - Wait for lock acquisition
72 * @lock: the rt_mutex we were woken on
73 * @to: the timeout, null if none. hrtimer should already have
74 * been started.
75 * @waiter: the pre-initialized rt_mutex_waiter
76 *
77 - * Complete the lock acquisition started our behalf by another thread.
78 + * Wait for the the lock acquisition started on our behalf by
79 + * rt_mutex_start_proxy_lock(). Upon failure, the caller must call
80 + * rt_mutex_cleanup_proxy_lock().
81 *
82 * Returns:
83 * 0 - success
84 * <0 - error, one of -EINTR, -ETIMEDOUT
85 *
86 - * Special API call for PI-futex requeue support
87 + * Special API call for PI-futex support
88 */
89 -int rt_mutex_finish_proxy_lock(struct rt_mutex *lock,
90 +int rt_mutex_wait_proxy_lock(struct rt_mutex *lock,
91 struct hrtimer_sleeper *to,
92 struct rt_mutex_waiter *waiter)
93 {
94 @@ -1739,9 +1741,6 @@ int rt_mutex_finish_proxy_lock(struct rt
95 /* sleep on the mutex */
96 ret = __rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE, to, waiter);
97
98 - if (unlikely(ret))
99 - remove_waiter(lock, waiter);
100 -
101 /*
102 * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might
103 * have to fix that up.
104 @@ -1752,3 +1751,42 @@ int rt_mutex_finish_proxy_lock(struct rt
105
106 return ret;
107 }
108 +
109 +/**
110 + * rt_mutex_cleanup_proxy_lock() - Cleanup failed lock acquisition
111 + * @lock: the rt_mutex we were woken on
112 + * @waiter: the pre-initialized rt_mutex_waiter
113 + *
114 + * Attempt to clean up after a failed rt_mutex_wait_proxy_lock().
115 + *
116 + * Unless we acquired the lock; we're still enqueued on the wait-list and can
117 + * in fact still be granted ownership until we're removed. Therefore we can
118 + * find we are in fact the owner and must disregard the
119 + * rt_mutex_wait_proxy_lock() failure.
120 + *
121 + * Returns:
122 + * true - did the cleanup, we done.
123 + * false - we acquired the lock after rt_mutex_wait_proxy_lock() returned,
124 + * caller should disregards its return value.
125 + *
126 + * Special API call for PI-futex support
127 + */
128 +bool rt_mutex_cleanup_proxy_lock(struct rt_mutex *lock,
129 + struct rt_mutex_waiter *waiter)
130 +{
131 + bool cleanup = false;
132 +
133 + raw_spin_lock_irq(&lock->wait_lock);
134 + /*
135 + * Unless we're the owner; we're still enqueued on the wait_list.
136 + * So check if we became owner, if not, take us off the wait_list.
137 + */
138 + if (rt_mutex_owner(lock) != current) {
139 + remove_waiter(lock, waiter);
140 + fixup_rt_mutex_waiters(lock);
141 + cleanup = true;
142 + }
143 + raw_spin_unlock_irq(&lock->wait_lock);
144 +
145 + return cleanup;
146 +}
147 --- a/kernel/locking/rtmutex_common.h
148 +++ b/kernel/locking/rtmutex_common.h
149 @@ -106,9 +106,11 @@ extern void rt_mutex_proxy_unlock(struct
150 extern int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
151 struct rt_mutex_waiter *waiter,
152 struct task_struct *task);
153 -extern int rt_mutex_finish_proxy_lock(struct rt_mutex *lock,
154 - struct hrtimer_sleeper *to,
155 - struct rt_mutex_waiter *waiter);
156 +extern int rt_mutex_wait_proxy_lock(struct rt_mutex *lock,
157 + struct hrtimer_sleeper *to,
158 + struct rt_mutex_waiter *waiter);
159 +extern bool rt_mutex_cleanup_proxy_lock(struct rt_mutex *lock,
160 + struct rt_mutex_waiter *waiter);
161 extern int rt_mutex_timed_futex_lock(struct rt_mutex *l, struct hrtimer_sleeper *to);
162 extern bool rt_mutex_futex_unlock(struct rt_mutex *lock,
163 struct wake_q_head *wqh);