diff options
| author | Peter Zijlstra <peterz@infradead.org> | 2013-10-31 13:14:17 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2013-11-06 01:55:08 -0500 |
| commit | 8eddac3f103736163f49255bcb109edadea167f6 (patch) | |
| tree | cd3161b76bb7a7e2614817d0ba66446676e6b677 /kernel/locking | |
| parent | 01768b42dc97a67b4fb33a2535c49fc1969880df (diff) | |
locking: Move the lockdep code to kernel/locking/
Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/n/tip-wl7s3tta5isufzfguc23et06@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/locking')
| -rw-r--r-- | kernel/locking/Makefile | 6 | ||||
| -rw-r--r-- | kernel/locking/lockdep.c | 4257 | ||||
| -rw-r--r-- | kernel/locking/lockdep_internals.h | 170 | ||||
| -rw-r--r-- | kernel/locking/lockdep_proc.c | 683 | ||||
| -rw-r--r-- | kernel/locking/lockdep_states.h | 9 |
5 files changed, 5125 insertions, 0 deletions
diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile index fe8bd58b22f8..c103599fc1ba 100644 --- a/kernel/locking/Makefile +++ b/kernel/locking/Makefile | |||
| @@ -2,8 +2,14 @@ | |||
| 2 | obj-y += mutex.o | 2 | obj-y += mutex.o |
| 3 | 3 | ||
| 4 | ifdef CONFIG_FUNCTION_TRACER | 4 | ifdef CONFIG_FUNCTION_TRACER |
| 5 | CFLAGS_REMOVE_lockdep.o = -pg | ||
| 6 | CFLAGS_REMOVE_lockdep_proc.o = -pg | ||
| 5 | CFLAGS_REMOVE_mutex-debug.o = -pg | 7 | CFLAGS_REMOVE_mutex-debug.o = -pg |
| 6 | CFLAGS_REMOVE_rtmutex-debug.o = -pg | 8 | CFLAGS_REMOVE_rtmutex-debug.o = -pg |
| 7 | endif | 9 | endif |
| 8 | 10 | ||
| 9 | obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o | 11 | obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o |
| 12 | obj-$(CONFIG_LOCKDEP) += lockdep.o | ||
| 13 | ifeq ($(CONFIG_PROC_FS),y) | ||
| 14 | obj-$(CONFIG_LOCKDEP) += lockdep_proc.o | ||
| 15 | endif | ||
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c new file mode 100644 index 000000000000..4e8e14c34e42 --- /dev/null +++ b/kernel/locking/lockdep.c | |||
| @@ -0,0 +1,4257 @@ | |||
| 1 | /* | ||
| 2 | * kernel/lockdep.c | ||
| 3 | * | ||
| 4 | * Runtime locking correctness validator | ||
| 5 | * | ||
| 6 | * Started by Ingo Molnar: | ||
| 7 | * | ||
| 8 | * Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> | ||
| 9 | * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> | ||
| 10 | * | ||
| 11 | * this code maps all the lock dependencies as they occur in a live kernel | ||
| 12 | * and will warn about the following classes of locking bugs: | ||
| 13 | * | ||
| 14 | * - lock inversion scenarios | ||
| 15 | * - circular lock dependencies | ||
| 16 | * - hardirq/softirq safe/unsafe locking bugs | ||
| 17 | * | ||
| 18 | * Bugs are reported even if the current locking scenario does not cause | ||
| 19 | * any deadlock at this point. | ||
| 20 | * | ||
| 21 | * I.e. if anytime in the past two locks were taken in a different order, | ||
| 22 | * even if it happened for another task, even if those were different | ||
| 23 | * locks (but of the same class as this lock), this code will detect it. | ||
| 24 | * | ||
| 25 | * Thanks to Arjan van de Ven for coming up with the initial idea of | ||
| 26 | * mapping lock dependencies runtime. | ||
| 27 | */ | ||
| 28 | #define DISABLE_BRANCH_PROFILING | ||
| 29 | #include <linux/mutex.h> | ||
| 30 | #include <linux/sched.h> | ||
| 31 | #include <linux/delay.h> | ||
| 32 | #include <linux/module.h> | ||
| 33 | #include <linux/proc_fs.h> | ||
| 34 | #include <linux/seq_file.h> | ||
| 35 | #include <linux/spinlock.h> | ||
| 36 | #include <linux/kallsyms.h> | ||
| 37 | #include <linux/interrupt.h> | ||
| 38 | #include <linux/stacktrace.h> | ||
| 39 | #include <linux/debug_locks.h> | ||
| 40 | #include <linux/irqflags.h> | ||
| 41 | #include <linux/utsname.h> | ||
| 42 | #include <linux/hash.h> | ||
| 43 | #include <linux/ftrace.h> | ||
| 44 | #include <linux/stringify.h> | ||
| 45 | #include <linux/bitops.h> | ||
| 46 | #include <linux/gfp.h> | ||
| 47 | #include <linux/kmemcheck.h> | ||
| 48 | |||
| 49 | #include <asm/sections.h> | ||
| 50 | |||
| 51 | #include "lockdep_internals.h" | ||
| 52 | |||
| 53 | #define CREATE_TRACE_POINTS | ||
| 54 | #include <trace/events/lock.h> | ||
| 55 | |||
| 56 | #ifdef CONFIG_PROVE_LOCKING | ||
| 57 | int prove_locking = 1; | ||
| 58 | module_param(prove_locking, int, 0644); | ||
| 59 | #else | ||
| 60 | #define prove_locking 0 | ||
| 61 | #endif | ||
| 62 | |||
| 63 | #ifdef CONFIG_LOCK_STAT | ||
| 64 | int lock_stat = 1; | ||
| 65 | module_param(lock_stat, int, 0644); | ||
| 66 | #else | ||
| 67 | #define lock_stat 0 | ||
| 68 | #endif | ||
| 69 | |||
| 70 | /* | ||
| 71 | * lockdep_lock: protects the lockdep graph, the hashes and the | ||
| 72 | * class/list/hash allocators. | ||
| 73 | * | ||
| 74 | * This is one of the rare exceptions where it's justified | ||
| 75 | * to use a raw spinlock - we really dont want the spinlock | ||
| 76 | * code to recurse back into the lockdep code... | ||
| 77 | */ | ||
| 78 | static arch_spinlock_t lockdep_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; | ||
| 79 | |||
| 80 | static int graph_lock(void) | ||
| 81 | { | ||
| 82 | arch_spin_lock(&lockdep_lock); | ||
| 83 | /* | ||
| 84 | * Make sure that if another CPU detected a bug while | ||
| 85 | * walking the graph we dont change it (while the other | ||
| 86 | * CPU is busy printing out stuff with the graph lock | ||
| 87 | * dropped already) | ||
| 88 | */ | ||
| 89 | if (!debug_locks) { | ||
| 90 | arch_spin_unlock(&lockdep_lock); | ||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | /* prevent any recursions within lockdep from causing deadlocks */ | ||
| 94 | current->lockdep_recursion++; | ||
| 95 | return 1; | ||
| 96 | } | ||
| 97 | |||
| 98 | static inline int graph_unlock(void) | ||
| 99 | { | ||
| 100 | if (debug_locks && !arch_spin_is_locked(&lockdep_lock)) { | ||
| 101 | /* | ||
| 102 | * The lockdep graph lock isn't locked while we expect it to | ||
| 103 | * be, we're confused now, bye! | ||
| 104 | */ | ||
| 105 | return DEBUG_LOCKS_WARN_ON(1); | ||
| 106 | } | ||
| 107 | |||
| 108 | current->lockdep_recursion--; | ||
| 109 | arch_spin_unlock(&lockdep_lock); | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | /* | ||
| 114 | * Turn lock debugging off and return with 0 if it was off already, | ||
| 115 | * and also release the graph lock: | ||
| 116 | */ | ||
| 117 | static inline int debug_locks_off_graph_unlock(void) | ||
| 118 | { | ||
| 119 | int ret = debug_locks_off(); | ||
| 120 | |||
| 121 | arch_spin_unlock(&lockdep_lock); | ||
| 122 | |||
| 123 | return ret; | ||
| 124 | } | ||
| 125 | |||
| 126 | static int lockdep_initialized; | ||
| 127 | |||
| 128 | unsigned long nr_list_entries; | ||
| 129 | static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES]; | ||
| 130 | |||
| 131 | /* | ||
| 132 | * All data structures here are protected by the global debug_lock. | ||
| 133 | * | ||
| 134 | * Mutex key structs only get allocated, once during bootup, and never | ||
| 135 | * get freed - this significantly simplifies the debugging code. | ||
| 136 | */ | ||
| 137 | unsigned long nr_lock_classes; | ||
| 138 | static struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; | ||
| 139 | |||
| 140 | static inline struct lock_class *hlock_class(struct held_lock *hlock) | ||
| 141 | { | ||
| 142 | if (!hlock->class_idx) { | ||
| 143 | /* | ||
| 144 | * Someone passed in garbage, we give up. | ||
| 145 | */ | ||
| 146 | DEBUG_LOCKS_WARN_ON(1); | ||
| 147 | return NULL; | ||
| 148 | } | ||
| 149 | return lock_classes + hlock->class_idx - 1; | ||
| 150 | } | ||
| 151 | |||
| 152 | #ifdef CONFIG_LOCK_STAT | ||
| 153 | static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], | ||
| 154 | cpu_lock_stats); | ||
| 155 | |||
| 156 | static inline u64 lockstat_clock(void) | ||
| 157 | { | ||
| 158 | return local_clock(); | ||
| 159 | } | ||
| 160 | |||
| 161 | static int lock_point(unsigned long points[], unsigned long ip) | ||
| 162 | { | ||
| 163 | int i; | ||
| 164 | |||
| 165 | for (i = 0; i < LOCKSTAT_POINTS; i++) { | ||
| 166 | if (points[i] == 0) { | ||
| 167 | points[i] = ip; | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | if (points[i] == ip) | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | |||
| 174 | return i; | ||
| 175 | |||
