Enable context analysis for struct rt_mutex and annotate all functions that accept a struct rt_mutex pointer. In the __rt_mutex_lock_common() callers, instead of adding the __no_context_analysis annotation, emit a runtime warning if the __rt_mutex_lock_common() return value is not zero and add an __acquire() statement.
Unified · Split
| @@ -56,6 +56,8 @@ static inline struct task_struct *rt_mutex_owner(struct rt_mutex_base *lock) · 55 unmodified lines | ||
| 56 | 56 | #endif |
| 57 | 57 | extern void rt_mutex_base_init(struct rt_mutex_base *rtb); |
| 58 | 58 | |
| 59 | +context_lock_struct(rt_mutex); | |
| 60 | + | |
| 59 | 61 | /** |
| 60 | 62 | * The rt_mutex structure |
| 61 | 63 | * |
| @@ -108,8 +110,10 @@ do { \ · 46 unmodified lines | ||
| 108 | 110 | extern void __rt_mutex_init(struct rt_mutex *lock, const char *name, struct lock_class_key *key); |
| 109 | 111 | |
| 110 | 112 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
| 111 | −extern void rt_mutex_lock_nested(struct rt_mutex *lock, unsigned int subclass); | |
| 112 | −extern void _rt_mutex_lock_nest_lock(struct rt_mutex *lock, struct lockdep_map *nest_lock); | |
| 113 | +extern void rt_mutex_lock_nested(struct rt_mutex *lock, unsigned int subclass) | |
| 114 | + __acquires(lock); | |
| 115 | +extern void _rt_mutex_lock_nest_lock(struct rt_mutex *lock, struct lockdep_map *nest_lock) | |
| 116 | + __acquires(lock); | |
| 113 | 117 | #define rt_mutex_lock(lock) rt_mutex_lock_nested(lock, 0) |
| 114 | 118 | #define rt_mutex_lock_nest_lock(lock, nest_lock) \ |
| 115 | 119 | do { \ |
| @@ -118,15 +122,19 @@ extern void _rt_mutex_lock_nest_lock(struct rt_mutex *lock, struct lockdep_map * · 2 unmodified lines | ||
| 118 | 122 | } while (0) |
| 119 | 123 | |
| 120 | 124 | #else |
| 121 | −extern void rt_mutex_lock(struct rt_mutex *lock); | |
| 125 | +extern void rt_mutex_lock(struct rt_mutex *lock) __acquires(lock); | |
| 122 | 126 | #define rt_mutex_lock_nested(lock, subclass) rt_mutex_lock(lock) |
| 123 | 127 | #define rt_mutex_lock_nest_lock(lock, nest_lock) rt_mutex_lock(lock) |
| 124 | 128 | #endif |
| 125 | 129 | |
| 126 | −extern int rt_mutex_lock_interruptible(struct rt_mutex *lock); | |
| 127 | −extern int rt_mutex_lock_killable(struct rt_mutex *lock); | |
| 128 | −extern int rt_mutex_trylock(struct rt_mutex *lock); | |
| 130 | +extern int rt_mutex_lock_interruptible(struct rt_mutex *lock) | |
| 131 | + __cond_acquires(0, lock); | |
| 132 | +extern int rt_mutex_lock_killable(struct rt_mutex *lock) | |
| 133 | + __cond_acquires(0, lock); | |
| 134 | +extern int rt_mutex_trylock(struct rt_mutex *lock) | |
| 135 | + __cond_acquires(true, lock); | |
| 129 | 136 | |
| 130 | −extern void rt_mutex_unlock(struct rt_mutex *lock); | |
| 137 | +extern void rt_mutex_unlock(struct rt_mutex *lock) | |
| 138 | + __releases(lock); | |
| 131 | 139 | |
| 132 | 140 | #endif |
| @@ -484,6 +484,7 @@ static __always_inline bool __waiter_less(struct rb_node *a, const struct rb_nod · 483 unmodified lines | ||
| 484 | 484 | |
| 485 | 485 | static __always_inline void |
| 486 | 486 | rt_mutex_enqueue(struct rt_mutex_base *lock, struct rt_mutex_waiter *waiter) |
| 487 | + __must_hold(&lock->wait_lock) | |
| 487 | 488 | { |
| 488 | 489 | lockdep_assert_held(&lock->wait_lock); |
| 489 | 490 | |
| @@ -492,6 +493,7 @@ rt_mutex_enqueue(struct rt_mutex_base *lock, struct rt_mutex_waiter *waiter) · 2 unmodified lines | ||
| 492 | 493 | |
| 493 | 494 | static __always_inline void |
| 494 | 495 | rt_mutex_dequeue(struct rt_mutex_base *lock, struct rt_mutex_waiter *waiter) |
| 496 | + __must_hold(&lock->wait_lock) | |
| 495 | 497 | { |
| 496 | 498 | lockdep_assert_held(&lock->wait_lock); |
| 497 | 499 | |
| @@ -1092,6 +1094,7 @@ static int __sched rt_mutex_adjust_prio_chain(struct task_struct *task, · 594 unmodified lines | ||
| 1092 | 1094 | static int __sched |
| 1093 | 1095 | try_to_take_rt_mutex(struct rt_mutex_base *lock, struct task_struct *task, |
| 1094 | 1096 | struct rt_mutex_waiter *waiter) |
| 1097 | + __must_hold(&lock->wait_lock) | |
| 1095 | 1098 | { |
| 1096 | 1099 | lockdep_assert_held(&lock->wait_lock); |
| 1097 | 1100 | |
| @@ -1319,6 +1322,7 @@ static int __sched task_blocks_on_rt_mutex(struct rt_mutex_base *lock, · 221 unmodified lines | ||
| 1319 | 1322 | */ |
| 1320 | 1323 | static void __sched mark_wakeup_next_waiter(struct rt_wake_q_head *wqh, |
| 1321 | 1324 | struct rt_mutex_base *lock) |
| 1325 | + __must_hold(&lock->wait_lock) | |
| 1322 | 1326 | { |
| 1323 | 1327 | struct rt_mutex_waiter *waiter; |
| 1324 | 1328 | |
| @@ -41,6 +41,7 @@ static __always_inline int __rt_mutex_lock_common(struct rt_mutex *lock, · 40 unmodified lines | ||
| 41 | 41 | unsigned int state, |
| 42 | 42 | struct lockdep_map *nest_lock, |
| 43 | 43 | unsigned int subclass) |
| 44 | + __cond_acquires(0, lock) | |
| 44 | 45 | { |
| 45 | 46 | int ret; |
| 46 | 47 | |
| @@ -67,13 +68,27 @@ EXPORT_SYMBOL(rt_mutex_base_init); · 20 unmodified lines | ||
| 67 | 68 | */ |
| 68 | 69 | void __sched rt_mutex_lock_nested(struct rt_mutex *lock, unsigned int subclass) |
| 69 | 70 | { |
| 70 | − __rt_mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, NULL, subclass); | |
| 71 | + if (__rt_mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, NULL, subclass) == 0) | |
| 72 | + return; | |
| 73 | + /* | |
| 74 | + * The code below is never reached because __rt_mutex_lock_common() only | |
| 75 | + * returns an error code if interrupted by a signal or upon a timeout. | |
| 76 | + */ | |
| 77 | + WARN_ON_ONCE(true); | |
| 78 | + __acquire(lock); | |
| 71 | 79 | } |
| 72 | 80 | EXPORT_SYMBOL_GPL(rt_mutex_lock_nested); |
| 73 | 81 | |
| 74 | 82 | void __sched _rt_mutex_lock_nest_lock(struct rt_mutex *lock, struct lockdep_map *nest_lock) |
| 75 | 83 | { |
| 76 | − __rt_mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, nest_lock, 0); | |
| 84 | + if (__rt_mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, nest_lock, 0) == 0) | |
| 85 | + return; | |
| 86 | + /* | |
| 87 | + * The code below is never reached because __rt_mutex_lock_common() only | |
| 88 | + * returns an error code if interrupted by a signal or upon a timeout. | |
| 89 | + */ | |
| 90 | + WARN_ON_ONCE(true); | |
| 91 | + __acquire(lock); | |
| 77 | 92 | } |
| 78 | 93 | EXPORT_SYMBOL_GPL(_rt_mutex_lock_nest_lock); |
| 79 | 94 | |
| @@ -86,7 +101,14 @@ EXPORT_SYMBOL_GPL(_rt_mutex_lock_nest_lock); · 6 unmodified lines | ||
| 86 | 101 | */ |
| 87 | 102 | void __sched rt_mutex_lock(struct rt_mutex *lock) |
| 88 | 103 | { |
| 89 | − __rt_mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, NULL, 0); | |
| 104 | + if (__rt_mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, NULL, 0) == 0) | |
| 105 | + return; | |
| 106 | + /* | |
| 107 | + * The code below is never reached because __rt_mutex_lock_common() only | |
| 108 | + * returns an error code if interrupted by a signal or upon a timeout. | |
| 109 | + */ | |
| 110 | + WARN_ON_ONCE(true); | |
| 111 | + __acquire(lock); | |
| 90 | 112 | } |
| 91 | 113 | EXPORT_SYMBOL_GPL(rt_mutex_lock); |
| 92 | 114 | #endif |
| @@ -157,6 +179,7 @@ void __sched rt_mutex_unlock(struct rt_mutex *lock) · 64 unmodified lines | ||
| 157 | 179 | { |
| 158 | 180 | mutex_release(&lock->dep_map, _RET_IP_); |
| 159 | 181 | __rt_mutex_unlock(&lock->rtmutex); |
| 182 | + __release(lock); | |
| 160 | 183 | } |
| 161 | 184 | EXPORT_SYMBOL_GPL(rt_mutex_unlock); |
| 162 | 185 | |
| @@ -182,6 +205,7 @@ int __sched __rt_mutex_futex_trylock(struct rt_mutex_base *lock) · 19 unmodified lines | ||
| 182 | 205 | */ |
| 183 | 206 | bool __sched __rt_mutex_futex_unlock(struct rt_mutex_base *lock, |
| 184 | 207 | struct rt_wake_q_head *wqh) |
| 208 | + __must_hold(&lock->wait_lock) | |
| 185 | 209 | { |
| 186 | 210 | lockdep_assert_held(&lock->wait_lock); |
| 187 | 211 | |
| @@ -312,6 +336,7 @@ int __sched __rt_mutex_start_proxy_lock(struct rt_mutex_base *lock, · 124 unmodified lines | ||
| 312 | 336 | struct rt_mutex_waiter *waiter, |
| 313 | 337 | struct task_struct *task, |
| 314 | 338 | struct wake_q_head *wake_q) |
| 339 | + __must_hold(&lock->wait_lock) | |
| 315 | 340 | { |
| 316 | 341 | int ret; |
| 317 | 342 | |