diff options
| -rw-r--r-- | include/linux/lockdep.h | 17 | ||||
| -rw-r--r-- | kernel/lockdep.c | 38 | ||||
| -rw-r--r-- | kernel/lockdep_proc.c | 19 | ||||
| -rw-r--r-- | kernel/mutex.c | 2 |
4 files changed, 55 insertions, 21 deletions
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 3d3386b88b6a..0e843bf65877 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h | |||
| @@ -130,12 +130,24 @@ struct lock_time { | |||
| 130 | unsigned long nr; | 130 | unsigned long nr; |
| 131 | }; | 131 | }; |
| 132 | 132 | ||
| 133 | enum bounce_type { | ||
| 134 | bounce_acquired_write, | ||
| 135 | bounce_acquired_read, | ||
| 136 | bounce_contended_write, | ||
| 137 | bounce_contended_read, | ||
| 138 | nr_bounce_types, | ||
| 139 | |||
| 140 | bounce_acquired = bounce_acquired_write, | ||
| 141 | bounce_contended = bounce_contended_write, | ||
| 142 | }; | ||
| 143 | |||
| 133 | struct lock_class_stats { | 144 | struct lock_class_stats { |
| 134 | unsigned long contention_point[4]; | 145 | unsigned long contention_point[4]; |
| 135 | struct lock_time read_waittime; | 146 | struct lock_time read_waittime; |
| 136 | struct lock_time write_waittime; | 147 | struct lock_time write_waittime; |
| 137 | struct lock_time read_holdtime; | 148 | struct lock_time read_holdtime; |
| 138 | struct lock_time write_holdtime; | 149 | struct lock_time write_holdtime; |
| 150 | unsigned long bounces[nr_bounce_types]; | ||
| 139 | }; | 151 | }; |
| 140 | 152 | ||
| 141 | struct lock_class_stats lock_stats(struct lock_class *class); | 153 | struct lock_class_stats lock_stats(struct lock_class *class); |
| @@ -150,6 +162,9 @@ struct lockdep_map { | |||
| 150 | struct lock_class_key *key; | 162 | struct lock_class_key *key; |
| 151 | struct lock_class *class_cache; | 163 | struct lock_class *class_cache; |
| 152 | const char *name; | 164 | const char *name; |
| 165 | #ifdef CONFIG_LOCK_STAT | ||
| 166 | int cpu; | ||
| 167 | #endif | ||
| 153 | }; | 168 | }; |
| 154 | 169 | ||
| 155 | /* | 170 | /* |
| @@ -321,8 +336,8 @@ do { \ | |||
| 321 | if (!try(_lock)) { \ | 336 | if (!try(_lock)) { \ |
| 322 | lock_contended(&(_lock)->dep_map, _RET_IP_); \ | 337 | lock_contended(&(_lock)->dep_map, _RET_IP_); \ |
| 323 | lock(_lock); \ | 338 | lock(_lock); \ |
| 324 | lock_acquired(&(_lock)->dep_map); \ | ||
| 325 | } \ | 339 | } \ |
| 340 | lock_acquired(&(_lock)->dep_map); \ | ||
| 326 | } while (0) | 341 | } while (0) |
| 327 | 342 | ||
| 328 | #else /* CONFIG_LOCK_STAT */ | 343 | #else /* CONFIG_LOCK_STAT */ |
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index cb64022851c8..156fce4960c3 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
| @@ -177,6 +177,9 @@ struct lock_class_stats lock_stats(struct lock_class *class) | |||
| 177 | 177 | ||
| 178 | lock_time_add(&pcs->read_holdtime, &stats.read_holdtime); | 178 | lock_time_add(&pcs->read_holdtime, &stats.read_holdtime); |
| 179 | lock_time_add(&pcs->write_holdtime, &stats.write_holdtime); | 179 | lock_time_add(&pcs->write_holdtime, &stats.write_holdtime); |
| 180 | |||
| 181 | for (i = 0; i < ARRAY_SIZE(stats.bounces); i++) | ||
| 182 | stats.bounces[i] += pcs->bounces[i]; | ||
| 180 | } | 183 | } |
| 181 | 184 | ||
| 182 | return stats; | 185 | return stats; |
| @@ -2325,6 +2328,9 @@ void lockdep_init_map(struct lockdep_map *lock, const char *name, | |||
| 2325 | lock->name = name; | 2328 | lock->name = name; |
| 2326 | lock->key = key; | 2329 | lock->key = key; |
| 2327 | lock->class_cache = NULL; | 2330 | lock->class_cache = NULL; |
| 2331 | #ifdef CONFIG_LOCK_STAT | ||
| 2332 | lock->cpu = raw_smp_processor_id(); | ||
| 2333 | #endif | ||
| 2328 | if (subclass) | 2334 | if (subclass) |
| 2329 | register_lock_class(lock, subclass, 1); | 2335 | register_lock_class(lock, subclass, 1); |
| 2330 | } | 2336 | } |
| @@ -2775,6 +2781,8 @@ found_it: | |||
| 2775 | stats = get_lock_stats(hlock->class); | 2781 | stats = get_lock_stats(hlock->class); |
| 2776 | if (point < ARRAY_SIZE(stats->contention_point)) | 2782 | if (point < ARRAY_SIZE(stats->contention_point)) |
| 2777 | stats->contention_point[i]++; | 2783 | stats->contention_point[i]++; |
| 2784 | if (lock->cpu != smp_processor_id()) | ||
| 2785 | stats->bounces[bounce_contended + !!hlock->read]++; | ||
| 2778 | put_lock_stats(stats); | 2786 | put_lock_stats(stats); |
| 2779 | } | 2787 | } |
| 2780 | 2788 | ||
| @@ -2786,8 +2794,8 @@ __lock_acquired(struct lockdep_map *lock) | |||
| 2786 | struct lock_class_stats *stats; | 2794 | struct lock_class_stats *stats; |
| 2787 | unsigned int depth; | 2795 | unsigned int depth; |
| 2788 | u64 now; | 2796 | u64 now; |
| 2789 | s64 waittime; | 2797 | s64 waittime = 0; |
| 2790 | int i; | 2798 | int i, cpu; |
| 2791 | 2799 | ||
| 2792 | depth = curr->lockdep_depth; | 2800 | depth = curr->lockdep_depth; |
| 2793 | if (DEBUG_LOCKS_WARN_ON(!depth)) | 2801 | if (DEBUG_LOCKS_WARN_ON(!depth)) |
| @@ -2809,19 +2817,25 @@ __lock_acquired(struct lockdep_map *lock) | |||
| 2809 | return; | 2817 | return; |
| 2810 | 2818 | ||
| 2811 | found_it: | 2819 | found_it: |
| 2812 | if (!hlock->waittime_stamp) | 2820 | cpu = smp_processor_id(); |
| 2813 | return; | 2821 | if (hlock->waittime_stamp) { |
| 2814 | 2822 | now = sched_clock(); | |
| 2815 | now = sched_clock(); | 2823 | waittime = now - hlock->waittime_stamp; |
| 2816 | waittime = now - hlock->waittime_stamp; | 2824 | hlock->holdtime_stamp = now; |
| 2817 | hlock->holdtime_stamp = now; | 2825 | } |
| 2818 | 2826 | ||
| 2819 | stats = get_lock_stats(hlock->class); | 2827 | stats = get_lock_stats(hlock->class); |
| 2820 | if (hlock->read) | 2828 | if (waittime) { |
| 2821 | lock_time_inc(&stats->read_waittime, waittime); | 2829 | if (hlock->read) |
| 2822 | else | 2830 | lock_time_inc(&stats->read_waittime, waittime); |
| 2823 | lock_time_inc(&stats->write_waittime, waittime); | 2831 | else |
| 2832 | lock_time_inc(&stats->write_waittime, waittime); | ||
| 2833 | } | ||
| 2834 | if (lock->cpu != cpu) | ||
| 2835 | stats->bounces[bounce_acquired + !!hlock->read]++; | ||
| 2824 | put_lock_stats(stats); | 2836 | put_lock_stats(stats); |
| 2837 | |||
| 2838 | lock->cpu = cpu; | ||
| 2825 | } | 2839 | } |
| 2826 | 2840 | ||
| 2827 | void lock_contended(struct lockdep_map *lock, unsigned long ip) | 2841 | void lock_contended(struct lockdep_map *lock, unsigned long ip) |
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c index 39163ed1bf0a..7ff80135cbeb 100644 --- a/kernel/lockdep_proc.c +++ b/kernel/lockdep_proc.c | |||
| @@ -430,16 +430,18 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data) | |||
| 430 | else | 430 | else |
| 431 | seq_printf(m, "%40s:", name); | 431 | seq_printf(m, "%40s:", name); |
| 432 | 432 | ||
| 433 | seq_printf(m, "%14lu ", stats->bounces[bounce_contended_write]); | ||
| 433 | seq_lock_time(m, &stats->write_waittime); | 434 | seq_lock_time(m, &stats->write_waittime); |
| 434 | seq_puts(m, " "); | 435 | seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_write]); |
| 435 | seq_lock_time(m, &stats->write_holdtime); | 436 | seq_lock_time(m, &stats->write_holdtime); |
| 436 | seq_puts(m, "\n"); | 437 | seq_puts(m, "\n"); |
| 437 | } | 438 | } |
| 438 | 439 | ||
| 439 | if (stats->read_holdtime.nr) { | 440 | if (stats->read_holdtime.nr) { |
| 440 | seq_printf(m, "%38s-R:", name); | 441 | seq_printf(m, "%38s-R:", name); |
| 442 | seq_printf(m, "%14lu ", stats->bounces[bounce_contended_read]); | ||
| 441 | seq_lock_time(m, &stats->read_waittime); | 443 | seq_lock_time(m, &stats->read_waittime); |
| 442 | seq_puts(m, " "); | 444 | seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_read]); |
| 443 | seq_lock_time(m, &stats->read_holdtime); | 445 | seq_lock_time(m, &stats->read_holdtime); |
| 444 | seq_puts(m, "\n"); | 446 | seq_puts(m, "\n"); |
| 445 | } | 447 | } |
| @@ -469,26 +471,29 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data) | |||
| 469 | } | 471 | } |
| 470 | if (i) { | 472 | if (i) { |
| 471 | seq_puts(m, "\n"); | 473 | seq_puts(m, "\n"); |
| 472 | seq_line(m, '.', 0, 40 + 1 + 8 * (14 + 1)); | 474 | seq_line(m, '.', 0, 40 + 1 + 10 * (14 + 1)); |
| 473 | seq_puts(m, "\n"); | 475 | seq_puts(m, "\n"); |
| 474 | } | 476 | } |
| 475 | } | 477 | } |
| 476 | 478 | ||
| 477 | static void seq_header(struct seq_file *m) | 479 | static void seq_header(struct seq_file *m) |
| 478 | { | 480 | { |
| 479 | seq_printf(m, "lock_stat version 0.1\n"); | 481 | seq_printf(m, "lock_stat version 0.2\n"); |
| 480 | seq_line(m, '-', 0, 40 + 1 + 8 * (14 + 1)); | 482 | seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); |
| 481 | seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s\n", | 483 | seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s " |
| 484 | "%14s %14s\n", | ||
| 482 | "class name", | 485 | "class name", |
| 486 | "con-bounces", | ||
| 483 | "contentions", | 487 | "contentions", |
| 484 | "waittime-min", | 488 | "waittime-min", |
| 485 | "waittime-max", | 489 | "waittime-max", |
| 486 | "waittime-total", | 490 | "waittime-total", |
| 491 | "acq-bounces", | ||
| 487 | "acquisitions", | 492 | "acquisitions", |
| 488 | "holdtime-min", | 493 | "holdtime-min", |
| 489 | "holdtime-max", | 494 | "holdtime-max", |
| 490 | "holdtime-total"); | 495 | "holdtime-total"); |
| 491 | seq_line(m, '-', 0, 40 + 1 + 8 * (14 + 1)); | 496 | seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); |
| 492 | seq_printf(m, "\n"); | 497 | seq_printf(m, "\n"); |
| 493 | } | 498 | } |
| 494 | 499 | ||
diff --git a/kernel/mutex.c b/kernel/mutex.c index 7a3f32761f26..691b86564dd9 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c | |||
| @@ -180,8 +180,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass) | |||
| 180 | spin_lock_mutex(&lock->wait_lock, flags); | 180 | spin_lock_mutex(&lock->wait_lock, flags); |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | lock_acquired(&lock->dep_map); | ||
| 184 | done: | 183 | done: |
| 184 | lock_acquired(&lock->dep_map); | ||
| 185 | /* got the lock - rejoice! */ | 185 | /* got the lock - rejoice! */ |
| 186 | mutex_remove_waiter(lock, &waiter, task_thread_info(task)); | 186 | mutex_remove_waiter(lock, &waiter, task_thread_info(task)); |
| 187 | debug_mutex_set_owner(lock, task_thread_info(task)); | 187 | debug_mutex_set_owner(lock, task_thread_info(task)); |
