summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavidlohr Bueso <dave@stgolabs.net>2017-09-08 19:15:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-08 21:26:49 -0400
commita23ba907d5e65d6aeea3e59c82fda9cd206a7aad (patch)
treea0bd42b27596cf758517fa004d1d8681a7eef932
parent2161573ecd6931565936cb66793b2d2bf805c088 (diff)
locking/rtmutex: replace top-waiter and pi_waiters leftmost caching
... with the generic rbtree flavor instead. No changes in semantics whatsoever. Link: http://lkml.kernel.org/r/20170719014603.19029-10-dave@stgolabs.net Signed-off-by: Davidlohr Bueso <dbueso@suse.de> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/init_task.h5
-rw-r--r--include/linux/rtmutex.h11
-rw-r--r--include/linux/sched.h3
-rw-r--r--kernel/fork.c3
-rw-r--r--kernel/locking/rtmutex-debug.c2
-rw-r--r--kernel/locking/rtmutex.c35
-rw-r--r--kernel/locking/rtmutex_common.h12
7 files changed, 27 insertions, 44 deletions
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 0e849715e5be..3c07ace5b431 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -175,9 +175,8 @@ extern struct cred init_cred;
175 175
176#ifdef CONFIG_RT_MUTEXES 176#ifdef CONFIG_RT_MUTEXES
177# define INIT_RT_MUTEXES(tsk) \ 177# define INIT_RT_MUTEXES(tsk) \
178 .pi_waiters = RB_ROOT, \ 178 .pi_waiters = RB_ROOT_CACHED, \
179 .pi_top_task = NULL, \ 179 .pi_top_task = NULL,
180 .pi_waiters_leftmost = NULL,
181#else 180#else
182# define INIT_RT_MUTEXES(tsk) 181# define INIT_RT_MUTEXES(tsk)
183#endif 182#endif
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h
index 44fd002f7cd5..53fcbe9de7fd 100644
--- a/include/linux/rtmutex.h
+++ b/include/linux/rtmutex.h
@@ -22,18 +22,17 @@ extern int max_lock_depth; /* for sysctl */
22 * The rt_mutex structure 22 * The rt_mutex structure
23 * 23 *
24 * @wait_lock: spinlock to protect the structure 24 * @wait_lock: spinlock to protect the structure
25 * @waiters: rbtree root to enqueue waiters in priority order 25 * @waiters: rbtree root to enqueue waiters in priority order;
26 * @waiters_leftmost: top waiter 26 * caches top-waiter (leftmost node).
27 * @owner: the mutex owner 27 * @owner: the mutex owner
28 */ 28 */
29struct rt_mutex { 29struct rt_mutex {
30 raw_spinlock_t wait_lock; 30 raw_spinlock_t wait_lock;
31 struct rb_root waiters; 31 struct rb_root_cached waiters;
32 struct rb_node *waiters_leftmost;
33 struct task_struct *owner; 32 struct task_struct *owner;
34#ifdef CONFIG_DEBUG_RT_MUTEXES 33#ifdef CONFIG_DEBUG_RT_MUTEXES
35 int save_state; 34 int save_state;
36 const char *name, *file; 35 const char *name, *file;
37 int line; 36 int line;
38 void *magic; 37 void *magic;
39#endif 38#endif
@@ -84,7 +83,7 @@ do { \
84 83
85#define __RT_MUTEX_INITIALIZER(mutexname) \ 84#define __RT_MUTEX_INITIALIZER(mutexname) \
86 { .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \ 85 { .wait_lock = __RAW_SPIN_LOCK_UNLOCKED(mutexname.wait_lock) \
87 , .waiters = RB_ROOT \ 86 , .waiters = RB_ROOT_CACHED \
88 , .owner = NULL \ 87 , .owner = NULL \
89 __DEBUG_RT_MUTEX_INITIALIZER(mutexname) \ 88 __DEBUG_RT_MUTEX_INITIALIZER(mutexname) \
90 __DEP_MAP_RT_MUTEX_INITIALIZER(mutexname)} 89 __DEP_MAP_RT_MUTEX_INITIALIZER(mutexname)}
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 68b38335d33c..92fb8dd5a9e4 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -812,8 +812,7 @@ struct task_struct {
812 812
813#ifdef CONFIG_RT_MUTEXES 813#ifdef CONFIG_RT_MUTEXES
814 /* PI waiters blocked on a rt_mutex held by this task: */ 814 /* PI waiters blocked on a rt_mutex held by this task: */
815 struct rb_root pi_waiters; 815 struct rb_root_cached pi_waiters;
816 struct rb_node *pi_waiters_leftmost;
817 /* Updated under owner's pi_lock and rq lock */ 816 /* Updated under owner's pi_lock and rq lock */
818 struct task_struct *pi_top_task; 817 struct task_struct *pi_top_task;
819 /* Deadlock detection and priority inheritance handling: */ 818 /* Deadlock detection and priority inheritance handling: */
diff --git a/kernel/fork.c b/kernel/fork.c
index 2ccbbbfcb7b8..6f1b0af00bda 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1462,8 +1462,7 @@ static void rt_mutex_init_task(struct task_struct *p)
1462{ 1462{
1463 raw_spin_lock_init(&p->pi_lock); 1463 raw_spin_lock_init(&p->pi_lock);
1464#ifdef CONFIG_RT_MUTEXES 1464#ifdef CONFIG_RT_MUTEXES
1465 p->pi_waiters = RB_ROOT; 1465 p->pi_waiters = RB_ROOT_CACHED;
1466 p->pi_waiters_leftmost = NULL;
1467 p->pi_top_task = NULL; 1466 p->pi_top_task = NULL;
1468 p->pi_blocked_on = NULL; 1467 p->pi_blocked_on = NULL;
1469#endif 1468#endif
diff --git a/kernel/locking/rtmutex-debug.c b/kernel/locking/rtmutex-debug.c
index ac35e648b0e5..f4a74e78d467 100644
--- a/kernel/locking/rtmutex-debug.c
+++ b/kernel/locking/rtmutex-debug.c
@@ -58,7 +58,7 @@ static void printk_lock(struct rt_mutex *lock, int print_owner)
58 58
59void rt_mutex_debug_task_free(struct task_struct *task) 59void rt_mutex_debug_task_free(struct task_struct *task)
60{ 60{
61 DEBUG_LOCKS_WARN_ON(!RB_EMPTY_ROOT(&task->pi_waiters)); 61 DEBUG_LOCKS_WARN_ON(!RB_EMPTY_ROOT(&task->pi_waiters.rb_root));
62 DEBUG_LOCKS_WARN_ON(task->pi_blocked_on); 62 DEBUG_LOCKS_WARN_ON(task->pi_blocked_on);
63} 63}
64 64
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 649dc9d3951a..6f3dba6e4e9e 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -271,10 +271,10 @@ rt_mutex_waiter_equal(struct rt_mutex_waiter *left,
271static void 271static void
272rt_mutex_enqueue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter) 272rt_mutex_enqueue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter)
273{ 273{
274 struct rb_node **link = &lock->waiters.rb_node; 274 struct rb_node **link = &lock->waiters.rb_root.rb_node;
275 struct rb_node *parent = NULL; 275 struct rb_node *parent = NULL;
276 struct rt_mutex_waiter *entry; 276 struct rt_mutex_waiter *entry;
277 int leftmost = 1; 277 bool leftmost = true;
278 278
279 while (*link) { 279 while (*link) {
280 parent = *link; 280 parent = *link;
@@ -283,15 +283,12 @@ rt_mutex_enqueue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter)
283 link = &parent->rb_left; 283 link = &parent->rb_left;
284 } else { 284 } else {
285 link = &parent->rb_right; 285 link = &parent->rb_right;
286 leftmost = 0; 286 leftmost = false;
287 } 287 }
288 } 288 }
289 289
290 if (leftmost)
291 lock->waiters_leftmost = &waiter->tree_entry;
292
293 rb_link_node(&waiter->tree_entry, parent, link); 290 rb_link_node(&waiter->tree_entry, parent, link);
294 rb_insert_color(&waiter->tree_entry, &lock->waiters); 291 rb_insert_color_cached(&waiter->tree_entry, &lock->waiters, leftmost);
295} 292}
296 293
297static void 294static void
@@ -300,20 +297,17 @@ rt_mutex_dequeue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter)
300 if (RB_EMPTY_NODE(&waiter->tree_entry)) 297 if (RB_EMPTY_NODE(&waiter->tree_entry))
301 return; 298 return;
302 299
303 if (lock->waiters_leftmost == &waiter->tree_entry) 300 rb_erase_cached(&waiter->tree_entry, &lock->waiters);
304 lock->waiters_leftmost = rb_next(&waiter->tree_entry);
305
306 rb_erase(&waiter->tree_entry, &lock->waiters);
307 RB_CLEAR_NODE(&waiter->tree_entry); 301 RB_CLEAR_NODE(&waiter->tree_entry);
308} 302}
309 303
310static void 304static void
311rt_mutex_enqueue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter) 305rt_mutex_enqueue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter)
312{ 306{
313 struct rb_node **link = &task->pi_waiters.rb_node; 307 struct rb_node **link = &task->pi_waiters.rb_root.rb_node;
314 struct rb_node *parent = NULL; 308 struct rb_node *parent = NULL;
315 struct rt_mutex_waiter *entry; 309 struct rt_mutex_waiter *entry;
316 int leftmost = 1; 310 bool leftmost = true;
317 311
318 while (*link) { 312 while (*link) {
319 parent = *link; 313 parent = *link;
@@ -322,15 +316,12 @@ rt_mutex_enqueue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter)
322 link = &parent->rb_left; 316 link = &parent->rb_left;
323 } else { 317 } else {
324 link = &parent->rb_right; 318 link = &parent->rb_right;
325 leftmost = 0; 319 leftmost = false;
326 } 320 }
327 } 321 }
328 322
329 if (leftmost)
330 task->pi_waiters_leftmost = &waiter->pi_tree_entry;
331
332 rb_link_node(&waiter->pi_tree_entry, parent, link); 323 rb_link_node(&waiter->pi_tree_entry, parent, link);
333 rb_insert_color(&waiter->pi_tree_entry, &task->pi_waiters); 324 rb_insert_color_cached(&waiter->pi_tree_entry, &task->pi_waiters, leftmost);
334} 325}
335 326
336static void 327static void
@@ -339,10 +330,7 @@ rt_mutex_dequeue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter)
339 if (RB_EMPTY_NODE(&waiter->pi_tree_entry)) 330 if (RB_EMPTY_NODE(&waiter->pi_tree_entry))
340 return; 331 return;
341 332
342 if (task->pi_waiters_leftmost == &waiter->pi_tree_entry) 333 rb_erase_cached(&waiter->pi_tree_entry, &task->pi_waiters);
343 task->pi_waiters_leftmost = rb_next(&waiter->pi_tree_entry);
344
345 rb_erase(&waiter->pi_tree_entry, &task->pi_waiters);
346 RB_CLEAR_NODE(&waiter->pi_tree_entry); 334 RB_CLEAR_NODE(&waiter->pi_tree_entry);
347} 335}
348 336
@@ -1657,8 +1645,7 @@ void __rt_mutex_init(struct rt_mutex *lock, const char *name,
1657{ 1645{
1658 lock->owner = NULL; 1646 lock->owner = NULL;
1659 raw_spin_lock_init(&lock->wait_lock); 1647 raw_spin_lock_init(&lock->wait_lock);
1660 lock->waiters = RB_ROOT; 1648 lock->waiters = RB_ROOT_CACHED;
1661 lock->waiters_leftmost = NULL;
1662 1649
1663 if (name && key) 1650 if (name && key)
1664 debug_rt_mutex_init(lock, name, key); 1651 debug_rt_mutex_init(lock, name, key);
diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h
index 8d039b928d61..7453be0485a5 100644
--- a/kernel/locking/rtmutex_common.h
+++ b/kernel/locking/rtmutex_common.h
@@ -45,7 +45,7 @@ struct rt_mutex_waiter {
45 45
46static inline int rt_mutex_has_waiters(struct rt_mutex *lock) 46static inline int rt_mutex_has_waiters(struct rt_mutex *lock)
47{ 47{
48 return !RB_EMPTY_ROOT(&lock->waiters); 48 return !RB_EMPTY_ROOT(&lock->waiters.rb_root);
49} 49}
50 50
51static inline struct rt_mutex_waiter * 51static inline struct rt_mutex_waiter *
@@ -53,8 +53,8 @@ rt_mutex_top_waiter(struct rt_mutex *lock)
53{ 53{
54 struct rt_mutex_waiter *w; 54 struct rt_mutex_waiter *w;
55 55
56 w = rb_entry(lock->waiters_leftmost, struct rt_mutex_waiter, 56 w = rb_entry(lock->waiters.rb_leftmost,
57 tree_entry); 57 struct rt_mutex_waiter, tree_entry);
58 BUG_ON(w->lock != lock); 58 BUG_ON(w->lock != lock);
59 59
60 return w; 60 return w;
@@ -62,14 +62,14 @@ rt_mutex_top_waiter(struct rt_mutex *lock)
62 62
63static inline int task_has_pi_waiters(struct task_struct *p) 63static inline int task_has_pi_waiters(struct task_struct *p)
64{ 64{
65 return !RB_EMPTY_ROOT(&p->pi_waiters); 65 return !RB_EMPTY_ROOT(&p->pi_waiters.rb_root);
66} 66}
67 67
68static inline struct rt_mutex_waiter * 68static inline struct rt_mutex_waiter *
69task_top_pi_waiter(struct task_struct *p) 69task_top_pi_waiter(struct task_struct *p)
70{ 70{
71 return rb_entry(p->pi_waiters_leftmost, struct rt_mutex_waiter, 71 return rb_entry(p->pi_waiters.rb_leftmost,
72 pi_tree_entry); 72 struct rt_mutex_waiter, pi_tree_entry);
73} 73}
74 74
75#else 75#else