summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2016-09-19 06:15:37 -0400
committerIngo Molnar <mingo@kernel.org>2017-06-08 04:35:49 -0400
commitf5694788ad8da5da41b501f3d6d2ae22379c4ef9 (patch)
tree660f642ba2afcd13ef71449526184480202e8d63
parent3942b77121986519ee52ab4dd4ae8f4383dfe765 (diff)
rt_mutex: Add lockdep annotations
Now that (PI) futexes have their own private RT-mutex interface and implementation we can easily add lockdep annotations to the existing RT-mutex interface. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--include/linux/rtmutex.h25
-rw-r--r--kernel/locking/rtmutex-debug.c6
-rw-r--r--kernel/locking/rtmutex-debug.h2
-rw-r--r--kernel/locking/rtmutex.c36
-rw-r--r--kernel/locking/rtmutex.h2
-rw-r--r--lib/Kconfig.debug3
6 files changed, 60 insertions, 14 deletions
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h
index 1abba5ce2a2f..44fd002f7cd5 100644
--- a/include/linux/rtmutex.h
+++ b/include/linux/rtmutex.h
@@ -37,6 +37,9 @@ struct rt_mutex {
37 int line; 37 int line;
38 void *magic; 38 void *magic;
39#endif 39#endif
40#ifdef CONFIG_DEBUG_LOCK_ALLOC
41 struct lockdep_map dep_map;
42#endif
40}; 43};
41 44
42struct rt_mutex_waiter; 45struct rt_mutex_waiter;
@@ -58,19 +61,33 @@ struct hrtimer_sleeper;
58#ifdef CONFIG_DEBUG_RT_MUTEXES 61#ifdef CONFIG_DEBUG_RT_MUTEXES
59# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname) \ 62# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname) \
60 , .name = #mutexname, .file = __FILE__, .line = __LINE__ 63 , .name = #mutexname, .file = __FILE__, .line = __LINE__
61# define rt_mutex_init(mutex) __rt_mutex_init(mutex, __func__) 64
65# define rt_mutex_init(mutex) \
66do { \
67 static struct lock_class_key __key; \
68 __rt_mutex_init(mutex, __func__, &__key); \
69} while (0)
70
62 extern void rt_mutex_debug_task_free(struct task_struct *tsk); 71 extern void rt_mutex_debug_task_free(struct task_struct *tsk);
63#else 72#else
64# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname) 73# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname)
65# define rt_mutex_init(mutex) __rt_mutex_init(mutex, NULL) 74# define rt_mutex_init(mutex) __rt_mutex_init(mutex, NULL, NULL)
66# define rt_mutex_debug_task_free(t) do { } while (0) 75# define rt_mutex_debug_task_free(t) do { } while (0)
67#endif 76#endif
68 77
78#ifdef CONFIG_DEBUG_LOCK_ALLOC
79#define __DEP_MAP_RT_MUTEX_INITIALIZER(mutexname) \
80 , .dep_map = { .name = #mutexname }
81#else
82#define __DEP_MAP_RT_MUTEX_INITIALIZER(mutexname)
83#endif
84
69#define __RT_MUTEX_INITIALIZER(mutexname) \ 85#define __RT_MUTEX_INITIALIZER(mutexname) \
70 { .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \ 86 { .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \
71 , .waiters = RB_ROOT \ 87 , .waiters = RB_ROOT \
72 , .owner = NULL \ 88 , .owner = NULL \
73 __DEBUG_RT_MUTEX_INITIALIZER(mutexname)} 89 __DEBUG_RT_MUTEX_INITIALIZER(mutexname) \
90 __DEP_MAP_RT_MUTEX_INITIALIZER(mutexname)}
74 91
75#define DEFINE_RT_MUTEX(mutexname) \ 92#define DEFINE_RT_MUTEX(mutexname) \
76 struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname) 93 struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname)
@@ -86,7 +103,7 @@ static inline int rt_mutex_is_locked(struct rt_mutex *lock)
86 return lock->owner != NULL; 103 return lock->owner != NULL;
87} 104}
88 105
89extern void __rt_mutex_init(struct rt_mutex *lock, const char *name); 106extern void __rt_mutex_init(struct rt_mutex *lock, const char *name, struct lock_class_key *key);
90extern void rt_mutex_destroy(struct rt_mutex *lock); 107extern void rt_mutex_destroy(struct rt_mutex *lock);
91 108
92extern void rt_mutex_lock(struct rt_mutex *lock); 109extern void rt_mutex_lock(struct rt_mutex *lock);
diff --git a/kernel/locking/rtmutex-debug.c b/kernel/locking/rtmutex-debug.c
index 58e366ad36f4..ac35e648b0e5 100644
--- a/kernel/locking/rtmutex-debug.c
+++ b/kernel/locking/rtmutex-debug.c
@@ -166,12 +166,16 @@ void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)
166 memset(waiter, 0x22, sizeof(*waiter)); 166 memset(waiter, 0x22, sizeof(*waiter));
167} 167}
168 168
169void debug_rt_mutex_init(struct rt_mutex *lock, const char *name) 169void debug_rt_mutex_init(struct rt_mutex *lock, const char *name, struct lock_class_key *key)
170{ 170{
171 /* 171 /*
172 * Make sure we are not reinitializing a held lock: 172 * Make sure we are not reinitializing a held lock:
173 */ 173 */
174 debug_check_no_locks_freed((void *)lock, sizeof(*lock)); 174 debug_check_no_locks_freed((void *)lock, sizeof(*lock));
175 lock->name = name; 175 lock->name = name;
176
177#ifdef CONFIG_DEBUG_LOCK_ALLOC
178 lockdep_init_map(&lock->dep_map, name, key, 0);
179#endif
176} 180}
177 181
diff --git a/kernel/locking/rtmutex-debug.h b/kernel/locking/rtmutex-debug.h
index b585af9a1b50..5078c6ddf4a5 100644
--- a/kernel/locking/rtmutex-debug.h
+++ b/kernel/locking/rtmutex-debug.h
@@ -11,7 +11,7 @@
11 11
12extern void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter); 12extern void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter);
13extern void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter); 13extern void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter);
14extern void debug_rt_mutex_init(struct rt_mutex *lock, const char *name); 14extern void debug_rt_mutex_init(struct rt_mutex *lock, const char *name, struct lock_class_key *key);
15extern void debug_rt_mutex_lock(struct rt_mutex *lock); 15extern void debug_rt_mutex_lock(struct rt_mutex *lock);
16extern void debug_rt_mutex_unlock(struct rt_mutex *lock); 16extern void debug_rt_mutex_unlock(struct rt_mutex *lock);
17extern void debug_rt_mutex_proxy_lock(struct rt_mutex *lock, 17extern void debug_rt_mutex_proxy_lock(struct rt_mutex *lock,
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 28cd09e635ed..43123533e9b1 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1481,6 +1481,7 @@ void __sched rt_mutex_lock(struct rt_mutex *lock)
1481{ 1481{
1482 might_sleep(); 1482 might_sleep();
1483 1483
1484 mutex_acquire(&lock->dep_map, 0, 0, _RET_IP_);
1484 rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, rt_mutex_slowlock); 1485 rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, rt_mutex_slowlock);
1485} 1486}
1486EXPORT_SYMBOL_GPL(rt_mutex_lock); 1487EXPORT_SYMBOL_GPL(rt_mutex_lock);
@@ -1496,9 +1497,16 @@ EXPORT_SYMBOL_GPL(rt_mutex_lock);
1496 */ 1497 */
1497int __sched rt_mutex_lock_interruptible(struct rt_mutex *lock) 1498int __sched rt_mutex_lock_interruptible(struct rt_mutex *lock)
1498{ 1499{
1500 int ret;
1501
1499 might_sleep(); 1502 might_sleep();
1500 1503
1501 return rt_mutex_fastlock(lock, TASK_INTERRUPTIBLE, rt_mutex_slowlock); 1504 mutex_acquire(&lock->dep_map, 0, 0, _RET_IP_);
1505 ret = rt_mutex_fastlock(lock, TASK_INTERRUPTIBLE, rt_mutex_slowlock);
1506 if (ret)
1507 mutex_release(&lock->dep_map, 1, _RET_IP_);
1508
1509 return ret;
1502} 1510}
1503EXPORT_SYMBOL_GPL(rt_mutex_lock_interruptible); 1511EXPORT_SYMBOL_GPL(rt_mutex_lock_interruptible);
1504 1512
@@ -1526,11 +1534,18 @@ int __sched rt_mutex_futex_trylock(struct rt_mutex *lock)
1526int 1534int
1527rt_mutex_timed_lock(struct rt_mutex *lock, struct hrtimer_sleeper *timeout) 1535rt_mutex_timed_lock(struct rt_mutex *lock, struct hrtimer_sleeper *timeout)
1528{ 1536{
1537 int ret;
1538
1529 might_sleep(); 1539 might_sleep();
1530 1540
1531 return rt_mutex_timed_fastlock(lock, TASK_INTERRUPTIBLE, timeout, 1541 mutex_acquire(&lock->dep_map, 0, 0, _RET_IP_);
1542 ret = rt_mutex_timed_fastlock(lock, TASK_INTERRUPTIBLE, timeout,
1532 RT_MUTEX_MIN_CHAINWALK, 1543 RT_MUTEX_MIN_CHAINWALK,
1533 rt_mutex_slowlock); 1544 rt_mutex_slowlock);
1545 if (ret)
1546 mutex_release(&lock->dep_map, 1, _RET_IP_);
1547
1548 return ret;
1534} 1549}
1535EXPORT_SYMBOL_GPL(rt_mutex_timed_lock); 1550EXPORT_SYMBOL_GPL(rt_mutex_timed_lock);
1536 1551
@@ -1547,10 +1562,16 @@ EXPORT_SYMBOL_GPL(rt_mutex_timed_lock);
1547 */ 1562 */
1548int __sched rt_mutex_trylock(struct rt_mutex *lock) 1563int __sched rt_mutex_trylock(struct rt_mutex *lock)
1549{ 1564{
1565 int ret;
1566
1550 if (WARN_ON_ONCE(in_irq() || in_nmi() || in_serving_softirq())) 1567 if (WARN_ON_ONCE(in_irq() || in_nmi() || in_serving_softirq()))
1551 return 0; 1568 return 0;
1552 1569
1553 return rt_mutex_fasttrylock(lock, rt_mutex_slowtrylock); 1570 ret = rt_mutex_fasttrylock(lock, rt_mutex_slowtrylock);
1571 if (ret)
1572 mutex_acquire(&lock->dep_map, 0, 1, _RET_IP_);
1573
1574 return ret;
1554} 1575}
1555EXPORT_SYMBOL_GPL(rt_mutex_trylock); 1576EXPORT_SYMBOL_GPL(rt_mutex_trylock);
1556 1577
@@ -1561,6 +1582,7 @@ EXPORT_SYMBOL_GPL(rt_mutex_trylock);
1561 */ 1582 */
1562void __sched rt_mutex_unlock(struct rt_mutex *lock) 1583void __sched rt_mutex_unlock(struct rt_mutex *lock)
1563{ 1584{
1585 mutex_release(&lock->dep_map, 1, _RET_IP_);
1564 rt_mutex_fastunlock(lock, rt_mutex_slowunlock); 1586 rt_mutex_fastunlock(lock, rt_mutex_slowunlock);
1565} 1587}
1566EXPORT_SYMBOL_GPL(rt_mutex_unlock); 1588EXPORT_SYMBOL_GPL(rt_mutex_unlock);
@@ -1620,7 +1642,6 @@ void rt_mutex_destroy(struct rt_mutex *lock)
1620 lock->magic = NULL; 1642 lock->magic = NULL;
1621#endif 1643#endif
1622} 1644}
1623
1624EXPORT_SYMBOL_GPL(rt_mutex_destroy); 1645EXPORT_SYMBOL_GPL(rt_mutex_destroy);
1625 1646
1626/** 1647/**
@@ -1632,14 +1653,15 @@ EXPORT_SYMBOL_GPL(rt_mutex_destroy);
1632 * 1653 *
1633 * Initializing of a locked rt lock is not allowed 1654 * Initializing of a locked rt lock is not allowed
1634 */ 1655 */
1635void __rt_mutex_init(struct rt_mutex *lock, const char *name) 1656void __rt_mutex_init(struct rt_mutex *lock, const char *name,
1657 struct lock_class_key *key)
1636{ 1658{
1637 lock->owner = NULL; 1659 lock->owner = NULL;
1638 raw_spin_lock_init(&lock->wait_lock); 1660 raw_spin_lock_init(&lock->wait_lock);
1639 lock->waiters = RB_ROOT; 1661 lock->waiters = RB_ROOT;
1640 lock->waiters_leftmost = NULL; 1662 lock->waiters_leftmost = NULL;
1641 1663
1642 debug_rt_mutex_init(lock, name); 1664 debug_rt_mutex_init(lock, name, key);
1643} 1665}
1644EXPORT_SYMBOL_GPL(__rt_mutex_init); 1666EXPORT_SYMBOL_GPL(__rt_mutex_init);
1645 1667
@@ -1660,7 +1682,7 @@ EXPORT_SYMBOL_GPL(__rt_mutex_init);
1660void rt_mutex_init_proxy_locked(struct rt_mutex *lock, 1682void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
1661 struct task_struct *proxy_owner) 1683 struct task_struct *proxy_owner)
1662{ 1684{
1663 __rt_mutex_init(lock, NULL); 1685 __rt_mutex_init(lock, NULL, NULL);
1664 debug_rt_mutex_proxy_lock(lock, proxy_owner); 1686 debug_rt_mutex_proxy_lock(lock, proxy_owner);
1665 rt_mutex_set_owner(lock, proxy_owner); 1687 rt_mutex_set_owner(lock, proxy_owner);
1666} 1688}
diff --git a/kernel/locking/rtmutex.h b/kernel/locking/rtmutex.h
index 6607802efa8b..5c253caffe91 100644
--- a/kernel/locking/rtmutex.h
+++ b/kernel/locking/rtmutex.h
@@ -17,7 +17,7 @@
17#define debug_rt_mutex_proxy_lock(l,p) do { } while (0) 17#define debug_rt_mutex_proxy_lock(l,p) do { } while (0)
18#define debug_rt_mutex_proxy_unlock(l) do { } while (0) 18#define debug_rt_mutex_proxy_unlock(l) do { } while (0)
19#define debug_rt_mutex_unlock(l) do { } while (0) 19#define debug_rt_mutex_unlock(l) do { } while (0)
20#define debug_rt_mutex_init(m, n) do { } while (0) 20#define debug_rt_mutex_init(m, n, k) do { } while (0)
21#define debug_rt_mutex_deadlock(d, a ,l) do { } while (0) 21#define debug_rt_mutex_deadlock(d, a ,l) do { } while (0)
22#define debug_rt_mutex_print_deadlock(w) do { } while (0) 22#define debug_rt_mutex_print_deadlock(w) do { } while (0)
23#define debug_rt_mutex_reset_waiter(w) do { } while (0) 23#define debug_rt_mutex_reset_waiter(w) do { } while (0)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index e4587ebe52c7..ca615129aec5 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1052,6 +1052,7 @@ config DEBUG_LOCK_ALLOC
1052 depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT 1052 depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
1053 select DEBUG_SPINLOCK 1053 select DEBUG_SPINLOCK
1054 select DEBUG_MUTEXES 1054 select DEBUG_MUTEXES
1055 select DEBUG_RT_MUTEXES if RT_MUTEXES
1055 select LOCKDEP 1056 select LOCKDEP
1056 help 1057 help
1057 This feature will check whether any held lock (spinlock, rwlock, 1058 This feature will check whether any held lock (spinlock, rwlock,
@@ -1067,6 +1068,7 @@ config PROVE_LOCKING
1067 select LOCKDEP 1068 select LOCKDEP
1068 select DEBUG_SPINLOCK 1069 select DEBUG_SPINLOCK
1069 select DEBUG_MUTEXES 1070 select DEBUG_MUTEXES
1071 select DEBUG_RT_MUTEXES if RT_MUTEXES
1070 select DEBUG_LOCK_ALLOC 1072 select DEBUG_LOCK_ALLOC
1071 select TRACE_IRQFLAGS 1073 select TRACE_IRQFLAGS
1072 default n 1074 default n
@@ -1121,6 +1123,7 @@ config LOCK_STAT
1121 select LOCKDEP 1123 select LOCKDEP
1122 select DEBUG_SPINLOCK 1124 select DEBUG_SPINLOCK
1123 select DEBUG_MUTEXES 1125 select DEBUG_MUTEXES
1126 select DEBUG_RT_MUTEXES if RT_MUTEXES
1124 select DEBUG_LOCK_ALLOC 1127 select DEBUG_LOCK_ALLOC
1125 default n 1128 default n
1126 help 1129 help