1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/mutex.h>
21#include <linux/sched.h>
22#include <linux/module.h>
23#include <linux/spinlock.h>
24#include <linux/interrupt.h>
25#include <linux/debug_locks.h>
26
27
28
29
30
31#ifdef CONFIG_DEBUG_MUTEXES
32# include "mutex-debug.h"
33# include <asm-generic/mutex-null.h>
34#else
35# include "mutex.h"
36# include <asm/mutex.h>
37#endif
38
39
40
41
42
43
44
45
46
47
48void
49__mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
50{
51 atomic_set(&lock->count, 1);
52 spin_lock_init(&lock->wait_lock);
53 INIT_LIST_HEAD(&lock->wait_list);
54 mutex_clear_owner(lock);
55
56 debug_mutex_init(lock, name, key);
57}
58
59EXPORT_SYMBOL(__mutex_init);
60
61#ifndef CONFIG_DEBUG_LOCK_ALLOC
62
63
64
65
66
67
68static __used noinline void __sched
69__mutex_lock_slowpath(atomic_t *lock_count);
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92void __sched mutex_lock(struct mutex *lock)
93{
94 might_sleep();
95
96
97
98
99 __mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
100 mutex_set_owner(lock);
101}
102
103EXPORT_SYMBOL(mutex_lock);
104#endif
105
106static __used noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
107
108
109
110
111
112
113
114
115
116
117
118
119void __sched mutex_unlock(struct mutex *lock)
120{
121
122
123
124
125#ifndef CONFIG_DEBUG_MUTEXES
126
127
128
129
130
131 mutex_clear_owner(lock);
132#endif
133 __mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
134}
135
136EXPORT_SYMBOL(mutex_unlock);
137
138
139
140
141static inline int __sched
142__mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
143 unsigned long ip)
144{
145 struct task_struct *task = current;
146 struct mutex_waiter waiter;
147 unsigned long flags;
148
149 preempt_disable();
150 mutex_acquire(&lock->dep_map, subclass, 0, ip);
151
152#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 for (;;) {
172 struct thread_info *owner;
173
174
175
176
177
178 if (unlikely(current->lock_depth >= 0))
179 break;
180
181
182
183
184
185 owner = ACCESS_ONCE(lock->owner);
186 if (owner && !mutex_spin_on_owner(lock, owner))
187 break;
188
189 if (atomic_cmpxchg(&lock->count, 1, 0) == 1) {
190 lock_acquired(&lock->dep_map, ip);
191 mutex_set_owner(lock);
192 preempt_enable();
193 return 0;
194 }
195
196
197
198
199
200
201
202 if (!owner && (need_resched() || rt_task(task)))
203 break;
204
205
206
207
208
209
210
211 cpu_relax();
212 }
213#endif
214 spin_lock_mutex(&lock->wait_lock, flags);
215
216 debug_mutex_lock_common(lock, &waiter);
217 debug_mutex_add_waiter(lock, &waiter, task_thread_info(task));
218
219
220 list_add_tail(&waiter.list, &lock->wait_list);
221 waiter.task = task;
222
223 if (atomic_xchg(&lock->count, -1) == 1)
224 goto done;
225
226 lock_contended(&lock->dep_map, ip);
227
228 for (;;) {
229
230
231
232
233
234
235
236
237
238 if (atomic_xchg(&lock->count, -1) == 1)
239 break;
240
241
242
243
244
245 if (unlikely(signal_pending_state(state, task))) {
246 mutex_remove_waiter(lock, &waiter,
247 task_thread_info(task));
248 mutex_release(&lock->dep_map, 1, ip);
249 spin_unlock_mutex(&lock->wait_lock, flags);
250
251 debug_mutex_free_waiter(&waiter);
252 preempt_enable();
253 return -EINTR;
254 }
255 __set_task_state(task, state);
256
257
258 spin_unlock_mutex(&lock->wait_lock, flags);
259 preempt_enable_no_resched();
260 schedule();
261 preempt_disable();
262 spin_lock_mutex(&lock->wait_lock, flags);
263 }
264
265done:
266 lock_acquired(&lock->dep_map, ip);
267
268 mutex_remove_waiter(lock, &waiter, current_thread_info());
269 mutex_set_owner(lock);
270
271
272 if (likely(list_empty(&lock->wait_list)))
273 atomic_set(&lock->count, 0);
274
275 spin_unlock_mutex(&lock->wait_lock, flags);
276
277 debug_mutex_free_waiter(&waiter);
278 preempt_enable();
279
280 return 0;
281}
282
283#ifdef CONFIG_DEBUG_LOCK_ALLOC
284void __sched
285mutex_lock_nested(struct mutex *lock, unsigned int subclass)
286{
287 might_sleep();
288 __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, subclass, _RET_IP_);
289}
290
291EXPORT_SYMBOL_GPL(mutex_lock_nested);
292
293int __sched
294mutex_lock_killable_nested(struct mutex *lock, unsigned int subclass)
295{
296 might_sleep();
297 return __mutex_lock_common(lock, TASK_KILLABLE, subclass, _RET_IP_);
298}
299EXPORT_SYMBOL_GPL(mutex_lock_killable_nested);
300
301int __sched
302mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass)
303{
304 might_sleep();
305 return __mutex_lock_common(lock, TASK_INTERRUPTIBLE,
306 subclass, _RET_IP_);
307}
308
309EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested);
310#endif
311
312
313
314
315static inline void
316__mutex_unlock_common_slowpath(atomic_t *lock_count, int nested)
317{
318 struct mutex *lock = container_of(lock_count, struct mutex, count);
319 unsigned long flags;
320
321 spin_lock_mutex(&lock->wait_lock, flags);
322 mutex_release(&lock->dep_map, nested, _RET_IP_);
323 debug_mutex_unlock(lock);
324
325
326
327
328
329
330 if (__mutex_slowpath_needs_to_unlock())
331 atomic_set(&lock->count, 1);
332
333 if (!list_empty(&lock->wait_list)) {
334
335 struct mutex_waiter *waiter =
336 list_entry(lock->wait_list.next,
337 struct mutex_waiter, list);
338
339 debug_mutex_wake_waiter(lock, waiter);
340
341 wake_up_process(waiter->task);
342 }
343
344 spin_unlock_mutex(&lock->wait_lock, flags);
345}
346
347
348
349
350static __used noinline void
351__mutex_unlock_slowpath(atomic_t *lock_count)
352{
353 __mutex_unlock_common_slowpath(lock_count, 1);
354}
355
356#ifndef CONFIG_DEBUG_LOCK_ALLOC
357
358
359
360
361static noinline int __sched
362__mutex_lock_killable_slowpath(atomic_t *lock_count);
363
364static noinline int __sched
365__mutex_lock_interruptible_slowpath(atomic_t *lock_count);
366
367
368
369
370
371
372
373
374
375
376
377
378int __sched mutex_lock_interruptible(struct mutex *lock)
379{
380 int ret;
381
382 might_sleep();
383 ret = __mutex_fastpath_lock_retval
384 (&lock->count, __mutex_lock_interruptible_slowpath);
385 if (!ret)
386 mutex_set_owner(lock);
387
388 return ret;
389}
390
391EXPORT_SYMBOL(mutex_lock_interruptible);
392
393int __sched mutex_lock_killable(struct mutex *lock)
394{
395 int ret;
396
397 might_sleep();
398 ret = __mutex_fastpath_lock_retval
399 (&lock->count, __mutex_lock_killable_slowpath);
400 if (!ret)
401 mutex_set_owner(lock);
402
403 return ret;
404}
405EXPORT_SYMBOL(mutex_lock_killable);
406
407static __used noinline void __sched
408__mutex_lock_slowpath(atomic_t *lock_count)
409{
410 struct mutex *lock = container_of(lock_count, struct mutex, count);
411
412 __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0, _RET_IP_);
413}
414
415static noinline int __sched
416__mutex_lock_killable_slowpath(atomic_t *lock_count)
417{
418 struct mutex *lock = container_of(lock_count, struct mutex, count);
419
420 return __mutex_lock_common(lock, TASK_KILLABLE, 0, _RET_IP_);
421}
422
423static noinline int __sched
424__mutex_lock_interruptible_slowpath(atomic_t *lock_count)
425{
426 struct mutex *lock = container_of(lock_count, struct mutex, count);
427
428 return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, 0, _RET_IP_);
429}
430#endif
431
432
433
434
435
436static inline int __mutex_trylock_slowpath(atomic_t *lock_count)
437{
438 struct mutex *lock = container_of(lock_count, struct mutex, count);
439 unsigned long flags;
440 int prev;
441
442 spin_lock_mutex(&lock->wait_lock, flags);
443
444 prev = atomic_xchg(&lock->count, -1);
445 if (likely(prev == 1)) {
446 mutex_set_owner(lock);
447 mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_);
448 }
449
450
451 if (likely(list_empty(&lock->wait_list)))
452 atomic_set(&lock->count, 0);
453
454 spin_unlock_mutex(&lock->wait_lock, flags);
455
456 return prev == 1;
457}
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473int __sched mutex_trylock(struct mutex *lock)
474{
475 int ret;
476
477 ret = __mutex_fastpath_trylock(&lock->count, __mutex_trylock_slowpath);
478 if (ret)
479 mutex_set_owner(lock);
480
481 return ret;
482}
483EXPORT_SYMBOL(mutex_trylock);
484
485
486
487
488
489
490
491
492int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock)
493{
494
495 if (atomic_add_unless(cnt, -1, 1))
496 return 0;
497
498 mutex_lock(lock);
499 if (!atomic_dec_and_test(cnt)) {
500
501 mutex_unlock(lock);
502 return 0;
503 }
504
505 return 1;
506}
507EXPORT_SYMBOL(atomic_dec_and_mutex_lock);
508