diff options
Diffstat (limited to 'kernel/lockdep.c')
-rw-r--r-- | kernel/lockdep.c | 60 |
1 files changed, 32 insertions, 28 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 46a404173db2..4fa6eeb4e8a7 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -136,16 +136,16 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock) | |||
136 | #ifdef CONFIG_LOCK_STAT | 136 | #ifdef CONFIG_LOCK_STAT |
137 | static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], lock_stats); | 137 | static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], lock_stats); |
138 | 138 | ||
139 | static int lock_contention_point(struct lock_class *class, unsigned long ip) | 139 | static int lock_point(unsigned long points[], unsigned long ip) |
140 | { | 140 | { |
141 | int i; | 141 | int i; |
142 | 142 | ||
143 | for (i = 0; i < ARRAY_SIZE(class->contention_point); i++) { | 143 | for (i = 0; i < LOCKSTAT_POINTS; i++) { |
144 | if (class->contention_point[i] == 0) { | 144 | if (points[i] == 0) { |
145 | class->contention_point[i] = ip; | 145 | points[i] = ip; |
146 | break; | 146 | break; |
147 | } | 147 | } |
148 | if (class->contention_point[i] == ip) | 148 | if (points[i] == ip) |
149 | break; | 149 | break; |
150 | } | 150 | } |
151 | 151 | ||
@@ -185,6 +185,9 @@ struct lock_class_stats lock_stats(struct lock_class *class) | |||
185 | for (i = 0; i < ARRAY_SIZE(stats.contention_point); i++) | 185 | for (i = 0; i < ARRAY_SIZE(stats.contention_point); i++) |
186 | stats.contention_point[i] += pcs->contention_point[i]; | 186 | stats.contention_point[i] += pcs->contention_point[i]; |
187 | 187 | ||
188 | for (i = 0; i < ARRAY_SIZE(stats.contending_point); i++) | ||
189 | stats.contending_point[i] += pcs->contending_point[i]; | ||
190 | |||
188 | lock_time_add(&pcs->read_waittime, &stats.read_waittime); | 191 | lock_time_add(&pcs->read_waittime, &stats.read_waittime); |
189 | lock_time_add(&pcs->write_waittime, &stats.write_waittime); | 192 | lock_time_add(&pcs->write_waittime, &stats.write_waittime); |
190 | 193 | ||
@@ -209,6 +212,7 @@ void clear_lock_stats(struct lock_class *class) | |||
209 | memset(cpu_stats, 0, sizeof(struct lock_class_stats)); | 212 | memset(cpu_stats, 0, sizeof(struct lock_class_stats)); |
210 | } | 213 | } |
211 | memset(class->contention_point, 0, sizeof(class->contention_point)); | 214 | memset(class->contention_point, 0, sizeof(class->contention_point)); |
215 | memset(class->contending_point, 0, sizeof(class->contending_point)); | ||
212 | } | 216 | } |
213 | 217 | ||
214 | static struct lock_class_stats *get_lock_stats(struct lock_class *class) | 218 | static struct lock_class_stats *get_lock_stats(struct lock_class *class) |
@@ -287,14 +291,12 @@ void lockdep_off(void) | |||
287 | { | 291 | { |
288 | current->lockdep_recursion++; | 292 | current->lockdep_recursion++; |
289 | } | 293 | } |
290 | |||
291 | EXPORT_SYMBOL(lockdep_off); | 294 | EXPORT_SYMBOL(lockdep_off); |
292 | 295 | ||
293 | void lockdep_on(void) | 296 | void lockdep_on(void) |
294 | { | 297 | { |
295 | current->lockdep_recursion--; | 298 | current->lockdep_recursion--; |
296 | } | 299 | } |
297 | |||
298 | EXPORT_SYMBOL(lockdep_on); | 300 | EXPORT_SYMBOL(lockdep_on); |
299 | 301 | ||
300 | /* | 302 | /* |
@@ -576,7 +578,8 @@ static void print_lock_class_header(struct lock_class *class, int depth) | |||
576 | /* | 578 | /* |
577 | * printk all lock dependencies starting at <entry>: | 579 | * printk all lock dependencies starting at <entry>: |
578 | */ | 580 | */ |
579 | static void print_lock_dependencies(struct lock_class *class, int depth) | 581 | static void __used |
582 | print_lock_dependencies(struct lock_class *class, int depth) | ||
580 | { | 583 | { |
581 | struct lock_list *entry; | 584 | struct lock_list *entry; |
582 | 585 | ||
@@ -2508,7 +2511,6 @@ void lockdep_init_map(struct lockdep_map *lock, const char *name, | |||
2508 | if (subclass) | 2511 | if (subclass) |
2509 | register_lock_class(lock, subclass, 1); | 2512 | register_lock_class(lock, subclass, 1); |
2510 | } | 2513 | } |
2511 | |||
2512 | EXPORT_SYMBOL_GPL(lockdep_init_map); | 2514 | EXPORT_SYMBOL_GPL(lockdep_init_map); |
2513 | 2515 | ||
2514 | /* | 2516 | /* |
@@ -2689,8 +2691,9 @@ static int check_unlock(struct task_struct *curr, struct lockdep_map *lock, | |||
2689 | } | 2691 | } |
2690 | 2692 | ||
2691 | static int | 2693 | static int |
2692 | __lock_set_subclass(struct lockdep_map *lock, | 2694 | __lock_set_class(struct lockdep_map *lock, const char *name, |
2693 | unsigned int subclass, unsigned long ip) | 2695 | struct lock_class_key *key, unsigned int subclass, |
2696 | unsigned long ip) | ||
2694 | { | 2697 | { |
2695 | struct task_struct *curr = current; | 2698 | struct task_struct *curr = current; |
2696 | struct held_lock *hlock, *prev_hlock; | 2699 | struct held_lock *hlock, *prev_hlock; |
@@ -2717,6 +2720,7 @@ __lock_set_subclass(struct lockdep_map *lock, | |||
2717 | return print_unlock_inbalance_bug(curr, lock, ip); | 2720 | return print_unlock_inbalance_bug(curr, lock, ip); |
2718 | 2721 | ||
2719 | found_it: | 2722 | found_it: |
2723 | lockdep_init_map(lock, name, key, 0); | ||
2720 | class = register_lock_class(lock, subclass, 0); | 2724 | class = register_lock_class(lock, subclass, 0); |
2721 | hlock->class_idx = class - lock_classes + 1; | 2725 | hlock->class_idx = class - lock_classes + 1; |
2722 | 2726 | ||
@@ -2901,9 +2905,9 @@ static void check_flags(unsigned long flags) | |||
2901 | #endif | 2905 | #endif |
2902 | } | 2906 | } |
2903 | 2907 | ||
2904 | void | 2908 | void lock_set_class(struct lockdep_map *lock, const char *name, |
2905 | lock_set_subclass(struct lockdep_map *lock, | 2909 | struct lock_class_key *key, unsigned int subclass, |
2906 | unsigned int subclass, unsigned long ip) | 2910 | unsigned long ip) |
2907 | { | 2911 | { |
2908 | unsigned long flags; | 2912 | unsigned long flags; |
2909 | 2913 | ||
@@ -2913,13 +2917,12 @@ lock_set_subclass(struct lockdep_map *lock, | |||
2913 | raw_local_irq_save(flags); | 2917 | raw_local_irq_save(flags); |
2914 | current->lockdep_recursion = 1; | 2918 | current->lockdep_recursion = 1; |
2915 | check_flags(flags); | 2919 | check_flags(flags); |
2916 | if (__lock_set_subclass(lock, subclass, ip)) | 2920 | if (__lock_set_class(lock, name, key, subclass, ip)) |
2917 | check_chain_key(current); | 2921 | check_chain_key(current); |
2918 | current->lockdep_recursion = 0; | 2922 | current->lockdep_recursion = 0; |
2919 | raw_local_irq_restore(flags); | 2923 | raw_local_irq_restore(flags); |
2920 | } | 2924 | } |
2921 | 2925 | EXPORT_SYMBOL_GPL(lock_set_class); | |
2922 | EXPORT_SYMBOL_GPL(lock_set_subclass); | ||
2923 | 2926 | ||
2924 | /* | 2927 | /* |
2925 | * We are not always called with irqs disabled - do that here, | 2928 | * We are not always called with irqs disabled - do that here, |
@@ -2943,7 +2946,6 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass, | |||
2943 | current->lockdep_recursion = 0; | 2946 | current->lockdep_recursion = 0; |
2944 | raw_local_irq_restore(flags); | 2947 | raw_local_irq_restore(flags); |
2945 | } | 2948 | } |
2946 | |||
2947 | EXPORT_SYMBOL_GPL(lock_acquire); | 2949 | EXPORT_SYMBOL_GPL(lock_acquire); |
2948 | 2950 | ||
2949 | void lock_release(struct lockdep_map *lock, int nested, | 2951 | void lock_release(struct lockdep_map *lock, int nested, |
@@ -2961,7 +2963,6 @@ void lock_release(struct lockdep_map *lock, int nested, | |||
2961 | current->lockdep_recursion = 0; | 2963 | current->lockdep_recursion = 0; |
2962 | raw_local_irq_restore(flags); | 2964 | raw_local_irq_restore(flags); |
2963 | } | 2965 | } |
2964 | |||
2965 | EXPORT_SYMBOL_GPL(lock_release); | 2966 | EXPORT_SYMBOL_GPL(lock_release); |
2966 | 2967 | ||
2967 | #ifdef CONFIG_LOCK_STAT | 2968 | #ifdef CONFIG_LOCK_STAT |
@@ -2999,7 +3000,7 @@ __lock_contended(struct lockdep_map *lock, unsigned long ip) | |||
2999 | struct held_lock *hlock, *prev_hlock; | 3000 | struct held_lock *hlock, *prev_hlock; |
3000 | struct lock_class_stats *stats; | 3001 | struct lock_class_stats *stats; |
3001 | unsigned int depth; | 3002 | unsigned int depth; |
3002 | int i, point; | 3003 | int i, contention_point, contending_point; |
3003 | 3004 | ||
3004 | depth = curr->lockdep_depth; | 3005 | depth = curr->lockdep_depth; |
3005 | if (DEBUG_LOCKS_WARN_ON(!depth)) | 3006 | if (DEBUG_LOCKS_WARN_ON(!depth)) |
@@ -3023,18 +3024,22 @@ __lock_contended(struct lockdep_map *lock, unsigned long ip) | |||
3023 | found_it: | 3024 | found_it: |
3024 | hlock->waittime_stamp = sched_clock(); | 3025 | hlock->waittime_stamp = sched_clock(); |
3025 | 3026 | ||
3026 | point = lock_contention_point(hlock_class(hlock), ip); | 3027 | contention_point = lock_point(hlock_class(hlock)->contention_point, ip); |
3028 | contending_point = lock_point(hlock_class(hlock)->contending_point, | ||
3029 | lock->ip); | ||
3027 | 3030 | ||
3028 | stats = get_lock_stats(hlock_class(hlock)); | 3031 | stats = get_lock_stats(hlock_class(hlock)); |
3029 | if (point < ARRAY_SIZE(stats->contention_point)) | 3032 | if (contention_point < LOCKSTAT_POINTS) |
3030 | stats->contention_point[point]++; | 3033 | stats->contention_point[contention_point]++; |
3034 | if (contending_point < LOCKSTAT_POINTS) | ||
3035 | stats->contending_point[contending_point]++; | ||
3031 | if (lock->cpu != smp_processor_id()) | 3036 | if (lock->cpu != smp_processor_id()) |
3032 | stats->bounces[bounce_contended + !!hlock->read]++; | 3037 | stats->bounces[bounce_contended + !!hlock->read]++; |
3033 | put_lock_stats(stats); | 3038 | put_lock_stats(stats); |
3034 | } | 3039 | } |
3035 | 3040 | ||
3036 | static void | 3041 | static void |
3037 | __lock_acquired(struct lockdep_map *lock) | 3042 | __lock_acquired(struct lockdep_map *lock, unsigned long ip) |
3038 | { | 3043 | { |
3039 | struct task_struct *curr = current; | 3044 | struct task_struct *curr = current; |
3040 | struct held_lock *hlock, *prev_hlock; | 3045 | struct held_lock *hlock, *prev_hlock; |
@@ -3083,6 +3088,7 @@ found_it: | |||
3083 | put_lock_stats(stats); | 3088 | put_lock_stats(stats); |
3084 | 3089 | ||
3085 | lock->cpu = cpu; | 3090 | lock->cpu = cpu; |
3091 | lock->ip = ip; | ||
3086 | } | 3092 | } |
3087 | 3093 | ||
3088 | void lock_contended(struct lockdep_map *lock, unsigned long ip) | 3094 | void lock_contended(struct lockdep_map *lock, unsigned long ip) |
@@ -3104,7 +3110,7 @@ void lock_contended(struct lockdep_map *lock, unsigned long ip) | |||
3104 | } | 3110 | } |
3105 | EXPORT_SYMBOL_GPL(lock_contended); | 3111 | EXPORT_SYMBOL_GPL(lock_contended); |
3106 | 3112 | ||
3107 | void lock_acquired(struct lockdep_map *lock) | 3113 | void lock_acquired(struct lockdep_map *lock, unsigned long ip) |
3108 | { | 3114 | { |
3109 | unsigned long flags; | 3115 | unsigned long flags; |
3110 | 3116 | ||
@@ -3117,7 +3123,7 @@ void lock_acquired(struct lockdep_map *lock) | |||
3117 | raw_local_irq_save(flags); | 3123 | raw_local_irq_save(flags); |
3118 | check_flags(flags); | 3124 | check_flags(flags); |
3119 | current->lockdep_recursion = 1; | 3125 | current->lockdep_recursion = 1; |
3120 | __lock_acquired(lock); | 3126 | __lock_acquired(lock, ip); |
3121 | current->lockdep_recursion = 0; | 3127 | current->lockdep_recursion = 0; |
3122 | raw_local_irq_restore(flags); | 3128 | raw_local_irq_restore(flags); |
3123 | } | 3129 | } |
@@ -3441,7 +3447,6 @@ retry: | |||
3441 | if (unlock) | 3447 | if (unlock) |
3442 | read_unlock(&tasklist_lock); | 3448 | read_unlock(&tasklist_lock); |
3443 | } | 3449 | } |
3444 | |||
3445 | EXPORT_SYMBOL_GPL(debug_show_all_locks); | 3450 | EXPORT_SYMBOL_GPL(debug_show_all_locks); |
3446 | 3451 | ||
3447 | /* | 3452 | /* |
@@ -3462,7 +3467,6 @@ void debug_show_held_locks(struct task_struct *task) | |||
3462 | { | 3467 | { |
3463 | __debug_show_held_locks(task); | 3468 | __debug_show_held_locks(task); |
3464 | } | 3469 | } |
3465 | |||
3466 | EXPORT_SYMBOL_GPL(debug_show_held_locks); | 3470 | EXPORT_SYMBOL_GPL(debug_show_held_locks); |
3467 | 3471 | ||
3468 | void lockdep_sys_exit(void) | 3472 | void lockdep_sys_exit(void) |