diff options
| -rw-r--r-- | kernel/trace/ftrace.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 2404b59b3097..3bcb340d6f02 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -264,6 +264,7 @@ struct ftrace_profile { | |||
| 264 | unsigned long counter; | 264 | unsigned long counter; |
| 265 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 265 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 266 | unsigned long long time; | 266 | unsigned long long time; |
| 267 | unsigned long long time_squared; | ||
| 267 | #endif | 268 | #endif |
| 268 | }; | 269 | }; |
| 269 | 270 | ||
| @@ -366,9 +367,9 @@ static int function_stat_headers(struct seq_file *m) | |||
| 366 | { | 367 | { |
| 367 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 368 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 368 | seq_printf(m, " Function " | 369 | seq_printf(m, " Function " |
| 369 | "Hit Time Avg\n" | 370 | "Hit Time Avg s^2\n" |
| 370 | " -------- " | 371 | " -------- " |
| 371 | "--- ---- ---\n"); | 372 | "--- ---- --- ---\n"); |
| 372 | #else | 373 | #else |
| 373 | seq_printf(m, " Function Hit\n" | 374 | seq_printf(m, " Function Hit\n" |
| 374 | " -------- ---\n"); | 375 | " -------- ---\n"); |
| @@ -384,6 +385,7 @@ static int function_stat_show(struct seq_file *m, void *v) | |||
| 384 | static DEFINE_MUTEX(mutex); | 385 | static DEFINE_MUTEX(mutex); |
| 385 | static struct trace_seq s; | 386 | static struct trace_seq s; |
| 386 | unsigned long long avg; | 387 | unsigned long long avg; |
| 388 | unsigned long long stddev; | ||
| 387 | #endif | 389 | #endif |
| 388 | 390 | ||
| 389 | kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); | 391 | kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); |
| @@ -394,11 +396,25 @@ static int function_stat_show(struct seq_file *m, void *v) | |||
| 394 | avg = rec->time; | 396 | avg = rec->time; |
| 395 | do_div(avg, rec->counter); | 397 | do_div(avg, rec->counter); |
| 396 | 398 | ||
| 399 | /* Sample standard deviation (s^2) */ | ||
| 400 | if (rec->counter <= 1) | ||
| 401 | stddev = 0; | ||
| 402 | else { | ||
| 403 | stddev = rec->time_squared - rec->counter * avg * avg; | ||
| 404 | /* | ||
| 405 | * Divide only 1000 for ns^2 -> us^2 conversion. | ||
| 406 | * trace_print_graph_duration will divide 1000 again. | ||
| 407 | */ | ||
| 408 | do_div(stddev, (rec->counter - 1) * 1000); | ||
| 409 | } | ||
| 410 | |||
| 397 | mutex_lock(&mutex); | 411 | mutex_lock(&mutex); |
| 398 | trace_seq_init(&s); | 412 | trace_seq_init(&s); |
| 399 | trace_print_graph_duration(rec->time, &s); | 413 | trace_print_graph_duration(rec->time, &s); |
| 400 | trace_seq_puts(&s, " "); | 414 | trace_seq_puts(&s, " "); |
| 401 | trace_print_graph_duration(avg, &s); | 415 | trace_print_graph_duration(avg, &s); |
| 416 | trace_seq_puts(&s, " "); | ||
| 417 | trace_print_graph_duration(stddev, &s); | ||
| 402 | trace_print_seq(m, &s); | 418 | trace_print_seq(m, &s); |
| 403 | mutex_unlock(&mutex); | 419 | mutex_unlock(&mutex); |
| 404 | #endif | 420 | #endif |
| @@ -668,8 +684,10 @@ static void profile_graph_return(struct ftrace_graph_ret *trace) | |||
| 668 | } | 684 | } |
| 669 | 685 | ||
| 670 | rec = ftrace_find_profiled_func(stat, trace->func); | 686 | rec = ftrace_find_profiled_func(stat, trace->func); |
| 671 | if (rec) | 687 | if (rec) { |
| 672 | rec->time += calltime; | 688 | rec->time += calltime; |
| 689 | rec->time_squared += calltime * calltime; | ||
| 690 | } | ||
| 673 | 691 | ||
| 674 | out: | 692 | out: |
| 675 | local_irq_restore(flags); | 693 | local_irq_restore(flags); |
