aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-05-29 16:03:07 -0400
committerIngo Molnar <mingo@elte.hu>2009-05-30 05:34:00 -0400
commitc44613a4c1092e85841b78b7ab52a06654fcd321 (patch)
tree364605b0662b25f6a3abe3238489bdb5dfe001f5
parentb78c07d45a7e71be7b5c5d7486f922355ccf23a8 (diff)
perf_counter tools: Add locking to perf top
perf_counter tools: Add locking to perf top We need to protect the active_symbols list as two threads change it: the main thread adding entries to the head and the display thread decaying entries from any place in the list. Also related: take a snapshot of syme->count[0] before using it to calculate the weight and to show the same number used in this calc when displaying the symbol usage. Reported-by: Mike Galbraith <efault@gmx.de> Tested-by: Mike Galbraith <efault@gmx.de> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <20090529200307.GR4747@ghostprotocols.net> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--Documentation/perf_counter/builtin-top.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/Documentation/perf_counter/builtin-top.c b/Documentation/perf_counter/builtin-top.c
index ebe8bec1a0e8..24a887907a7a 100644
--- a/Documentation/perf_counter/builtin-top.c
+++ b/Documentation/perf_counter/builtin-top.c
@@ -129,6 +129,8 @@ struct sym_entry {
129 struct rb_node rb_node; 129 struct rb_node rb_node;
130 struct list_head node; 130 struct list_head node;
131 unsigned long count[MAX_COUNTERS]; 131 unsigned long count[MAX_COUNTERS];
132 unsigned long snap_count;
133 double weight;
132 int skip; 134 int skip;
133}; 135};
134 136
@@ -141,17 +143,16 @@ struct dso *kernel_dso;
141 * after decayed. 143 * after decayed.
142 */ 144 */
143static LIST_HEAD(active_symbols); 145static LIST_HEAD(active_symbols);
146static pthread_mutex_t active_symbols_lock = PTHREAD_MUTEX_INITIALIZER;
144 147
145/* 148/*
146 * Ordering weight: count-1 * count-2 * ... / count-n 149 * Ordering weight: count-1 * count-2 * ... / count-n
147 */ 150 */
148static double sym_weight(const struct sym_entry *sym) 151static double sym_weight(const struct sym_entry *sym)
149{ 152{
150 double weight; 153 double weight = sym->snap_count;
151 int counter; 154 int counter;
152 155
153 weight = sym->count[0];
154
155 for (counter = 1; counter < nr_counters-1; counter++) 156 for (counter = 1; counter < nr_counters-1; counter++)
156 weight *= sym->count[counter]; 157 weight *= sym->count[counter];
157 158
@@ -164,11 +165,18 @@ static long events;
164static long userspace_events; 165static long userspace_events;
165static const char CONSOLE_CLEAR[] = ""; 166static const char CONSOLE_CLEAR[] = "";
166 167
167static void list_insert_active_sym(struct sym_entry *syme) 168static void __list_insert_active_sym(struct sym_entry *syme)
168{ 169{
169 list_add(&syme->node, &active_symbols); 170 list_add(&syme->node, &active_symbols);
170} 171}
171 172
173static void list_remove_active_sym(struct sym_entry *syme)
174{
175 pthread_mutex_lock(&active_symbols_lock);
176 list_del_init(&syme->node);
177 pthread_mutex_unlock(&active_symbols_lock);
178}
179
172static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se) 180static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
173{ 181{
174 struct rb_node **p = &tree->rb_node; 182 struct rb_node **p = &tree->rb_node;
@@ -179,7 +187,7 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
179 parent = *p; 187 parent = *p;
180 iter = rb_entry(parent, struct sym_entry, rb_node); 188 iter = rb_entry(parent, struct sym_entry, rb_node);
181 189
182 if (sym_weight(se) > sym_weight(iter)) 190 if (se->weight > iter->weight)
183 p = &(*p)->rb_left; 191 p = &(*p)->rb_left;
184 else 192 else
185 p = &(*p)->rb_right; 193 p = &(*p)->rb_right;
@@ -203,15 +211,21 @@ static void print_sym_table(void)
203 events = userspace_events = 0; 211 events = userspace_events = 0;
204 212
205 /* Sort the active symbols */ 213 /* Sort the active symbols */
206 list_for_each_entry_safe(syme, n, &active_symbols, node) { 214 pthread_mutex_lock(&active_symbols_lock);
207 if (syme->count[0] != 0) { 215 syme = list_entry(active_symbols.next, struct sym_entry, node);
216 pthread_mutex_unlock(&active_symbols_lock);
217
218 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
219 syme->snap_count = syme->count[0];
220 if (syme->snap_count != 0) {
221 syme->weight = sym_weight(syme);
208 rb_insert_active_sym(&tmp, syme); 222 rb_insert_active_sym(&tmp, syme);
209 sum_kevents += syme->count[0]; 223 sum_kevents += syme->snap_count;
210 224
211 for (j = 0; j < nr_counters; j++) 225 for (j = 0; j < nr_counters; j++)
212 syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8; 226 syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8;
213 } else 227 } else
214 list_del_init(&syme->node); 228 list_remove_active_sym(syme);
215 } 229 }
216 230
217 write(1, CONSOLE_CLEAR, strlen(CONSOLE_CLEAR)); 231 write(1, CONSOLE_CLEAR, strlen(CONSOLE_CLEAR));
@@ -264,19 +278,18 @@ static void print_sym_table(void)
264 struct symbol *sym = (struct symbol *)(syme + 1); 278 struct symbol *sym = (struct symbol *)(syme + 1);
265 float pcnt; 279 float pcnt;
266 280
267 if (++printed > 18 || syme->count[0] < count_filter) 281 if (++printed > 18 || syme->snap_count < count_filter)
268 break; 282 continue;
269 283
270 pcnt = 100.0 - (100.0 * ((sum_kevents - syme->count[0]) / 284 pcnt = 100.0 - (100.0 * ((sum_kevents - syme->snap_count) /
271 sum_kevents)); 285 sum_kevents));
272 286
273 if (nr_counters == 1) 287 if (nr_counters == 1)
274 printf("%19.2f - %4.1f%% - %016llx : %s\n", 288 printf("%19.2f - %4.1f%% - %016llx : %s\n",
275 sym_weight(syme), 289 syme->weight, pcnt, sym->start, sym->name);
276 pcnt, sym->start, sym->name);
277 else 290 else
278 printf("%8.1f %10ld - %4.1f%% - %016llx : %s\n", 291 printf("%8.1f %10ld - %4.1f%% - %016llx : %s\n",
279 sym_weight(syme), syme->count[0], 292 syme->weight, syme->snap_count,
280 pcnt, sym->start, sym->name); 293 pcnt, sym->start, sym->name);
281 } 294 }
282 295
@@ -395,8 +408,10 @@ static void record_ip(uint64_t ip, int counter)
395 408
396 if (!syme->skip) { 409 if (!syme->skip) {
397 syme->count[counter]++; 410 syme->count[counter]++;
411 pthread_mutex_lock(&active_symbols_lock);
398 if (list_empty(&syme->node) || !syme->node.next) 412 if (list_empty(&syme->node) || !syme->node.next)
399 list_insert_active_sym(syme); 413 __list_insert_active_sym(syme);
414 pthread_mutex_unlock(&active_symbols_lock);
400 return; 415 return;
401 } 416 }
402 } 417 }