diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2007-07-19 04:49:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 13:04:49 -0400 |
commit | 96645678cd726e87ce42a0664de71e047e32bca4 (patch) | |
tree | 116f568a090414777b481e8e5d9db55f420e4335 /kernel/lockdep.c | |
parent | 443aef0eddfa44c158d1b94ebb431a70638fcab4 (diff) |
lockstat: measure lock bouncing
__acquire
|
lock _____
| \
| __contended
| |
| wait
| _______/
|/
|
__acquired
|
__release
|
unlock
We measure acquisition and contention bouncing.
This is done by recording a cpu stamp in each lock instance.
Contention bouncing requires the cpu stamp to be set on acquisition. Hence we
move __acquired into the generic path.
__acquired is then used to measure acquisition bouncing by comparing the
current cpu with the old stamp before replacing it.
__contended is used to measure contention bouncing (only useful for preemptable
locks)
[akpm@linux-foundation.org: cleanups]
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/lockdep.c')
-rw-r--r-- | kernel/lockdep.c | 38 |
1 files changed, 26 insertions, 12 deletions
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) |