diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2007-07-19 01:49:00 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 10:04:49 -0700 |
commit | 96645678cd726e87ce42a0664de71e047e32bca4 (patch) | |
tree | 116f568a090414777b481e8e5d9db55f420e4335 /kernel/lockdep.c | |
parent | 443aef0eddfa44c158d1b94ebb431a70638fcab4 (diff) | |
download | linux-96645678cd726e87ce42a0664de71e047e32bca4.tar.gz linux-96645678cd726e87ce42a0664de71e047e32bca4.tar.bz2 linux-96645678cd726e87ce42a0664de71e047e32bca4.zip |
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) lock_time_add(&pcs->read_holdtime, &stats.read_holdtime); lock_time_add(&pcs->write_holdtime, &stats.write_holdtime); + + for (i = 0; i < ARRAY_SIZE(stats.bounces); i++) + stats.bounces[i] += pcs->bounces[i]; } return stats; @@ -2325,6 +2328,9 @@ void lockdep_init_map(struct lockdep_map *lock, const char *name, lock->name = name; lock->key = key; lock->class_cache = NULL; +#ifdef CONFIG_LOCK_STAT + lock->cpu = raw_smp_processor_id(); +#endif if (subclass) register_lock_class(lock, subclass, 1); } @@ -2775,6 +2781,8 @@ found_it: stats = get_lock_stats(hlock->class); if (point < ARRAY_SIZE(stats->contention_point)) stats->contention_point[i]++; + if (lock->cpu != smp_processor_id()) + stats->bounces[bounce_contended + !!hlock->read]++; put_lock_stats(stats); } @@ -2786,8 +2794,8 @@ __lock_acquired(struct lockdep_map *lock) struct lock_class_stats *stats; unsigned int depth; u64 now; - s64 waittime; - int i; + s64 waittime = 0; + int i, cpu; depth = curr->lockdep_depth; if (DEBUG_LOCKS_WARN_ON(!depth)) @@ -2809,19 +2817,25 @@ __lock_acquired(struct lockdep_map *lock) return; found_it: - if (!hlock->waittime_stamp) - return; - - now = sched_clock(); - waittime = now - hlock->waittime_stamp; - hlock->holdtime_stamp = now; + cpu = smp_processor_id(); + if (hlock->waittime_stamp) { + now = sched_clock(); + waittime = now - hlock->waittime_stamp; + hlock->holdtime_stamp = now; + } stats = get_lock_stats(hlock->class); - if (hlock->read) - lock_time_inc(&stats->read_waittime, waittime); - else - lock_time_inc(&stats->write_waittime, waittime); + if (waittime) { + if (hlock->read) + lock_time_inc(&stats->read_waittime, waittime); + else + lock_time_inc(&stats->write_waittime, waittime); + } + if (lock->cpu != cpu) + stats->bounces[bounce_acquired + !!hlock->read]++; put_lock_stats(stats); + + lock->cpu = cpu; } void lock_contended(struct lockdep_map *lock, unsigned long ip) |