diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-09-14 00:16:56 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-09-14 00:16:56 -0400 |
commit | fc8e1ead9314cf0e0f1922e661428b93d3a50d88 (patch) | |
tree | f3cb97c4769b74f6627a59769f1ed5c92a13c58a /kernel/trace/trace.h | |
parent | 2bcaa6a4238094c5695d5b1943078388d82d3004 (diff) | |
parent | 9de48cc300fb10f7d9faa978670becf5e352462a (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'kernel/trace/trace.h')
-rw-r--r-- | kernel/trace/trace.h | 254 |
1 files changed, 105 insertions, 149 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index e685ac2b2ba1..8b9f4f6e9559 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -9,9 +9,12 @@ | |||
9 | #include <linux/mmiotrace.h> | 9 | #include <linux/mmiotrace.h> |
10 | #include <linux/ftrace.h> | 10 | #include <linux/ftrace.h> |
11 | #include <trace/boot.h> | 11 | #include <trace/boot.h> |
12 | #include <trace/kmemtrace.h> | 12 | #include <linux/kmemtrace.h> |
13 | #include <trace/power.h> | 13 | #include <trace/power.h> |
14 | 14 | ||
15 | #include <linux/trace_seq.h> | ||
16 | #include <linux/ftrace_event.h> | ||
17 | |||
15 | enum trace_type { | 18 | enum trace_type { |
16 | __TRACE_FIRST_TYPE = 0, | 19 | __TRACE_FIRST_TYPE = 0, |
17 | 20 | ||
@@ -42,20 +45,6 @@ enum trace_type { | |||
42 | }; | 45 | }; |
43 | 46 | ||
44 | /* | 47 | /* |
45 | * The trace entry - the most basic unit of tracing. This is what | ||
46 | * is printed in the end as a single line in the trace output, such as: | ||
47 | * | ||
48 | * bash-15816 [01] 235.197585: idle_cpu <- irq_enter | ||
49 | */ | ||
50 | struct trace_entry { | ||
51 | unsigned char type; | ||
52 | unsigned char flags; | ||
53 | unsigned char preempt_count; | ||
54 | int pid; | ||
55 | int tgid; | ||
56 | }; | ||
57 | |||
58 | /* | ||
59 | * Function trace entry - function address and parent function addres: | 48 | * Function trace entry - function address and parent function addres: |
60 | */ | 49 | */ |
61 | struct ftrace_entry { | 50 | struct ftrace_entry { |
@@ -263,8 +252,6 @@ struct trace_array_cpu { | |||
263 | char comm[TASK_COMM_LEN]; | 252 | char comm[TASK_COMM_LEN]; |
264 | }; | 253 | }; |
265 | 254 | ||
266 | struct trace_iterator; | ||
267 | |||
268 | /* | 255 | /* |
269 | * The trace array - an array of per-CPU trace arrays. This is the | 256 | * The trace array - an array of per-CPU trace arrays. This is the |
270 | * highest level data structure that individual tracers deal with. | 257 | * highest level data structure that individual tracers deal with. |
@@ -339,15 +326,6 @@ extern void __ftrace_bad_type(void); | |||
339 | __ftrace_bad_type(); \ | 326 | __ftrace_bad_type(); \ |
340 | } while (0) | 327 | } while (0) |
341 | 328 | ||
342 | /* Return values for print_line callback */ | ||
343 | enum print_line_t { | ||
344 | TRACE_TYPE_PARTIAL_LINE = 0, /* Retry after flushing the seq */ | ||
345 | TRACE_TYPE_HANDLED = 1, | ||
346 | TRACE_TYPE_UNHANDLED = 2, /* Relay to other output functions */ | ||
347 | TRACE_TYPE_NO_CONSUME = 3 /* Handled but ask to not consume */ | ||
348 | }; | ||
349 | |||
350 | |||
351 | /* | 329 | /* |
352 | * An option specific to a tracer. This is a boolean value. | 330 | * An option specific to a tracer. This is a boolean value. |
353 | * The bit is the bit index that sets its value on the | 331 | * The bit is the bit index that sets its value on the |
@@ -423,60 +401,30 @@ struct tracer { | |||
423 | struct tracer_stat *stats; | 401 | struct tracer_stat *stats; |
424 | }; | 402 | }; |
425 | 403 | ||
426 | struct trace_seq { | ||
427 | unsigned char buffer[PAGE_SIZE]; | ||
428 | unsigned int len; | ||
429 | unsigned int readpos; | ||
430 | }; | ||
431 | |||
432 | static inline void | ||
433 | trace_seq_init(struct trace_seq *s) | ||
434 | { | ||
435 | s->len = 0; | ||
436 | s->readpos = 0; | ||
437 | } | ||
438 | |||
439 | 404 | ||
440 | #define TRACE_PIPE_ALL_CPU -1 | 405 | #define TRACE_PIPE_ALL_CPU -1 |
441 | 406 | ||
442 | /* | ||
443 | * Trace iterator - used by printout routines who present trace | ||
444 | * results to users and which routines might sleep, etc: | ||
445 | */ | ||
446 | struct trace_iterator { | ||
447 | struct trace_array *tr; | ||
448 | struct tracer *trace; | ||
449 | void *private; | ||
450 | int cpu_file; | ||
451 | struct mutex mutex; | ||
452 | struct ring_buffer_iter *buffer_iter[NR_CPUS]; | ||
453 | |||
454 | /* The below is zeroed out in pipe_read */ | ||
455 | struct trace_seq seq; | ||
456 | struct trace_entry *ent; | ||
457 | int cpu; | ||
458 | u64 ts; | ||
459 | |||
460 | unsigned long iter_flags; | ||
461 | loff_t pos; | ||
462 | long idx; | ||
463 | |||
464 | cpumask_var_t started; | ||
465 | }; | ||
466 | |||
467 | int tracer_init(struct tracer *t, struct trace_array *tr); | 407 | int tracer_init(struct tracer *t, struct trace_array *tr); |
468 | int tracing_is_enabled(void); | 408 | int tracing_is_enabled(void); |
469 | void trace_wake_up(void); | 409 | void trace_wake_up(void); |
470 | void tracing_reset(struct trace_array *tr, int cpu); | 410 | void tracing_reset(struct trace_array *tr, int cpu); |
471 | void tracing_reset_online_cpus(struct trace_array *tr); | 411 | void tracing_reset_online_cpus(struct trace_array *tr); |
412 | void tracing_reset_current(int cpu); | ||
413 | void tracing_reset_current_online_cpus(void); | ||
472 | int tracing_open_generic(struct inode *inode, struct file *filp); | 414 | int tracing_open_generic(struct inode *inode, struct file *filp); |
415 | struct dentry *trace_create_file(const char *name, | ||
416 | mode_t mode, | ||
417 | struct dentry *parent, | ||
418 | void *data, | ||
419 | const struct file_operations *fops); | ||
420 | |||
473 | struct dentry *tracing_init_dentry(void); | 421 | struct dentry *tracing_init_dentry(void); |
474 | void init_tracer_sysprof_debugfs(struct dentry *d_tracer); | 422 | void init_tracer_sysprof_debugfs(struct dentry *d_tracer); |
475 | 423 | ||
476 | struct ring_buffer_event; | 424 | struct ring_buffer_event; |
477 | 425 | ||
478 | struct ring_buffer_event *trace_buffer_lock_reserve(struct trace_array *tr, | 426 | struct ring_buffer_event *trace_buffer_lock_reserve(struct trace_array *tr, |
479 | unsigned char type, | 427 | int type, |
480 | unsigned long len, | 428 | unsigned long len, |
481 | unsigned long flags, | 429 | unsigned long flags, |
482 | int pc); | 430 | int pc); |
@@ -484,24 +432,12 @@ void trace_buffer_unlock_commit(struct trace_array *tr, | |||
484 | struct ring_buffer_event *event, | 432 | struct ring_buffer_event *event, |
485 | unsigned long flags, int pc); | 433 | unsigned long flags, int pc); |
486 | 434 | ||
487 | struct ring_buffer_event * | ||
488 | trace_current_buffer_lock_reserve(unsigned char type, unsigned long len, | ||
489 | unsigned long flags, int pc); | ||
490 | void trace_current_buffer_unlock_commit(struct ring_buffer_event *event, | ||
491 | unsigned long flags, int pc); | ||
492 | void trace_nowake_buffer_unlock_commit(struct ring_buffer_event *event, | ||
493 | unsigned long flags, int pc); | ||
494 | |||
495 | struct trace_entry *tracing_get_trace_entry(struct trace_array *tr, | 435 | struct trace_entry *tracing_get_trace_entry(struct trace_array *tr, |
496 | struct trace_array_cpu *data); | 436 | struct trace_array_cpu *data); |
497 | 437 | ||
498 | struct trace_entry *trace_find_next_entry(struct trace_iterator *iter, | 438 | struct trace_entry *trace_find_next_entry(struct trace_iterator *iter, |
499 | int *ent_cpu, u64 *ent_ts); | 439 | int *ent_cpu, u64 *ent_ts); |
500 | 440 | ||
501 | void tracing_generic_entry_update(struct trace_entry *entry, | ||
502 | unsigned long flags, | ||
503 | int pc); | ||
504 | |||
505 | void default_wait_pipe(struct trace_iterator *iter); | 441 | void default_wait_pipe(struct trace_iterator *iter); |
506 | void poll_wait_pipe(struct trace_iterator *iter); | 442 | void poll_wait_pipe(struct trace_iterator *iter); |
507 | 443 | ||
@@ -514,7 +450,6 @@ void tracing_sched_switch_trace(struct trace_array *tr, | |||
514 | struct task_struct *prev, | 450 | struct task_struct *prev, |
515 | struct task_struct *next, | 451 | struct task_struct *next, |
516 | unsigned long flags, int pc); | 452 | unsigned long flags, int pc); |
517 | void tracing_record_cmdline(struct task_struct *tsk); | ||
518 | 453 | ||
519 | void tracing_sched_wakeup_trace(struct trace_array *tr, | 454 | void tracing_sched_wakeup_trace(struct trace_array *tr, |
520 | struct task_struct *wakee, | 455 | struct task_struct *wakee, |
@@ -599,6 +534,8 @@ extern int trace_selftest_startup_sysprof(struct tracer *trace, | |||
599 | struct trace_array *tr); | 534 | struct trace_array *tr); |
600 | extern int trace_selftest_startup_branch(struct tracer *trace, | 535 | extern int trace_selftest_startup_branch(struct tracer *trace, |
601 | struct trace_array *tr); | 536 | struct trace_array *tr); |
537 | extern int trace_selftest_startup_hw_branches(struct tracer *trace, | ||
538 | struct trace_array *tr); | ||
602 | #endif /* CONFIG_FTRACE_STARTUP_TEST */ | 539 | #endif /* CONFIG_FTRACE_STARTUP_TEST */ |
603 | 540 | ||
604 | extern void *head_page(struct trace_array_cpu *data); | 541 | extern void *head_page(struct trace_array_cpu *data); |
@@ -613,6 +550,8 @@ extern unsigned long trace_flags; | |||
613 | /* Standard output formatting function used for function return traces */ | 550 | /* Standard output formatting function used for function return traces */ |
614 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 551 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
615 | extern enum print_line_t print_graph_function(struct trace_iterator *iter); | 552 | extern enum print_line_t print_graph_function(struct trace_iterator *iter); |
553 | extern enum print_line_t | ||
554 | trace_print_graph_duration(unsigned long long duration, struct trace_seq *s); | ||
616 | 555 | ||
617 | #ifdef CONFIG_DYNAMIC_FTRACE | 556 | #ifdef CONFIG_DYNAMIC_FTRACE |
618 | /* TODO: make this variable */ | 557 | /* TODO: make this variable */ |
@@ -644,7 +583,6 @@ static inline int ftrace_graph_addr(unsigned long addr) | |||
644 | return 1; | 583 | return 1; |
645 | } | 584 | } |
646 | #endif /* CONFIG_DYNAMIC_FTRACE */ | 585 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
647 | |||
648 | #else /* CONFIG_FUNCTION_GRAPH_TRACER */ | 586 | #else /* CONFIG_FUNCTION_GRAPH_TRACER */ |
649 | static inline enum print_line_t | 587 | static inline enum print_line_t |
650 | print_graph_function(struct trace_iterator *iter) | 588 | print_graph_function(struct trace_iterator *iter) |
@@ -655,6 +593,7 @@ print_graph_function(struct trace_iterator *iter) | |||
655 | 593 | ||
656 | extern struct pid *ftrace_pid_trace; | 594 | extern struct pid *ftrace_pid_trace; |
657 | 595 | ||
596 | #ifdef CONFIG_FUNCTION_TRACER | ||
658 | static inline int ftrace_trace_task(struct task_struct *task) | 597 | static inline int ftrace_trace_task(struct task_struct *task) |
659 | { | 598 | { |
660 | if (!ftrace_pid_trace) | 599 | if (!ftrace_pid_trace) |
@@ -662,6 +601,12 @@ static inline int ftrace_trace_task(struct task_struct *task) | |||
662 | 601 | ||
663 | return test_tsk_trace_trace(task); | 602 | return test_tsk_trace_trace(task); |
664 | } | 603 | } |
604 | #else | ||
605 | static inline int ftrace_trace_task(struct task_struct *task) | ||
606 | { | ||
607 | return 1; | ||
608 | } | ||
609 | #endif | ||
665 | 610 | ||
666 | /* | 611 | /* |
667 | * trace_iterator_flags is an enumeration that defines bit | 612 | * trace_iterator_flags is an enumeration that defines bit |
@@ -692,6 +637,7 @@ enum trace_iterator_flags { | |||
692 | TRACE_ITER_LATENCY_FMT = 0x40000, | 637 | TRACE_ITER_LATENCY_FMT = 0x40000, |
693 | TRACE_ITER_GLOBAL_CLK = 0x80000, | 638 | TRACE_ITER_GLOBAL_CLK = 0x80000, |
694 | TRACE_ITER_SLEEP_TIME = 0x100000, | 639 | TRACE_ITER_SLEEP_TIME = 0x100000, |
640 | TRACE_ITER_GRAPH_TIME = 0x200000, | ||
695 | }; | 641 | }; |
696 | 642 | ||
697 | /* | 643 | /* |
@@ -790,103 +736,113 @@ struct ftrace_event_field { | |||
790 | char *type; | 736 | char *type; |
791 | int offset; | 737 | int offset; |
792 | int size; | 738 | int size; |
739 | int is_signed; | ||
793 | }; | 740 | }; |
794 | 741 | ||
795 | struct ftrace_event_call { | 742 | struct event_filter { |
796 | char *name; | 743 | int n_preds; |
797 | char *system; | ||
798 | struct dentry *dir; | ||
799 | int enabled; | ||
800 | int (*regfunc)(void); | ||
801 | void (*unregfunc)(void); | ||
802 | int id; | ||
803 | int (*raw_init)(void); | ||
804 | int (*show_format)(struct trace_seq *s); | ||
805 | int (*define_fields)(void); | ||
806 | struct list_head fields; | ||
807 | struct filter_pred **preds; | 744 | struct filter_pred **preds; |
808 | 745 | char *filter_string; | |
809 | #ifdef CONFIG_EVENT_PROFILE | ||
810 | atomic_t profile_count; | ||
811 | int (*profile_enable)(struct ftrace_event_call *); | ||
812 | void (*profile_disable)(struct ftrace_event_call *); | ||
813 | #endif | ||
814 | }; | 746 | }; |
815 | 747 | ||
816 | struct event_subsystem { | 748 | struct event_subsystem { |
817 | struct list_head list; | 749 | struct list_head list; |
818 | const char *name; | 750 | const char *name; |
819 | struct dentry *entry; | 751 | struct dentry *entry; |
820 | struct filter_pred **preds; | 752 | void *filter; |
821 | }; | 753 | }; |
822 | 754 | ||
823 | #define events_for_each(event) \ | ||
824 | for (event = __start_ftrace_events; \ | ||
825 | (unsigned long)event < (unsigned long)__stop_ftrace_events; \ | ||
826 | event++) | ||
827 | |||
828 | #define MAX_FILTER_PRED 8 | ||
829 | |||
830 | struct filter_pred; | 755 | struct filter_pred; |
831 | 756 | ||
832 | typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event); | 757 | typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event, |
758 | int val1, int val2); | ||
833 | 759 | ||
834 | struct filter_pred { | 760 | struct filter_pred { |
835 | filter_pred_fn_t fn; | 761 | filter_pred_fn_t fn; |
836 | u64 val; | 762 | u64 val; |
837 | char *str_val; | 763 | char str_val[MAX_FILTER_STR_VAL]; |
838 | int str_len; | 764 | int str_len; |
839 | char *field_name; | 765 | char *field_name; |
840 | int offset; | 766 | int offset; |
841 | int not; | 767 | int not; |
842 | int or; | 768 | int op; |
843 | int compound; | 769 | int pop_n; |
844 | int clear; | ||
845 | }; | 770 | }; |
846 | 771 | ||
847 | int trace_define_field(struct ftrace_event_call *call, char *type, | 772 | extern void print_event_filter(struct ftrace_event_call *call, |
848 | char *name, int offset, int size); | ||
849 | extern void filter_free_pred(struct filter_pred *pred); | ||
850 | extern void filter_print_preds(struct filter_pred **preds, | ||
851 | struct trace_seq *s); | 773 | struct trace_seq *s); |
852 | extern int filter_parse(char **pbuf, struct filter_pred *pred); | 774 | extern int apply_event_filter(struct ftrace_event_call *call, |
853 | extern int filter_add_pred(struct ftrace_event_call *call, | 775 | char *filter_string); |
854 | struct filter_pred *pred); | 776 | extern int apply_subsystem_event_filter(struct event_subsystem *system, |
855 | extern void filter_free_preds(struct ftrace_event_call *call); | 777 | char *filter_string); |
856 | extern int filter_match_preds(struct ftrace_event_call *call, void *rec); | 778 | extern void print_subsystem_event_filter(struct event_subsystem *system, |
857 | extern void filter_free_subsystem_preds(struct event_subsystem *system); | 779 | struct trace_seq *s); |
858 | extern int filter_add_subsystem_pred(struct event_subsystem *system, | 780 | |
859 | struct filter_pred *pred); | 781 | static inline int |
860 | 782 | filter_check_discard(struct ftrace_event_call *call, void *rec, | |
861 | void event_trace_printk(unsigned long ip, const char *fmt, ...); | 783 | struct ring_buffer *buffer, |
862 | extern struct ftrace_event_call __start_ftrace_events[]; | 784 | struct ring_buffer_event *event) |
863 | extern struct ftrace_event_call __stop_ftrace_events[]; | 785 | { |
864 | 786 | if (unlikely(call->filter_active) && !filter_match_preds(call, rec)) { | |
865 | #define for_each_event(event) \ | 787 | ring_buffer_discard_commit(buffer, event); |
866 | for (event = __start_ftrace_events; \ | 788 | return 1; |
867 | (unsigned long)event < (unsigned long)__stop_ftrace_events; \ | 789 | } |
868 | event++) | 790 | |
791 | return 0; | ||
792 | } | ||
793 | |||
794 | #define DEFINE_COMPARISON_PRED(type) \ | ||
795 | static int filter_pred_##type(struct filter_pred *pred, void *event, \ | ||
796 | int val1, int val2) \ | ||
797 | { \ | ||
798 | type *addr = (type *)(event + pred->offset); \ | ||
799 | type val = (type)pred->val; \ | ||
800 | int match = 0; \ | ||
801 | \ | ||
802 | switch (pred->op) { \ | ||
803 | case OP_LT: \ | ||
804 | match = (*addr < val); \ | ||
805 | break; \ | ||
806 | case OP_LE: \ | ||
807 | match = (*addr <= val); \ | ||
808 | break; \ | ||
809 | case OP_GT: \ | ||
810 | match = (*addr > val); \ | ||
811 | break; \ | ||
812 | case OP_GE: \ | ||
813 | match = (*addr >= val); \ | ||
814 | break; \ | ||
815 | default: \ | ||
816 | break; \ | ||
817 | } \ | ||
818 | \ | ||
819 | return match; \ | ||
820 | } | ||
821 | |||
822 | #define DEFINE_EQUALITY_PRED(size) \ | ||
823 | static int filter_pred_##size(struct filter_pred *pred, void *event, \ | ||
824 | int val1, int val2) \ | ||
825 | { \ | ||
826 | u##size *addr = (u##size *)(event + pred->offset); \ | ||
827 | u##size val = (u##size)pred->val; \ | ||
828 | int match; \ | ||
829 | \ | ||
830 | match = (val == *addr) ^ pred->not; \ | ||
831 | \ | ||
832 | return match; \ | ||
833 | } | ||
834 | |||
835 | extern struct mutex event_mutex; | ||
836 | extern struct list_head ftrace_events; | ||
869 | 837 | ||
870 | extern const char *__start___trace_bprintk_fmt[]; | 838 | extern const char *__start___trace_bprintk_fmt[]; |
871 | extern const char *__stop___trace_bprintk_fmt[]; | 839 | extern const char *__stop___trace_bprintk_fmt[]; |
872 | 840 | ||
873 | /* | 841 | #undef TRACE_EVENT_FORMAT |
874 | * The double __builtin_constant_p is because gcc will give us an error | 842 | #define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt) \ |
875 | * if we try to allocate the static variable to fmt if it is not a | 843 | extern struct ftrace_event_call event_##call; |
876 | * constant. Even with the outer if statement optimizing out. | 844 | #undef TRACE_EVENT_FORMAT_NOFILTER |
877 | */ | 845 | #define TRACE_EVENT_FORMAT_NOFILTER(call, proto, args, fmt, tstruct, tpfmt) |
878 | #define event_trace_printk(ip, fmt, args...) \ | 846 | #include "trace_event_types.h" |
879 | do { \ | ||
880 | __trace_printk_check_format(fmt, ##args); \ | ||
881 | tracing_record_cmdline(current); \ | ||
882 | if (__builtin_constant_p(fmt)) { \ | ||
883 | static const char *trace_printk_fmt \ | ||
884 | __attribute__((section("__trace_printk_fmt"))) = \ | ||
885 | __builtin_constant_p(fmt) ? fmt : NULL; \ | ||
886 | \ | ||
887 | __trace_bprintk(ip, trace_printk_fmt, ##args); \ | ||
888 | } else \ | ||
889 | __trace_printk(ip, fmt, ##args); \ | ||
890 | } while (0) | ||
891 | 847 | ||
892 | #endif /* _LINUX_KERNEL_TRACE_H */ | 848 | #endif /* _LINUX_KERNEL_TRACE_H */ |