Messages in this thread Patch in this message | | | From | Yuyang Du <> | Subject | [PATCH 20/28] locking/lockdep: Refactorize check_noncircular and check_redundant | Date | Wed, 24 Apr 2019 18:19:26 +0800 |
| |
These two functions now handle different check results themselves. A new check_path function is added to check whether there is a path in the dependency graph. No functional change.
Signed-off-by: Yuyang Du <duyuyang@gmail.com> --- kernel/locking/lockdep.c | 98 +++++++++++++++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 35 deletions(-)
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index a3138c9..4d42124 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -1681,33 +1681,79 @@ unsigned long lockdep_count_backward_deps(struct lock_class *class) } /* - * Prove that the dependency graph starting at <entry> can not - * lead to <target>. Print an error and return 0 if it does. + * Check that the dependency graph starting at <src> can lead to + * <target> or not. Print an error and return 0 if it does. */ static noinline int -check_noncircular(struct lock_list *root, struct lock_class *target, - struct lock_list **target_entry) +check_path(struct lock_class *target, struct lock_list *src_entry, + struct lock_list **target_entry) { - int result; + int ret; + + ret = __bfs_forwards(src_entry, (void *)target, class_equal, + target_entry); + + if (unlikely(ret < 0)) + print_bfs_bug(ret); + + return ret; +} + +/* + * Prove that the dependency graph starting at <src> can not + * lead to <target>. If it can, there is a circle when adding + * <target> -> <src> dependency. + * + * Print an error and return 0 if it does. + */ +static noinline int +check_noncircular(struct held_lock *src, struct held_lock *target) +{ + int ret; + struct lock_list *uninitialized_var(target_entry); + struct lock_list src_entry = { + .class = hlock_class(src), + .parent = NULL, + }; debug_atomic_inc(nr_cyclic_checks); - result = __bfs_forwards(root, target, class_equal, target_entry); + ret = check_path(hlock_class(target), &src_entry, &target_entry); - return result; + if (unlikely(!ret)) + print_circular_bug(&src_entry, target_entry, src, target); + + return ret; } +/* + * Check that the dependency graph starting at <src> can lead to + * <target> or not. If it can, <src> -> <target> dependency is already + * in the graph. + * + * Print an error and return 2 if it does or 1 if it does not. + */ static noinline int -check_redundant(struct lock_list *root, struct lock_class *target, - struct lock_list **target_entry) +check_redundant(struct held_lock *src, struct held_lock *target) { - int result; + int ret; + struct lock_list *uninitialized_var(target_entry); + struct lock_list src_entry = { + .class = hlock_class(src), + .parent = NULL, + }; debug_atomic_inc(nr_redundant_checks); - result = __bfs_forwards(root, target, class_equal, target_entry); + ret = check_path(hlock_class(target), &src_entry, &target_entry); - return result; + if (!ret) { + debug_atomic_inc(nr_redundant); + ret = 2; + } else if (ret < 0) + ret = 0; + + return ret; } #if defined(CONFIG_TRACE_IRQFLAGS) @@ -2208,9 +2254,7 @@ static inline void inc_chains(void) check_prev_add(struct task_struct *curr, struct held_lock *prev, struct held_lock *next, int distance) { - struct lock_list *uninitialized_var(target_entry); struct lock_list *entry; - struct lock_list this; struct lock_trace trace; int ret; @@ -2242,17 +2286,9 @@ static inline void inc_chains(void) * MAX_CIRCULAR_QUEUE_SIZE) which keeps track of a breadth of nodes * in the graph whose neighbours are to be checked. */ - this.class = hlock_class(next); - this.parent = NULL; - ret = check_noncircular(&this, hlock_class(prev), &target_entry); - if (unlikely(!ret)) { - print_circular_bug(&this, target_entry, next, prev); - return 0; - } - else if (unlikely(ret < 0)) { - print_bfs_bug(ret); + ret = check_noncircular(next, prev); + if (unlikely(ret <= 0)) return 0; - } if (!check_prev_add_irq(curr, prev, next)) return 0; @@ -2286,17 +2322,9 @@ static inline void inc_chains(void) /* * Is the <prev> -> <next> link redundant? */ - this.class = hlock_class(prev); - this.parent = NULL; - ret = check_redundant(&this, hlock_class(next), &target_entry); - if (!ret) { - debug_atomic_inc(nr_redundant); - return 2; - } - if (ret < 0) { - print_bfs_bug(ret); - return 0; - } + ret = check_redundant(prev, next); + if (ret != 1) + return ret; if (!save_trace(&trace)) return 0; -- 1.8.3.1
| |