blob: 389f9bdec9bea58ea9b934bd8b9f837dee3bb18d [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * kernel/rt.c
3 *
4 * Real-Time Preemption Support
5 *
6 * started by Ingo Molnar:
7 *
8 * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
9 * Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
10 *
11 * historic credit for proving that Linux spinlocks can be implemented via
12 * RT-aware mutexes goes to many people: The Pmutex project (Dirk Grambow
13 * and others) who prototyped it on 2.4 and did lots of comparative
14 * research and analysis; TimeSys, for proving that you can implement a
15 * fully preemptible kernel via the use of IRQ threading and mutexes;
16 * Bill Huey for persuasively arguing on lkml that the mutex model is the
17 * right one; and to MontaVista, who ported pmutexes to 2.6.
18 *
19 * This code is a from-scratch implementation and is not based on pmutexes,
20 * but the idea of converting spinlocks to mutexes is used here too.
21 *
22 * lock debugging, locking tree, deadlock detection:
23 *
24 * Copyright (C) 2004, LynuxWorks, Inc., Igor Manyilov, Bill Huey
25 * Released under the General Public License (GPL).
26 *
27 * Includes portions of the generic R/W semaphore implementation from:
28 *
29 * Copyright (c) 2001 David Howells (dhowells@redhat.com).
30 * - Derived partially from idea by Andrea Arcangeli <andrea@suse.de>
31 * - Derived also from comments by Linus
32 *
33 * Pending ownership of locks and ownership stealing:
34 *
35 * Copyright (C) 2005, Kihon Technologies Inc., Steven Rostedt
36 *
37 * (also by Steven Rostedt)
38 * - Converted single pi_lock to individual task locks.
39 *
40 * By Esben Nielsen:
41 * Doing priority inheritance with help of the scheduler.
42 *
43 * Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
44 * - major rework based on Esben Nielsens initial patch
45 * - replaced thread_info references by task_struct refs
46 * - removed task->pending_owner dependency
47 * - BKL drop/reacquire for semaphore style locks to avoid deadlocks
48 * in the scheduler return path as discussed with Steven Rostedt
49 *
50 * Copyright (C) 2006, Kihon Technologies Inc.
51 * Steven Rostedt <rostedt@goodmis.org>
52 * - debugged and patched Thomas Gleixner's rework.
53 * - added back the cmpxchg to the rework.
54 * - turned atomic require back on for SMP.
55 */
56
57#include <linux/spinlock.h>
58#include <linux/rtmutex.h>
59#include <linux/sched.h>
60#include <linux/delay.h>
61#include <linux/module.h>
62#include <linux/kallsyms.h>
63#include <linux/syscalls.h>
64#include <linux/interrupt.h>
65#include <linux/plist.h>
66#include <linux/fs.h>
67#include <linux/futex.h>
68#include <linux/hrtimer.h>
69
70#include "rtmutex_common.h"
71
72/*
73 * struct mutex functions
74 */
75void __mutex_do_init(struct mutex *mutex, const char *name,
76 struct lock_class_key *key)
77{
78#ifdef CONFIG_DEBUG_LOCK_ALLOC
79 /*
80 * Make sure we are not reinitializing a held lock:
81 */
82 debug_check_no_locks_freed((void *)mutex, sizeof(*mutex));
83 lockdep_init_map(&mutex->dep_map, name, key, 0);
84#endif
85 mutex->lock.save_state = 0;
86}
87EXPORT_SYMBOL(__mutex_do_init);
88
89void __lockfunc _mutex_lock(struct mutex *lock)
90{
91 mutex_acquire(&lock->dep_map, 0, 0, _RET_IP_);
92 rt_mutex_lock(&lock->lock);
93}
94EXPORT_SYMBOL(_mutex_lock);
95
96int __lockfunc _mutex_lock_interruptible(struct mutex *lock)
97{
98 int ret;
99
100 mutex_acquire(&lock->dep_map, 0, 0, _RET_IP_);
101 ret = rt_mutex_lock_interruptible(&lock->lock);
102 if (ret)
103 mutex_release(&lock->dep_map, 1, _RET_IP_);
104 return ret;
105}
106EXPORT_SYMBOL(_mutex_lock_interruptible);
107
108int __lockfunc _mutex_lock_killable(struct mutex *lock)
109{
110 int ret;
111
112 mutex_acquire(&lock->dep_map, 0, 0, _RET_IP_);
113 ret = rt_mutex_lock_killable(&lock->lock);
114 if (ret)
115 mutex_release(&lock->dep_map, 1, _RET_IP_);
116 return ret;
117}
118EXPORT_SYMBOL(_mutex_lock_killable);
119
120#ifdef CONFIG_DEBUG_LOCK_ALLOC
121void __lockfunc _mutex_lock_nested(struct mutex *lock, int subclass)
122{
123 mutex_acquire_nest(&lock->dep_map, subclass, 0, NULL, _RET_IP_);
124 rt_mutex_lock(&lock->lock);
125}
126EXPORT_SYMBOL(_mutex_lock_nested);
127
128void __lockfunc _mutex_lock_nest_lock(struct mutex *lock, struct lockdep_map *nest)
129{
130 mutex_acquire_nest(&lock->dep_map, 0, 0, nest, _RET_IP_);
131 rt_mutex_lock(&lock->lock);
132}
133EXPORT_SYMBOL(_mutex_lock_nest_lock);
134
135int __lockfunc _mutex_lock_interruptible_nested(struct mutex *lock, int subclass)
136{
137 int ret;
138
139 mutex_acquire_nest(&lock->dep_map, subclass, 0, NULL, _RET_IP_);
140 ret = rt_mutex_lock_interruptible(&lock->lock);
141 if (ret)
142 mutex_release(&lock->dep_map, 1, _RET_IP_);
143 return ret;
144}
145EXPORT_SYMBOL(_mutex_lock_interruptible_nested);
146
147int __lockfunc _mutex_lock_killable_nested(struct mutex *lock, int subclass)
148{
149 int ret;
150
151 mutex_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
152 ret = rt_mutex_lock_killable(&lock->lock);
153 if (ret)
154 mutex_release(&lock->dep_map, 1, _RET_IP_);
155 return ret;
156}
157EXPORT_SYMBOL(_mutex_lock_killable_nested);
158#endif
159
160int __lockfunc _mutex_trylock(struct mutex *lock)
161{
162 int ret = rt_mutex_trylock(&lock->lock);
163
164 if (ret)
165 mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_);
166
167 return ret;
168}
169EXPORT_SYMBOL(_mutex_trylock);
170
171void __lockfunc _mutex_unlock(struct mutex *lock)
172{
173 mutex_release(&lock->dep_map, 1, _RET_IP_);
174 rt_mutex_unlock(&lock->lock);
175}
176EXPORT_SYMBOL(_mutex_unlock);
177
178/*
179 * rwlock_t functions
180 */
181int __lockfunc rt_write_trylock(rwlock_t *rwlock)
182{
183 int ret = rt_mutex_trylock(&rwlock->lock);
184
185 migrate_disable();
186 if (ret)
187 rwlock_acquire(&rwlock->dep_map, 0, 1, _RET_IP_);
188 else
189 migrate_enable();
190
191 return ret;
192}
193EXPORT_SYMBOL(rt_write_trylock);
194
195int __lockfunc rt_write_trylock_irqsave(rwlock_t *rwlock, unsigned long *flags)
196{
197 int ret;
198
199 *flags = 0;
200 migrate_disable();
201 ret = rt_write_trylock(rwlock);
202 if (!ret)
203 migrate_enable();
204 return ret;
205}
206EXPORT_SYMBOL(rt_write_trylock_irqsave);
207
208int __lockfunc rt_read_trylock(rwlock_t *rwlock)
209{
210 struct rt_mutex *lock = &rwlock->lock;
211 int ret = 1;
212
213 /*
214 * recursive read locks succeed when current owns the lock,
215 * but not when read_depth == 0 which means that the lock is
216 * write locked.
217 */
218 migrate_disable();
219 if (rt_mutex_owner(lock) != current) {
220 ret = rt_mutex_trylock(lock);
221 if (ret)
222 rwlock_acquire(&rwlock->dep_map, 0, 1, _RET_IP_);
223 } else if (!rwlock->read_depth) {
224 ret = 0;
225 }
226
227 if (ret)
228 rwlock->read_depth++;
229 else
230 migrate_enable();
231
232 return ret;
233}
234EXPORT_SYMBOL(rt_read_trylock);
235
236void __lockfunc rt_write_lock(rwlock_t *rwlock)
237{
238 rwlock_acquire(&rwlock->dep_map, 0, 0, _RET_IP_);
239 __rt_spin_lock(&rwlock->lock);
240}
241EXPORT_SYMBOL(rt_write_lock);
242
243void __lockfunc rt_read_lock(rwlock_t *rwlock)
244{
245 struct rt_mutex *lock = &rwlock->lock;
246
247 /*
248 * recursive read locks succeed when current owns the lock
249 */
250 if (rt_mutex_owner(lock) != current) {
251 rwlock_acquire(&rwlock->dep_map, 0, 0, _RET_IP_);
252 __rt_spin_lock(lock);
253 }
254 rwlock->read_depth++;
255}
256
257EXPORT_SYMBOL(rt_read_lock);
258
259void __lockfunc rt_write_unlock(rwlock_t *rwlock)
260{
261 /* NOTE: we always pass in '1' for nested, for simplicity */
262 rwlock_release(&rwlock->dep_map, 1, _RET_IP_);
263 __rt_spin_unlock(&rwlock->lock);
264}
265EXPORT_SYMBOL(rt_write_unlock);
266
267void __lockfunc rt_read_unlock(rwlock_t *rwlock)
268{
269 /* Release the lock only when read_depth is down to 0 */
270 if (--rwlock->read_depth == 0) {
271 rwlock_release(&rwlock->dep_map, 1, _RET_IP_);
272 __rt_spin_unlock(&rwlock->lock);
273 }
274}
275EXPORT_SYMBOL(rt_read_unlock);
276
277unsigned long __lockfunc rt_write_lock_irqsave(rwlock_t *rwlock)
278{
279 rt_write_lock(rwlock);
280
281 return 0;
282}
283EXPORT_SYMBOL(rt_write_lock_irqsave);
284
285unsigned long __lockfunc rt_read_lock_irqsave(rwlock_t *rwlock)
286{
287 rt_read_lock(rwlock);
288
289 return 0;
290}
291EXPORT_SYMBOL(rt_read_lock_irqsave);
292
293void __rt_rwlock_init(rwlock_t *rwlock, char *name, struct lock_class_key *key)
294{
295#ifdef CONFIG_DEBUG_LOCK_ALLOC
296 /*
297 * Make sure we are not reinitializing a held lock:
298 */
299 debug_check_no_locks_freed((void *)rwlock, sizeof(*rwlock));
300 lockdep_init_map(&rwlock->dep_map, name, key, 0);
301#endif
302 rwlock->lock.save_state = 1;
303 rwlock->read_depth = 0;
304}
305EXPORT_SYMBOL(__rt_rwlock_init);
306
307/*
308 * rw_semaphores
309 */
310
311void rt_up_write(struct rw_semaphore *rwsem)
312{
313 rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
314 rt_mutex_unlock(&rwsem->lock);
315}
316EXPORT_SYMBOL(rt_up_write);
317
318void rt_up_read(struct rw_semaphore *rwsem)
319{
320 if (--rwsem->read_depth == 0) {
321 rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
322 rt_mutex_unlock(&rwsem->lock);
323 }
324}
325EXPORT_SYMBOL(rt_up_read);
326
327/*
328 * downgrade a write lock into a read lock
329 * - just wake up any readers at the front of the queue
330 */
331void rt_downgrade_write(struct rw_semaphore *rwsem)
332{
333 BUG_ON(rt_mutex_owner(&rwsem->lock) != current);
334 rwsem->read_depth = 1;
335}
336EXPORT_SYMBOL(rt_downgrade_write);
337
338int rt_down_write_trylock(struct rw_semaphore *rwsem)
339{
340 int ret = rt_mutex_trylock(&rwsem->lock);
341
342 if (ret)
343 rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
344 return ret;
345}
346EXPORT_SYMBOL(rt_down_write_trylock);
347
348void rt_down_write(struct rw_semaphore *rwsem)
349{
350 rwsem_acquire(&rwsem->dep_map, 0, 0, _RET_IP_);
351 rt_mutex_lock(&rwsem->lock);
352}
353EXPORT_SYMBOL(rt_down_write);
354
355void rt_down_write_nested(struct rw_semaphore *rwsem, int subclass)
356{
357 rwsem_acquire(&rwsem->dep_map, subclass, 0, _RET_IP_);
358 rt_mutex_lock(&rwsem->lock);
359}
360EXPORT_SYMBOL(rt_down_write_nested);
361
362int rt_down_read_trylock(struct rw_semaphore *rwsem)
363{
364 struct rt_mutex *lock = &rwsem->lock;
365 int ret = 1;
366
367 /*
368 * recursive read locks succeed when current owns the rwsem,
369 * but not when read_depth == 0 which means that the rwsem is
370 * write locked.
371 */
372 if (rt_mutex_owner(lock) != current) {
373 ret = rt_mutex_trylock(&rwsem->lock);
374 if (ret)
375 rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
376 } else if (!rwsem->read_depth) {
377 ret = 0;
378 }
379
380 if (ret)
381 rwsem->read_depth++;
382 return ret;
383}
384EXPORT_SYMBOL(rt_down_read_trylock);
385
386static void __rt_down_read(struct rw_semaphore *rwsem, int subclass)
387{
388 struct rt_mutex *lock = &rwsem->lock;
389
390 if (rt_mutex_owner(lock) != current) {
391 rwsem_acquire(&rwsem->dep_map, subclass, 0, _RET_IP_);
392 rt_mutex_lock(&rwsem->lock);
393 }
394 rwsem->read_depth++;
395}
396
397void rt_down_read(struct rw_semaphore *rwsem)
398{
399 __rt_down_read(rwsem, 0);
400}
401EXPORT_SYMBOL(rt_down_read);
402
403void rt_down_read_nested(struct rw_semaphore *rwsem, int subclass)
404{
405 __rt_down_read(rwsem, subclass);
406}
407EXPORT_SYMBOL(rt_down_read_nested);
408
409void __rt_rwsem_init(struct rw_semaphore *rwsem, char *name,
410 struct lock_class_key *key)
411{
412#ifdef CONFIG_DEBUG_LOCK_ALLOC
413 /*
414 * Make sure we are not reinitializing a held lock:
415 */
416 debug_check_no_locks_freed((void *)rwsem, sizeof(*rwsem));
417 lockdep_init_map(&rwsem->dep_map, name, key, 0);
418#endif
419 rwsem->read_depth = 0;
420 rwsem->lock.save_state = 0;
421}
422EXPORT_SYMBOL(__rt_rwsem_init);
423
424/**
425 * atomic_dec_and_mutex_lock - return holding mutex if we dec to 0
426 * @cnt: the atomic which we are to dec
427 * @lock: the mutex to return holding if we dec to 0
428 *
429 * return true and hold lock if we dec to 0, return false otherwise
430 */
431int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock)
432{
433 /* dec if we can't possibly hit 0 */
434 if (atomic_add_unless(cnt, -1, 1))
435 return 0;
436 /* we might hit 0, so take the lock */
437 mutex_lock(lock);
438 if (!atomic_dec_and_test(cnt)) {
439 /* when we actually did the dec, we didn't hit 0 */
440 mutex_unlock(lock);
441 return 0;
442 }
443 /* we hit 0, and we hold the lock */
444 return 1;
445}
446EXPORT_SYMBOL(atomic_dec_and_mutex_lock);