diff options
Diffstat (limited to 'kernel/mutex.c')
-rw-r--r-- | kernel/mutex.c | 151 |
1 files changed, 147 insertions, 4 deletions
diff --git a/kernel/mutex.c b/kernel/mutex.c index 52f23011b6e0..ad53a664f113 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c | |||
@@ -37,6 +37,12 @@ | |||
37 | # include <asm/mutex.h> | 37 | # include <asm/mutex.h> |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | /* | ||
41 | * A negative mutex count indicates that waiters are sleeping waiting for the | ||
42 | * mutex. | ||
43 | */ | ||
44 | #define MUTEX_SHOW_NO_WAITER(mutex) (atomic_read(&(mutex)->count) >= 0) | ||
45 | |||
40 | void | 46 | void |
41 | __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key) | 47 | __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key) |
42 | { | 48 | { |
@@ -44,6 +50,9 @@ __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key) | |||
44 | spin_lock_init(&lock->wait_lock); | 50 | spin_lock_init(&lock->wait_lock); |
45 | INIT_LIST_HEAD(&lock->wait_list); | 51 | INIT_LIST_HEAD(&lock->wait_list); |
46 | mutex_clear_owner(lock); | 52 | mutex_clear_owner(lock); |
53 | #ifdef CONFIG_MUTEX_SPIN_ON_OWNER | ||
54 | lock->spin_mlock = NULL; | ||
55 | #endif | ||
47 | 56 | ||
48 | debug_mutex_init(lock, name, key); | 57 | debug_mutex_init(lock, name, key); |
49 | } | 58 | } |
@@ -95,6 +104,124 @@ void __sched mutex_lock(struct mutex *lock) | |||
95 | EXPORT_SYMBOL(mutex_lock); | 104 | EXPORT_SYMBOL(mutex_lock); |
96 | #endif | 105 | #endif |
97 | 106 | ||
107 | #ifdef CONFIG_MUTEX_SPIN_ON_OWNER | ||
108 | /* | ||
109 | * In order to avoid a stampede of mutex spinners from acquiring the mutex | ||
110 | * more or less simultaneously, the spinners need to acquire a MCS lock | ||
111 | * first before spinning on the owner field. | ||
112 | * | ||
113 | * We don't inline mspin_lock() so that perf can correctly account for the | ||
114 | * time spent in this lock function. | ||
115 | */ | ||
116 | struct mspin_node { | ||
117 | struct mspin_node *next ; | ||
118 | int locked; /* 1 if lock acquired */ | ||
119 | }; | ||
120 | #define MLOCK(mutex) ((struct mspin_node **)&((mutex)->spin_mlock)) | ||
121 | |||
122 | static noinline | ||
123 | void mspin_lock(struct mspin_node **lock, struct mspin_node *node) | ||
124 | { | ||
125 | struct mspin_node *prev; | ||
126 | |||
127 | /* Init node */ | ||
128 | node->locked = 0; | ||
129 | node->next = NULL; | ||
130 | |||
131 | prev = xchg(lock, node); | ||
132 | if (likely(prev == NULL)) { | ||
133 | /* Lock acquired */ | ||
134 | node->locked = 1; | ||
135 | return; | ||
136 | } | ||
137 | ACCESS_ONCE(prev->next) = node; | ||
138 | smp_wmb(); | ||
139 | /* Wait until the lock holder passes the lock down */ | ||
140 | while (!ACCESS_ONCE(node->locked)) | ||
141 | arch_mutex_cpu_relax(); | ||
142 | } | ||
143 | |||
144 | static void mspin_unlock(struct mspin_node **lock, struct mspin_node *node) | ||
145 | { | ||
146 | struct mspin_node *next = ACCESS_ONCE(node->next); | ||
147 | |||
148 | if (likely(!next)) { | ||
149 | /* | ||
150 | * Release the lock by setting it to NULL | ||
151 | */ | ||
152 | if (cmpxchg(lock, node, NULL) == node) | ||
153 | return; | ||
154 | /* Wait until the next pointer is set */ | ||
155 | while (!(next = ACCESS_ONCE(node->next))) | ||
156 | arch_mutex_cpu_relax(); | ||
157 | } | ||
158 | ACCESS_ONCE(next->locked) = 1; | ||
159 | smp_wmb(); | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Mutex spinning code migrated from kernel/sched/core.c | ||
164 | */ | ||
165 | |||
166 | static inline bool owner_running(struct mutex *lock, struct task_struct *owner) | ||
167 | { | ||
168 | if (lock->owner != owner) | ||
169 | return false; | ||
170 | |||
171 | /* | ||
172 | * Ensure we emit the owner->on_cpu, dereference _after_ checking | ||
173 | * lock->owner still matches owner, if that fails, owner might | ||
174 | * point to free()d memory, if it still matches, the rcu_read_lock() | ||
175 | * ensures the memory stays valid. | ||
176 | */ | ||
177 | barrier(); | ||
178 | |||
179 | return owner->on_cpu; | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * Look out! "owner" is an entirely speculative pointer | ||
184 | * access and not reliable. | ||
185 | */ | ||
186 | static noinline | ||
187 | int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner) | ||
188 | { | ||
189 | rcu_read_lock(); | ||
190 | while (owner_running(lock, owner)) { | ||
191 | if (need_resched()) | ||
192 | break; | ||
193 | |||
194 | arch_mutex_cpu_relax(); | ||
195 | } | ||
196 | rcu_read_unlock(); | ||
197 | |||
198 | /* | ||
199 | * We break out the loop above on need_resched() and when the | ||
200 | * owner changed, which is a sign for heavy contention. Return | ||
201 | * success only when lock->owner is NULL. | ||
202 | */ | ||
203 | return lock->owner == NULL; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * Initial check for entering the mutex spinning loop | ||
208 | */ | ||
209 | static inline int mutex_can_spin_on_owner(struct mutex *lock) | ||
210 | { | ||
211 | int retval = 1; | ||
212 | |||
213 | rcu_read_lock(); | ||
214 | if (lock->owner) | ||
215 | retval = lock->owner->on_cpu; | ||
216 | rcu_read_unlock(); | ||
217 | /* | ||
218 | * if lock->owner is not set, the mutex owner may have just acquired | ||
219 | * it and not set the owner yet or the mutex has been released. | ||
220 | */ | ||
221 | return retval; | ||
222 | } | ||
223 | #endif | ||
224 | |||
98 | static __used noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count); | 225 | static __used noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count); |
99 | 226 | ||
100 | /** | 227 | /** |
@@ -158,25 +285,39 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, | |||
158 | * | 285 | * |
159 | * We can't do this for DEBUG_MUTEXES because that relies on wait_lock | 286 | * We can't do this for DEBUG_MUTEXES because that relies on wait_lock |
160 | * to serialize everything. | 287 | * to serialize everything. |
288 | * | ||
289 | * The mutex spinners are queued up using MCS lock so that only one | ||
290 | * spinner can compete for the mutex. However, if mutex spinning isn't | ||
291 | * going to happen, there is no point in going through the lock/unlock | ||
292 | * overhead. | ||
161 | */ | 293 | */ |
294 | if (!mutex_can_spin_on_owner(lock)) | ||
295 | goto slowpath; | ||
162 | 296 | ||
163 | for (;;) { | 297 | for (;;) { |
164 | struct task_struct *owner; | 298 | struct task_struct *owner; |
299 | struct mspin_node node; | ||
165 | 300 | ||
166 | /* | 301 | /* |
167 | * If there's an owner, wait for it to either | 302 | * If there's an owner, wait for it to either |
168 | * release the lock or go to sleep. | 303 | * release the lock or go to sleep. |
169 | */ | 304 | */ |
305 | mspin_lock(MLOCK(lock), &node); | ||
170 | owner = ACCESS_ONCE(lock->owner); | 306 | owner = ACCESS_ONCE(lock->owner); |
171 | if (owner && !mutex_spin_on_owner(lock, owner)) | 307 | if (owner && !mutex_spin_on_owner(lock, owner)) { |
308 | mspin_unlock(MLOCK(lock), &node); | ||
172 | break; | 309 | break; |
310 | } | ||
173 | 311 | ||
174 | if (atomic_cmpxchg(&lock->count, 1, 0) == 1) { | 312 | if ((atomic_read(&lock->count) == 1) && |
313 | (atomic_cmpxchg(&lock->count, 1, 0) == 1)) { | ||
175 | lock_acquired(&lock->dep_map, ip); | 314 | lock_acquired(&lock->dep_map, ip); |
176 | mutex_set_owner(lock); | 315 | mutex_set_owner(lock); |
316 | mspin_unlock(MLOCK(lock), &node); | ||
177 | preempt_enable(); | 317 | preempt_enable(); |
178 | return 0; | 318 | return 0; |
179 | } | 319 | } |
320 | mspin_unlock(MLOCK(lock), &node); | ||
180 | 321 | ||
181 | /* | 322 | /* |
182 | * When there's no owner, we might have preempted between the | 323 | * When there's no owner, we might have preempted between the |
@@ -195,6 +336,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, | |||
195 | */ | 336 | */ |
196 | arch_mutex_cpu_relax(); | 337 | arch_mutex_cpu_relax(); |
197 | } | 338 | } |
339 | slowpath: | ||
198 | #endif | 340 | #endif |
199 | spin_lock_mutex(&lock->wait_lock, flags); | 341 | spin_lock_mutex(&lock->wait_lock, flags); |
200 | 342 | ||
@@ -205,7 +347,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, | |||
205 | list_add_tail(&waiter.list, &lock->wait_list); | 347 | list_add_tail(&waiter.list, &lock->wait_list); |
206 | waiter.task = task; | 348 | waiter.task = task; |
207 | 349 | ||
208 | if (atomic_xchg(&lock->count, -1) == 1) | 350 | if (MUTEX_SHOW_NO_WAITER(lock) && (atomic_xchg(&lock->count, -1) == 1)) |
209 | goto done; | 351 | goto done; |
210 | 352 | ||
211 | lock_contended(&lock->dep_map, ip); | 353 | lock_contended(&lock->dep_map, ip); |
@@ -220,7 +362,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, | |||
220 | * that when we release the lock, we properly wake up the | 362 | * that when we release the lock, we properly wake up the |
221 | * other waiters: | 363 | * other waiters: |
222 | */ | 364 | */ |
223 | if (atomic_xchg(&lock->count, -1) == 1) | 365 | if (MUTEX_SHOW_NO_WAITER(lock) && |
366 | (atomic_xchg(&lock->count, -1) == 1)) | ||
224 | break; | 367 | break; |
225 | 368 | ||
226 | /* | 369 | /* |