aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/lockstat.txt50
-rw-r--r--include/linux/lockdep.h13
-rw-r--r--kernel/lockdep.c33
-rw-r--r--kernel/lockdep_proc.c21
-rw-r--r--kernel/mutex.c2
5 files changed, 82 insertions, 37 deletions
diff --git a/Documentation/lockstat.txt b/Documentation/lockstat.txt
index 02f36f5c64fe..9cb9138f7a79 100644
--- a/Documentation/lockstat.txt
+++ b/Documentation/lockstat.txt
@@ -71,34 +71,48 @@ Look at the current lock statistics:
71 71
72# less /proc/lock_stat 72# less /proc/lock_stat
73 73
7401 lock_stat version 0.2 7401 lock_stat version 0.3
7502 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 7502 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
7603 class name con-bounces contentions waittime-min waittime-max waittime-total acq-bounces acquisitions holdtime-min holdtime-max holdtime-total 7603 class name con-bounces contentions waittime-min waittime-max waittime-total acq-bounces acquisitions holdtime-min holdtime-max holdtime-total
7704 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 7704 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
7805 7805
7906 &inode->i_data.tree_lock-W: 15 21657 0.18 1093295.30 11547131054.85 58 10415 0.16 87.51 6387.60 7906 &mm->mmap_sem-W: 233 538 18446744073708 22924.27 607243.51 1342 45806 1.71 8595.89 1180582.34
8007 &inode->i_data.tree_lock-R: 0 0 0.00 0.00 0.00 23302 231198 0.25 8.45 98023.38 8007 &mm->mmap_sem-R: 205 587 18446744073708 28403.36 731975.00 1940 412426 0.58 187825.45 6307502.88
8108 -------------------------- 8108 ---------------
8209 &inode->i_data.tree_lock 0 [<ffffffff8027c08f>] add_to_page_cache+0x5f/0x190 8209 &mm->mmap_sem 487 [<ffffffff8053491f>] do_page_fault+0x466/0x928
8310 8310 &mm->mmap_sem 179 [<ffffffff802a6200>] sys_mprotect+0xcd/0x21d
8411 ............................................................................................................................................................................................... 8411 &mm->mmap_sem 279 [<ffffffff80210a57>] sys_mmap+0x75/0xce
8512 8512 &mm->mmap_sem 76 [<ffffffff802a490b>] sys_munmap+0x32/0x59
8613 dcache_lock: 1037 1161 0.38 45.32 774.51 6611 243371 0.15 306.48 77387.24 8613 ---------------
8714 ----------- 8714 &mm->mmap_sem 270 [<ffffffff80210a57>] sys_mmap+0x75/0xce
8815 dcache_lock 180 [<ffffffff802c0d7e>] sys_getcwd+0x11e/0x230 8815 &mm->mmap_sem 431 [<ffffffff8053491f>] do_page_fault+0x466/0x928
8916 dcache_lock 165 [<ffffffff802c002a>] d_alloc+0x15a/0x210 8916 &mm->mmap_sem 138 [<ffffffff802a490b>] sys_munmap+0x32/0x59
9017 dcache_lock 33 [<ffffffff8035818d>] _atomic_dec_and_lock+0x4d/0x70 9017 &mm->mmap_sem 145 [<ffffffff802a6200>] sys_mprotect+0xcd/0x21d
9118 dcache_lock 1 [<ffffffff802beef8>] shrink_dcache_parent+0x18/0x130 9118
9219 ...............................................................................................................................................................................................
9320
9421 dcache_lock: 621 623 0.52 118.26 1053.02 6745 91930 0.29 316.29 118423.41
9522 -----------
9623 dcache_lock 179 [<ffffffff80378274>] _atomic_dec_and_lock+0x34/0x54
9724 dcache_lock 113 [<ffffffff802cc17b>] d_alloc+0x19a/0x1eb
9825 dcache_lock 99 [<ffffffff802ca0dc>] d_rehash+0x1b/0x44
9926 dcache_lock 104 [<ffffffff802cbca0>] d_instantiate+0x36/0x8a
10027 -----------
10128 dcache_lock 192 [<ffffffff80378274>] _atomic_dec_and_lock+0x34/0x54
10229 dcache_lock 98 [<ffffffff802ca0dc>] d_rehash+0x1b/0x44
10330 dcache_lock 72 [<ffffffff802cc17b>] d_alloc+0x19a/0x1eb
10431 dcache_lock 112 [<ffffffff802cbca0>] d_instantiate+0x36/0x8a
92 105
93This excerpt shows the first two lock class statistics. Line 01 shows the 106This excerpt shows the first two lock class statistics. Line 01 shows the
94output version - each time the format changes this will be updated. Line 02-04 107output version - each time the format changes this will be updated. Line 02-04
95show the header with column descriptions. Lines 05-10 and 13-18 show the actual 108show the header with column descriptions. Lines 05-18 and 20-31 show the actual
96statistics. These statistics come in two parts; the actual stats separated by a 109statistics. These statistics come in two parts; the actual stats separated by a
97short separator (line 08, 14) from the contention points. 110short separator (line 08, 13) from the contention points.
98 111
99The first lock (05-10) is a read/write lock, and shows two lines above the 112The first lock (05-18) is a read/write lock, and shows two lines above the
100short separator. The contention points don't match the column descriptors, 113short separator. The contention points don't match the column descriptors,
101they have two: contentions and [<IP>] symbol. 114they have two: contentions and [<IP>] symbol. The second set of contention
115points are the points we're contending with.
102 116
103The integer part of the time values is in us. 117The integer part of the time values is in us.
104 118
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 0aa657aa8a1e..fc9f8e88123b 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -73,6 +73,8 @@ struct lock_class_key {
73 struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES]; 73 struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES];
74}; 74};
75 75
76#define LOCKSTAT_POINTS 4
77
76/* 78/*
77 * The lock-class itself: 79 * The lock-class itself:
78 */ 80 */
@@ -119,7 +121,8 @@ struct lock_class {
119 int name_version; 121 int name_version;
120 122
121#ifdef CONFIG_LOCK_STAT 123#ifdef CONFIG_LOCK_STAT
122 unsigned long contention_point[4]; 124 unsigned long contention_point[LOCKSTAT_POINTS];
125 unsigned long contending_point[LOCKSTAT_POINTS];
123#endif 126#endif
124}; 127};
125 128
@@ -144,6 +147,7 @@ enum bounce_type {
144 147
145struct lock_class_stats { 148struct lock_class_stats {
146 unsigned long contention_point[4]; 149 unsigned long contention_point[4];
150 unsigned long contending_point[4];
147 struct lock_time read_waittime; 151 struct lock_time read_waittime;
148 struct lock_time write_waittime; 152 struct lock_time write_waittime;
149 struct lock_time read_holdtime; 153 struct lock_time read_holdtime;
@@ -165,6 +169,7 @@ struct lockdep_map {
165 const char *name; 169 const char *name;
166#ifdef CONFIG_LOCK_STAT 170#ifdef CONFIG_LOCK_STAT
167 int cpu; 171 int cpu;
172 unsigned long ip;
168#endif 173#endif
169}; 174};
170 175
@@ -355,7 +360,7 @@ struct lock_class_key { };
355#ifdef CONFIG_LOCK_STAT 360#ifdef CONFIG_LOCK_STAT
356 361
357extern void lock_contended(struct lockdep_map *lock, unsigned long ip); 362extern void lock_contended(struct lockdep_map *lock, unsigned long ip);
358extern void lock_acquired(struct lockdep_map *lock); 363extern void lock_acquired(struct lockdep_map *lock, unsigned long ip);
359 364
360#define LOCK_CONTENDED(_lock, try, lock) \ 365#define LOCK_CONTENDED(_lock, try, lock) \
361do { \ 366do { \
@@ -363,13 +368,13 @@ do { \
363 lock_contended(&(_lock)->dep_map, _RET_IP_); \ 368 lock_contended(&(_lock)->dep_map, _RET_IP_); \
364 lock(_lock); \ 369 lock(_lock); \
365 } \ 370 } \
366 lock_acquired(&(_lock)->dep_map); \ 371 lock_acquired(&(_lock)->dep_map, _RET_IP_); \
367} while (0) 372} while (0)
368 373
369#else /* CONFIG_LOCK_STAT */ 374#else /* CONFIG_LOCK_STAT */
370 375
371#define lock_contended(lockdep_map, ip) do {} while (0) 376#define lock_contended(lockdep_map, ip) do {} while (0)
372#define lock_acquired(lockdep_map) do {} while (0) 377#define lock_acquired(lockdep_map, ip) do {} while (0)
373 378
374#define LOCK_CONTENDED(_lock, try, lock) \ 379#define LOCK_CONTENDED(_lock, try, lock) \
375 lock(_lock) 380 lock(_lock)
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index dbda475b13bd..234a9dccb4be 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
137static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], lock_stats); 137static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], lock_stats);
138 138
139static int lock_contention_point(struct lock_class *class, unsigned long ip) 139static 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
214static struct lock_class_stats *get_lock_stats(struct lock_class *class) 218static struct lock_class_stats *get_lock_stats(struct lock_class *class)
@@ -3001,7 +3005,7 @@ __lock_contended(struct lockdep_map *lock, unsigned long ip)
3001 struct held_lock *hlock, *prev_hlock; 3005 struct held_lock *hlock, *prev_hlock;
3002 struct lock_class_stats *stats; 3006 struct lock_class_stats *stats;
3003 unsigned int depth; 3007 unsigned int depth;
3004 int i, point; 3008 int i, contention_point, contending_point;
3005 3009
3006 depth = curr->lockdep_depth; 3010 depth = curr->lockdep_depth;
3007 if (DEBUG_LOCKS_WARN_ON(!depth)) 3011 if (DEBUG_LOCKS_WARN_ON(!depth))
@@ -3025,18 +3029,22 @@ __lock_contended(struct lockdep_map *lock, unsigned long ip)
3025found_it: 3029found_it:
3026 hlock->waittime_stamp = sched_clock(); 3030 hlock->waittime_stamp = sched_clock();
3027 3031
3028 point = lock_contention_point(hlock_class(hlock), ip); 3032 contention_point = lock_point(hlock_class(hlock)->contention_point, ip);
3033 contending_point = lock_point(hlock_class(hlock)->contending_point,
3034 lock->ip);
3029 3035
3030 stats = get_lock_stats(hlock_class(hlock)); 3036 stats = get_lock_stats(hlock_class(hlock));
3031 if (point < ARRAY_SIZE(stats->contention_point)) 3037 if (contention_point < LOCKSTAT_POINTS)
3032 stats->contention_point[point]++; 3038 stats->contention_point[contention_point]++;
3039 if (contending_point < LOCKSTAT_POINTS)
3040 stats->contending_point[contending_point]++;
3033 if (lock->cpu != smp_processor_id()) 3041 if (lock->cpu != smp_processor_id())
3034 stats->bounces[bounce_contended + !!hlock->read]++; 3042 stats->bounces[bounce_contended + !!hlock->read]++;
3035 put_lock_stats(stats); 3043 put_lock_stats(stats);
3036} 3044}
3037 3045
3038static void 3046static void
3039__lock_acquired(struct lockdep_map *lock) 3047__lock_acquired(struct lockdep_map *lock, unsigned long ip)
3040{ 3048{
3041 struct task_struct *curr = current; 3049 struct task_struct *curr = current;
3042 struct held_lock *hlock, *prev_hlock; 3050 struct held_lock *hlock, *prev_hlock;
@@ -3085,6 +3093,7 @@ found_it:
3085 put_lock_stats(stats); 3093 put_lock_stats(stats);
3086 3094
3087 lock->cpu = cpu; 3095 lock->cpu = cpu;
3096 lock->ip = ip;
3088} 3097}
3089 3098
3090void lock_contended(struct lockdep_map *lock, unsigned long ip) 3099void lock_contended(struct lockdep_map *lock, unsigned long ip)
@@ -3106,7 +3115,7 @@ void lock_contended(struct lockdep_map *lock, unsigned long ip)
3106} 3115}
3107EXPORT_SYMBOL_GPL(lock_contended); 3116EXPORT_SYMBOL_GPL(lock_contended);
3108 3117
3109void lock_acquired(struct lockdep_map *lock) 3118void lock_acquired(struct lockdep_map *lock, unsigned long ip)
3110{ 3119{
3111 unsigned long flags; 3120 unsigned long flags;
3112 3121
@@ -3119,7 +3128,7 @@ void lock_acquired(struct lockdep_map *lock)
3119 raw_local_irq_save(flags); 3128 raw_local_irq_save(flags);
3120 check_flags(flags); 3129 check_flags(flags);
3121 current->lockdep_recursion = 1; 3130 current->lockdep_recursion = 1;
3122 __lock_acquired(lock); 3131 __lock_acquired(lock, ip);
3123 current->lockdep_recursion = 0; 3132 current->lockdep_recursion = 0;
3124 raw_local_irq_restore(flags); 3133 raw_local_irq_restore(flags);
3125} 3134}
diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c
index 8d3a6eba8d5a..13716b813896 100644
--- a/kernel/lockdep_proc.c
+++ b/kernel/lockdep_proc.c
@@ -557,7 +557,7 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data)
557 if (stats->read_holdtime.nr) 557 if (stats->read_holdtime.nr)
558 namelen += 2; 558 namelen += 2;
559 559
560 for (i = 0; i < ARRAY_SIZE(class->contention_point); i++) { 560 for (i = 0; i < LOCKSTAT_POINTS; i++) {
561 char sym[KSYM_SYMBOL_LEN]; 561 char sym[KSYM_SYMBOL_LEN];
562 char ip[32]; 562 char ip[32];
563 563
@@ -574,6 +574,23 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data)
574 stats->contention_point[i], 574 stats->contention_point[i],
575 ip, sym); 575 ip, sym);
576 } 576 }
577 for (i = 0; i < LOCKSTAT_POINTS; i++) {
578 char sym[KSYM_SYMBOL_LEN];
579 char ip[32];
580
581 if (class->contending_point[i] == 0)
582 break;
583
584 if (!i)
585 seq_line(m, '-', 40-namelen, namelen);
586
587 sprint_symbol(sym, class->contending_point[i]);
588 snprintf(ip, sizeof(ip), "[<%p>]",
589 (void *)class->contending_point[i]);
590 seq_printf(m, "%40s %14lu %29s %s\n", name,
591 stats->contending_point[i],
592 ip, sym);
593 }
577 if (i) { 594 if (i) {
578 seq_puts(m, "\n"); 595 seq_puts(m, "\n");
579 seq_line(m, '.', 0, 40 + 1 + 10 * (14 + 1)); 596 seq_line(m, '.', 0, 40 + 1 + 10 * (14 + 1));
@@ -583,7 +600,7 @@ static void seq_stats(struct seq_file *m, struct lock_stat_data *data)
583 600
584static void seq_header(struct seq_file *m) 601static void seq_header(struct seq_file *m)
585{ 602{
586 seq_printf(m, "lock_stat version 0.2\n"); 603 seq_printf(m, "lock_stat version 0.3\n");
587 seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); 604 seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1));
588 seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s " 605 seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s "
589 "%14s %14s\n", 606 "%14s %14s\n",
diff --git a/kernel/mutex.c b/kernel/mutex.c
index 12c779dc65d4..39a3816b68d9 100644
--- a/kernel/mutex.c
+++ b/kernel/mutex.c
@@ -184,7 +184,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
184 } 184 }
185 185
186done: 186done:
187 lock_acquired(&lock->dep_map); 187 lock_acquired(&lock->dep_map, ip);
188 /* got the lock - rejoice! */ 188 /* got the lock - rejoice! */
189 mutex_remove_waiter(lock, &waiter, task_thread_info(task)); 189 mutex_remove_waiter(lock, &waiter, task_thread_info(task));
190 debug_mutex_set_owner(lock, task_thread_info(task)); 190 debug_mutex_set_owner(lock, task_thread_info(task));