diff options
-rw-r--r-- | Documentation/markers.txt | 14 | ||||
-rw-r--r-- | include/linux/marker.h | 39 |
2 files changed, 37 insertions, 16 deletions
diff --git a/Documentation/markers.txt b/Documentation/markers.txt index 089f6138fcd9..6d275e4ef385 100644 --- a/Documentation/markers.txt +++ b/Documentation/markers.txt | |||
@@ -70,6 +70,20 @@ a printk warning which identifies the inconsistency: | |||
70 | 70 | ||
71 | "Format mismatch for probe probe_name (format), marker (format)" | 71 | "Format mismatch for probe probe_name (format), marker (format)" |
72 | 72 | ||
73 | Another way to use markers is to simply define the marker without generating any | ||
74 | function call to actually call into the marker. This is useful in combination | ||
75 | with tracepoint probes in a scheme like this : | ||
76 | |||
77 | void probe_tracepoint_name(unsigned int arg1, struct task_struct *tsk); | ||
78 | |||
79 | DEFINE_MARKER_TP(marker_eventname, tracepoint_name, probe_tracepoint_name, | ||
80 | "arg1 %u pid %d"); | ||
81 | |||
82 | notrace void probe_tracepoint_name(unsigned int arg1, struct task_struct *tsk) | ||
83 | { | ||
84 | struct marker *marker = &GET_MARKER(kernel_irq_entry); | ||
85 | /* write data to trace buffers ... */ | ||
86 | } | ||
73 | 87 | ||
74 | * Probe / marker example | 88 | * Probe / marker example |
75 | 89 | ||
diff --git a/include/linux/marker.h b/include/linux/marker.h index 57a307018ceb..34c14bc957f5 100644 --- a/include/linux/marker.h +++ b/include/linux/marker.h | |||
@@ -55,6 +55,22 @@ struct marker { | |||
55 | 55 | ||
56 | #ifdef CONFIG_MARKERS | 56 | #ifdef CONFIG_MARKERS |
57 | 57 | ||
58 | #define _DEFINE_MARKER(name, tp_name_str, tp_cb, format) \ | ||
59 | static const char __mstrtab_##name[] \ | ||
60 | __attribute__((section("__markers_strings"))) \ | ||
61 | = #name "\0" format; \ | ||
62 | static struct marker __mark_##name \ | ||
63 | __attribute__((section("__markers"), aligned(8))) = \ | ||
64 | { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \ | ||
65 | 0, 0, marker_probe_cb, { __mark_empty_function, NULL},\ | ||
66 | NULL, tp_name_str, tp_cb } | ||
67 | |||
68 | #define DEFINE_MARKER(name, format) \ | ||
69 | _DEFINE_MARKER(name, NULL, NULL, format) | ||
70 | |||
71 | #define DEFINE_MARKER_TP(name, tp_name, tp_cb, format) \ | ||
72 | _DEFINE_MARKER(name, #tp_name, tp_cb, format) | ||
73 | |||
58 | /* | 74 | /* |
59 | * Note : the empty asm volatile with read constraint is used here instead of a | 75 | * Note : the empty asm volatile with read constraint is used here instead of a |
60 | * "used" attribute to fix a gcc 4.1.x bug. | 76 | * "used" attribute to fix a gcc 4.1.x bug. |
@@ -68,14 +84,7 @@ struct marker { | |||
68 | */ | 84 | */ |
69 | #define __trace_mark(generic, name, call_private, format, args...) \ | 85 | #define __trace_mark(generic, name, call_private, format, args...) \ |
70 | do { \ | 86 | do { \ |
71 | static const char __mstrtab_##name[] \ | 87 | DEFINE_MARKER(name, format); \ |
72 | __attribute__((section("__markers_strings"))) \ | ||
73 | = #name "\0" format; \ | ||
74 | static struct marker __mark_##name \ | ||
75 | __attribute__((section("__markers"), aligned(8))) = \ | ||
76 | { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \ | ||
77 | 0, 0, marker_probe_cb, \ | ||
78 | { __mark_empty_function, NULL}, NULL, NULL, NULL }; \ | ||
79 | __mark_check_format(format, ## args); \ | 88 | __mark_check_format(format, ## args); \ |
80 | if (unlikely(__mark_##name.state)) { \ | 89 | if (unlikely(__mark_##name.state)) { \ |
81 | (*__mark_##name.call) \ | 90 | (*__mark_##name.call) \ |
@@ -89,14 +98,7 @@ struct marker { | |||
89 | { \ | 98 | { \ |
90 | register_trace_##tp_name(tp_cb); \ | 99 | register_trace_##tp_name(tp_cb); \ |
91 | } \ | 100 | } \ |
92 | static const char __mstrtab_##name[] \ | 101 | DEFINE_MARKER_TP(name, tp_name, tp_cb, format); \ |
93 | __attribute__((section("__markers_strings"))) \ | ||
94 | = #name "\0" format; \ | ||
95 | static struct marker __mark_##name \ | ||
96 | __attribute__((section("__markers"), aligned(8))) = \ | ||
97 | { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \ | ||
98 | 0, 0, marker_probe_cb, \ | ||
99 | { __mark_empty_function, NULL}, NULL, #tp_name, tp_cb };\ | ||
100 | __mark_check_format(format, ## args); \ | 102 | __mark_check_format(format, ## args); \ |
101 | (*__mark_##name.call)(&__mark_##name, call_private, \ | 103 | (*__mark_##name.call)(&__mark_##name, call_private, \ |
102 | ## args); \ | 104 | ## args); \ |
@@ -104,7 +106,11 @@ struct marker { | |||
104 | 106 | ||
105 | extern void marker_update_probe_range(struct marker *begin, | 107 | extern void marker_update_probe_range(struct marker *begin, |
106 | struct marker *end); | 108 | struct marker *end); |
109 | |||
110 | #define GET_MARKER(name) (__mark_##name) | ||
111 | |||
107 | #else /* !CONFIG_MARKERS */ | 112 | #else /* !CONFIG_MARKERS */ |
113 | #define DEFINE_MARKER(name, tp_name, tp_cb, format) | ||
108 | #define __trace_mark(generic, name, call_private, format, args...) \ | 114 | #define __trace_mark(generic, name, call_private, format, args...) \ |
109 | __mark_check_format(format, ## args) | 115 | __mark_check_format(format, ## args) |
110 | #define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \ | 116 | #define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \ |
@@ -118,6 +124,7 @@ extern void marker_update_probe_range(struct marker *begin, | |||
118 | static inline void marker_update_probe_range(struct marker *begin, | 124 | static inline void marker_update_probe_range(struct marker *begin, |
119 | struct marker *end) | 125 | struct marker *end) |
120 | { } | 126 | { } |
127 | #define GET_MARKER(name) | ||
121 | #endif /* CONFIG_MARKERS */ | 128 | #endif /* CONFIG_MARKERS */ |
122 | 129 | ||
123 | /** | 130 | /** |