diff options
author | Davidlohr Bueso <dave@stgolabs.net> | 2017-09-08 19:15:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-08 21:26:49 -0400 |
commit | a23ba907d5e65d6aeea3e59c82fda9cd206a7aad (patch) | |
tree | a0bd42b27596cf758517fa004d1d8681a7eef932 | |
parent | 2161573ecd6931565936cb66793b2d2bf805c088 (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.h | 5 | ||||
-rw-r--r-- | include/linux/rtmutex.h | 11 | ||||
-rw-r--r-- | include/linux/sched.h | 3 | ||||
-rw-r--r-- | kernel/fork.c | 3 | ||||
-rw-r--r-- | kernel/locking/rtmutex-debug.c | 2 | ||||
-rw-r--r-- | kernel/locking/rtmutex.c | 35 | ||||
-rw-r--r-- | kernel/locking/rtmutex_common.h | 12 |
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 | */ |
29 | struct rt_mutex { | 29 | struct 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 | ||
59 | void rt_mutex_debug_task_free(struct task_struct *task) | 59 | void 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, | |||
271 | static void | 271 | static void |
272 | rt_mutex_enqueue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter) | 272 | rt_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 | ||
297 | static void | 294 | static 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 | ||
310 | static void | 304 | static void |
311 | rt_mutex_enqueue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter) | 305 | rt_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 | ||
336 | static void | 327 | static 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 | ||
46 | static inline int rt_mutex_has_waiters(struct rt_mutex *lock) | 46 | static 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 | ||
51 | static inline struct rt_mutex_waiter * | 51 | static 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 | ||
63 | static inline int task_has_pi_waiters(struct task_struct *p) | 63 | static 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 | ||
68 | static inline struct rt_mutex_waiter * | 68 | static inline struct rt_mutex_waiter * |
69 | task_top_pi_waiter(struct task_struct *p) | 69 | task_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 |