1 /* SPDX-License-Identifier: GPL-2.0 */ 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 2 /* 3 * RT Mutexes: blocking mutual exclusion locks 3 * RT Mutexes: blocking mutual exclusion locks with PI support 4 * 4 * 5 * started by Ingo Molnar and Thomas Gleixner: 5 * started by Ingo Molnar and Thomas Gleixner: 6 * 6 * 7 * Copyright (C) 2004-2006 Red Hat, Inc., Ing 7 * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> 8 * Copyright (C) 2006, Timesys Corp., Thomas 8 * Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com> 9 * 9 * 10 * This file contains the private data structu 10 * This file contains the private data structure and API definitions. 11 */ 11 */ 12 12 13 #ifndef __KERNEL_RTMUTEX_COMMON_H 13 #ifndef __KERNEL_RTMUTEX_COMMON_H 14 #define __KERNEL_RTMUTEX_COMMON_H 14 #define __KERNEL_RTMUTEX_COMMON_H 15 15 16 #include <linux/debug_locks.h> 16 #include <linux/debug_locks.h> 17 #include <linux/rtmutex.h> 17 #include <linux/rtmutex.h> 18 #include <linux/sched/wake_q.h> 18 #include <linux/sched/wake_q.h> 19 19 20 << 21 /* << 22 * This is a helper for the struct rt_mutex_wa << 23 * separate trees and they need their own copy << 24 * different locking requirements. << 25 * << 26 * @entry: rbtree node to enqueue << 27 * @prio: Priority of the waiter << 28 * @deadline: Deadline of the waiter << 29 * << 30 * See rt_waiter_node_less() and waiter_*_prio << 31 */ << 32 struct rt_waiter_node { << 33 struct rb_node entry; << 34 int prio; << 35 u64 deadline; << 36 }; << 37 << 38 /* 20 /* 39 * This is the control structure for tasks blo 21 * This is the control structure for tasks blocked on a rt_mutex, 40 * which is allocated on the kernel stack on o 22 * which is allocated on the kernel stack on of the blocked task. 41 * 23 * 42 * @tree: node to enqueue into t !! 24 * @tree_entry: pi node to enqueue into the mutex waiters tree 43 * @pi_tree: node to enqueue into t !! 25 * @pi_tree_entry: pi node to enqueue into the mutex owner waiters tree 44 * @task: task reference to the 26 * @task: task reference to the blocked task 45 * @lock: Pointer to the rt_mute 27 * @lock: Pointer to the rt_mutex on which the waiter blocks 46 * @wake_state: Wakeup state to use (T !! 28 * @prio: Priority of the waiter 47 * @ww_ctx: WW context pointer !! 29 * @deadline: Deadline of the waiter if applicable 48 * << 49 * @tree is ordered by @lock->wait_lock << 50 * @pi_tree is ordered by rt_mutex_owner(@lock << 51 */ 30 */ 52 struct rt_mutex_waiter { 31 struct rt_mutex_waiter { 53 struct rt_waiter_node tree; !! 32 struct rb_node tree_entry; 54 struct rt_waiter_node pi_tree; !! 33 struct rb_node pi_tree_entry; 55 struct task_struct *task; 34 struct task_struct *task; 56 struct rt_mutex_base *lock; !! 35 struct rt_mutex *lock; 57 unsigned int wake_state; !! 36 int prio; 58 struct ww_acquire_ctx *ww_ctx; !! 37 u64 deadline; 59 }; << 60 << 61 /** << 62 * rt_wake_q_head - Wrapper around regular wak << 63 * "sleeping" spinlocks on RT << 64 * @head: The regular wake_q_hea << 65 * @rtlock_task: Task pointer for RT lo << 66 */ << 67 struct rt_wake_q_head { << 68 struct wake_q_head head; << 69 struct task_struct *rtlock_task; << 70 }; 38 }; 71 39 72 #define DEFINE_RT_WAKE_Q(name) << 73 struct rt_wake_q_head name = { << 74 .head = WAKE_Q_HEAD_ << 75 .rtlock_task = NULL, << 76 } << 77 << 78 /* << 79 * PI-futex support (proxy locking functions, << 80 */ << 81 extern void rt_mutex_init_proxy_locked(struct << 82 struct << 83 extern void rt_mutex_proxy_unlock(struct rt_mu << 84 extern int __rt_mutex_start_proxy_lock(struct << 85 struct rt << 86 struct ta << 87 extern int rt_mutex_start_proxy_lock(struct rt << 88 struct rt << 89 struct ta << 90 extern int rt_mutex_wait_proxy_lock(struct rt_ << 91 struct hrtimer_ << 92 struct rt_mutex << 93 extern bool rt_mutex_cleanup_proxy_lock(struct << 94 struct rt_mut << 95 << 96 extern int rt_mutex_futex_trylock(struct rt_mu << 97 extern int __rt_mutex_futex_trylock(struct rt_ << 98 << 99 extern void rt_mutex_futex_unlock(struct rt_mu << 100 extern bool __rt_mutex_futex_unlock(struct rt_ << 101 struct rt_wake << 102 << 103 extern void rt_mutex_postunlock(struct rt_wake << 104 << 105 /* 40 /* 106 * Must be guarded because this header is incl 41 * Must be guarded because this header is included from rcu/tree_plugin.h 107 * unconditionally. 42 * unconditionally. 108 */ 43 */ 109 #ifdef CONFIG_RT_MUTEXES 44 #ifdef CONFIG_RT_MUTEXES 110 static inline int rt_mutex_has_waiters(struct !! 45 static inline int rt_mutex_has_waiters(struct rt_mutex *lock) 111 { 46 { 112 return !RB_EMPTY_ROOT(&lock->waiters.r 47 return !RB_EMPTY_ROOT(&lock->waiters.rb_root); 113 } 48 } 114 49 115 /* !! 50 static inline struct rt_mutex_waiter *rt_mutex_top_waiter(struct rt_mutex *lock) 116 * Lockless speculative check whether @waiter << 117 * @lock. This is solely comparing pointers an << 118 * leftmost entry which might be about to vani << 119 */ << 120 static inline bool rt_mutex_waiter_is_top_wait << 121 << 122 { << 123 struct rb_node *leftmost = rb_first_ca << 124 << 125 return rb_entry(leftmost, struct rt_mu << 126 } << 127 << 128 static inline struct rt_mutex_waiter *rt_mutex << 129 { 51 { 130 struct rb_node *leftmost = rb_first_ca 52 struct rb_node *leftmost = rb_first_cached(&lock->waiters); 131 struct rt_mutex_waiter *w = NULL; 53 struct rt_mutex_waiter *w = NULL; 132 54 133 lockdep_assert_held(&lock->wait_lock); << 134 << 135 if (leftmost) { 55 if (leftmost) { 136 w = rb_entry(leftmost, struct !! 56 w = rb_entry(leftmost, struct rt_mutex_waiter, tree_entry); 137 BUG_ON(w->lock != lock); 57 BUG_ON(w->lock != lock); 138 } 58 } 139 return w; 59 return w; 140 } 60 } 141 61 142 static inline int task_has_pi_waiters(struct t 62 static inline int task_has_pi_waiters(struct task_struct *p) 143 { 63 { 144 return !RB_EMPTY_ROOT(&p->pi_waiters.r 64 return !RB_EMPTY_ROOT(&p->pi_waiters.rb_root); 145 } 65 } 146 66 147 static inline struct rt_mutex_waiter *task_top 67 static inline struct rt_mutex_waiter *task_top_pi_waiter(struct task_struct *p) 148 { 68 { 149 lockdep_assert_held(&p->pi_lock); << 150 << 151 return rb_entry(p->pi_waiters.rb_leftm 69 return rb_entry(p->pi_waiters.rb_leftmost, struct rt_mutex_waiter, 152 pi_tree.entry); !! 70 pi_tree_entry); 153 } 71 } 154 72 155 #define RT_MUTEX_HAS_WAITERS 1UL 73 #define RT_MUTEX_HAS_WAITERS 1UL 156 74 157 static inline struct task_struct *rt_mutex_own !! 75 static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock) 158 { 76 { 159 unsigned long owner = (unsigned long) 77 unsigned long owner = (unsigned long) READ_ONCE(lock->owner); 160 78 161 return (struct task_struct *) (owner & 79 return (struct task_struct *) (owner & ~RT_MUTEX_HAS_WAITERS); 162 } 80 } >> 81 #else /* CONFIG_RT_MUTEXES */ >> 82 /* Used in rcu/tree_plugin.h */ >> 83 static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock) >> 84 { >> 85 return NULL; >> 86 } >> 87 #endif /* !CONFIG_RT_MUTEXES */ 163 88 164 /* 89 /* 165 * Constants for rt mutex functions which have 90 * Constants for rt mutex functions which have a selectable deadlock 166 * detection. 91 * detection. 167 * 92 * 168 * RT_MUTEX_MIN_CHAINWALK: Stops the lock 93 * RT_MUTEX_MIN_CHAINWALK: Stops the lock chain walk when there are 169 * no further PI 94 * no further PI adjustments to be made. 170 * 95 * 171 * RT_MUTEX_FULL_CHAINWALK: Invoke deadloc 96 * RT_MUTEX_FULL_CHAINWALK: Invoke deadlock detection with a full 172 * walk of the lo 97 * walk of the lock chain. 173 */ 98 */ 174 enum rtmutex_chainwalk { 99 enum rtmutex_chainwalk { 175 RT_MUTEX_MIN_CHAINWALK, 100 RT_MUTEX_MIN_CHAINWALK, 176 RT_MUTEX_FULL_CHAINWALK, 101 RT_MUTEX_FULL_CHAINWALK, 177 }; 102 }; 178 103 179 static inline void __rt_mutex_base_init(struct !! 104 static inline void __rt_mutex_basic_init(struct rt_mutex *lock) 180 { 105 { >> 106 lock->owner = NULL; 181 raw_spin_lock_init(&lock->wait_lock); 107 raw_spin_lock_init(&lock->wait_lock); 182 lock->waiters = RB_ROOT_CACHED; 108 lock->waiters = RB_ROOT_CACHED; 183 lock->owner = NULL; << 184 } 109 } 185 110 >> 111 /* >> 112 * PI-futex support (proxy locking functions, etc.): >> 113 */ >> 114 extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock, >> 115 struct task_struct *proxy_owner); >> 116 extern void rt_mutex_proxy_unlock(struct rt_mutex *lock); >> 117 extern void rt_mutex_init_waiter(struct rt_mutex_waiter *waiter); >> 118 extern int __rt_mutex_start_proxy_lock(struct rt_mutex *lock, >> 119 struct rt_mutex_waiter *waiter, >> 120 struct task_struct *task); >> 121 extern int rt_mutex_start_proxy_lock(struct rt_mutex *lock, >> 122 struct rt_mutex_waiter *waiter, >> 123 struct task_struct *task); >> 124 extern int rt_mutex_wait_proxy_lock(struct rt_mutex *lock, >> 125 struct hrtimer_sleeper *to, >> 126 struct rt_mutex_waiter *waiter); >> 127 extern bool rt_mutex_cleanup_proxy_lock(struct rt_mutex *lock, >> 128 struct rt_mutex_waiter *waiter); >> 129 >> 130 extern int rt_mutex_futex_trylock(struct rt_mutex *l); >> 131 extern int __rt_mutex_futex_trylock(struct rt_mutex *l); >> 132 >> 133 extern void rt_mutex_futex_unlock(struct rt_mutex *lock); >> 134 extern bool __rt_mutex_futex_unlock(struct rt_mutex *lock, >> 135 struct wake_q_head *wqh); >> 136 >> 137 extern void rt_mutex_postunlock(struct wake_q_head *wake_q); >> 138 186 /* Debug functions */ 139 /* Debug functions */ 187 static inline void debug_rt_mutex_unlock(struc !! 140 static inline void debug_rt_mutex_unlock(struct rt_mutex *lock) 188 { 141 { 189 if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEXES 142 if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEXES)) 190 DEBUG_LOCKS_WARN_ON(rt_mutex_o 143 DEBUG_LOCKS_WARN_ON(rt_mutex_owner(lock) != current); 191 } 144 } 192 145 193 static inline void debug_rt_mutex_proxy_unlock !! 146 static inline void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock) 194 { 147 { 195 if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEXES 148 if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEXES)) 196 DEBUG_LOCKS_WARN_ON(!rt_mutex_ 149 DEBUG_LOCKS_WARN_ON(!rt_mutex_owner(lock)); 197 } 150 } 198 151 199 static inline void debug_rt_mutex_init_waiter( 152 static inline void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter) 200 { 153 { 201 if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEXES 154 if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEXES)) 202 memset(waiter, 0x11, sizeof(*w 155 memset(waiter, 0x11, sizeof(*waiter)); 203 } 156 } 204 157 205 static inline void debug_rt_mutex_free_waiter( 158 static inline void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter) 206 { 159 { 207 if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEXES 160 if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEXES)) 208 memset(waiter, 0x22, sizeof(*w 161 memset(waiter, 0x22, sizeof(*waiter)); 209 } 162 } 210 << 211 static inline void rt_mutex_init_waiter(struct << 212 { << 213 debug_rt_mutex_init_waiter(waiter); << 214 RB_CLEAR_NODE(&waiter->pi_tree.entry); << 215 RB_CLEAR_NODE(&waiter->tree.entry); << 216 waiter->wake_state = TASK_NORMAL; << 217 waiter->task = NULL; << 218 } << 219 << 220 static inline void rt_mutex_init_rtlock_waiter << 221 { << 222 rt_mutex_init_waiter(waiter); << 223 waiter->wake_state = TASK_RTLOCK_WAIT; << 224 } << 225 << 226 #else /* CONFIG_RT_MUTEXES */ << 227 /* Used in rcu/tree_plugin.h */ << 228 static inline struct task_struct *rt_mutex_own << 229 { << 230 return NULL; << 231 } << 232 #endif /* !CONFIG_RT_MUTEXES */ << 233 163 234 #endif 164 #endif 235 165
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.