aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2007-07-19 04:48:56 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:49 -0400
commitf20786ff4da51e56b1956acf30be2552be266746 (patch)
treef6d0a9ed84ca476ca19fe7131d842699881756c4 /include/linux
parent8e18257d29238311e82085152741f0c3aa18b74d (diff)
lockstat: core infrastructure
Introduce the core lock statistics code. Lock statistics provides lock wait-time and hold-time (as well as the count of corresponding contention and acquisitions events). Also, the first few call-sites that encounter contention are tracked. Lock wait-time is the time spent waiting on the lock. This provides insight into the locking scheme, that is, a heavily contended lock is indicative of a too coarse locking scheme. Lock hold-time is the duration the lock was held, this provides a reference for the wait-time numbers, so they can be put into perspective. 1) lock 2) ... do stuff .. unlock 3) The time between 1 and 2 is the wait-time. The time between 2 and 3 is the hold-time. The lockdep held-lock tracking code is reused, because it already collects locks into meaningful groups (classes), and because it is an existing infrastructure for lock instrumentation. Currently lockdep tracks lock acquisition with two hooks: lock() lock_acquire() _lock() ... code protected by lock ... unlock() lock_release() _unlock() We need to extend this with two more hooks, in order to measure contention. lock_contended() - used to measure contention events lock_acquired() - completion of the contention These are then placed the following way: lock() lock_acquire() if (!_try_lock()) lock_contended() _lock() lock_acquired() ... do locked stuff ... unlock() lock_release() _unlock() (Note: the try_lock() 'trick' is used to avoid instrumenting all platform dependent lock primitive implementations.) It is also possible to toggle the two lockdep features at runtime using: /proc/sys/kernel/prove_locking /proc/sys/kernel/lock_stat (esp. turning off the O(n^2) prove_locking functionaliy can help) [akpm@linux-foundation.org: build fixes] [akpm@linux-foundation.org: nuke unneeded ifdefs] Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Ingo Molnar <mingo@elte.hu> Acked-by: Jason Baron <jbaron@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/lockdep.h53
1 files changed, 53 insertions, 0 deletions
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 14c937d345cb..8f946f614f8e 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -9,6 +9,7 @@
9#define __LINUX_LOCKDEP_H 9#define __LINUX_LOCKDEP_H
10 10
11struct task_struct; 11struct task_struct;
12struct lockdep_map;
12 13
13#ifdef CONFIG_LOCKDEP 14#ifdef CONFIG_LOCKDEP
14 15
@@ -114,8 +115,32 @@ struct lock_class {
114 115
115 const char *name; 116 const char *name;
116 int name_version; 117 int name_version;
118
119#ifdef CONFIG_LOCK_STAT
120 unsigned long contention_point[4];
121#endif
122};
123
124#ifdef CONFIG_LOCK_STAT
125struct lock_time {
126 s64 min;
127 s64 max;
128 s64 total;
129 unsigned long nr;
117}; 130};
118 131
132struct lock_class_stats {
133 unsigned long contention_point[4];
134 struct lock_time read_waittime;
135 struct lock_time write_waittime;
136 struct lock_time read_holdtime;
137 struct lock_time write_holdtime;
138};
139
140struct lock_class_stats lock_stats(struct lock_class *class);
141void clear_lock_stats(struct lock_class *class);
142#endif
143
119/* 144/*
120 * Map the lock object (the lock instance) to the lock-class object. 145 * Map the lock object (the lock instance) to the lock-class object.
121 * This is embedded into specific lock instances: 146 * This is embedded into specific lock instances:
@@ -165,6 +190,10 @@ struct held_lock {
165 unsigned long acquire_ip; 190 unsigned long acquire_ip;
166 struct lockdep_map *instance; 191 struct lockdep_map *instance;
167 192
193#ifdef CONFIG_LOCK_STAT
194 u64 waittime_stamp;
195 u64 holdtime_stamp;
196#endif
168 /* 197 /*
169 * The lock-stack is unified in that the lock chains of interrupt 198 * The lock-stack is unified in that the lock chains of interrupt
170 * contexts nest ontop of process context chains, but we 'separate' 199 * contexts nest ontop of process context chains, but we 'separate'
@@ -281,6 +310,30 @@ struct lock_class_key { };
281 310
282#endif /* !LOCKDEP */ 311#endif /* !LOCKDEP */
283 312
313#ifdef CONFIG_LOCK_STAT
314
315extern void lock_contended(struct lockdep_map *lock, unsigned long ip);
316extern void lock_acquired(struct lockdep_map *lock);
317
318#define LOCK_CONTENDED(_lock, try, lock) \
319do { \
320 if (!try(_lock)) { \
321 lock_contended(&(_lock)->dep_map, _RET_IP_); \
322 lock(_lock); \
323 lock_acquired(&(_lock)->dep_map); \
324 } \
325} while (0)
326
327#else /* CONFIG_LOCK_STAT */
328
329#define lock_contended(lockdep_map, ip) do {} while (0)
330#define lock_acquired(lockdep_map) do {} while (0)
331
332#define LOCK_CONTENDED(_lock, try, lock) \
333 lock(_lock)
334
335#endif /* CONFIG_LOCK_STAT */
336
284#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS) 337#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS)
285extern void early_init_irq_lock_class(void); 338extern void early_init_irq_lock_class(void);
286#else 339#else