diff options
author | Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> | 2008-11-14 17:47:39 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-16 03:01:29 -0500 |
commit | c1df1bd2c4d4b20c83755a0f41956b57aec4842a (patch) | |
tree | 08761333b0850c6acfb31d72d7777dccc135ebde /include/linux/marker.h | |
parent | a419246ac7c2d9282dfd843103702895bb3f3fd7 (diff) |
markers: auto enable tracepoints (new API : trace_mark_tp())
Impact: new API
Add a new API trace_mark_tp(), which declares a marker within a
tracepoint probe. When the marker is activated, the tracepoint is
automatically enabled.
No branch test is used at the marker site, because it would be a
duplicate of the branch already present in the tracepoint.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/linux/marker.h')
-rw-r--r-- | include/linux/marker.h | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/include/linux/marker.h b/include/linux/marker.h index 05ec0df37089..57a307018ceb 100644 --- a/include/linux/marker.h +++ b/include/linux/marker.h | |||
@@ -49,6 +49,8 @@ struct marker { | |||
49 | void (*call)(const struct marker *mdata, void *call_private, ...); | 49 | void (*call)(const struct marker *mdata, void *call_private, ...); |
50 | struct marker_probe_closure single; | 50 | struct marker_probe_closure single; |
51 | struct marker_probe_closure *multi; | 51 | struct marker_probe_closure *multi; |
52 | const char *tp_name; /* Optional tracepoint name */ | ||
53 | void *tp_cb; /* Optional tracepoint callback */ | ||
52 | } __attribute__((aligned(8))); | 54 | } __attribute__((aligned(8))); |
53 | 55 | ||
54 | #ifdef CONFIG_MARKERS | 56 | #ifdef CONFIG_MARKERS |
@@ -73,7 +75,7 @@ struct marker { | |||
73 | __attribute__((section("__markers"), aligned(8))) = \ | 75 | __attribute__((section("__markers"), aligned(8))) = \ |
74 | { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \ | 76 | { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \ |
75 | 0, 0, marker_probe_cb, \ | 77 | 0, 0, marker_probe_cb, \ |
76 | { __mark_empty_function, NULL}, NULL }; \ | 78 | { __mark_empty_function, NULL}, NULL, NULL, NULL }; \ |
77 | __mark_check_format(format, ## args); \ | 79 | __mark_check_format(format, ## args); \ |
78 | if (unlikely(__mark_##name.state)) { \ | 80 | if (unlikely(__mark_##name.state)) { \ |
79 | (*__mark_##name.call) \ | 81 | (*__mark_##name.call) \ |
@@ -81,11 +83,38 @@ struct marker { | |||
81 | } \ | 83 | } \ |
82 | } while (0) | 84 | } while (0) |
83 | 85 | ||
86 | #define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \ | ||
87 | do { \ | ||
88 | void __check_tp_type(void) \ | ||
89 | { \ | ||
90 | register_trace_##tp_name(tp_cb); \ | ||
91 | } \ | ||
92 | static const char __mstrtab_##name[] \ | ||
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); \ | ||
101 | (*__mark_##name.call)(&__mark_##name, call_private, \ | ||
102 | ## args); \ | ||
103 | } while (0) | ||
104 | |||
84 | extern void marker_update_probe_range(struct marker *begin, | 105 | extern void marker_update_probe_range(struct marker *begin, |
85 | struct marker *end); | 106 | struct marker *end); |
86 | #else /* !CONFIG_MARKERS */ | 107 | #else /* !CONFIG_MARKERS */ |
87 | #define __trace_mark(generic, name, call_private, format, args...) \ | 108 | #define __trace_mark(generic, name, call_private, format, args...) \ |
88 | __mark_check_format(format, ## args) | 109 | __mark_check_format(format, ## args) |
110 | #define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \ | ||
111 | do { \ | ||
112 | void __check_tp_type(void) \ | ||
113 | { \ | ||
114 | register_trace_##tp_name(tp_cb); \ | ||
115 | } \ | ||
116 | __mark_check_format(format, ## args); \ | ||
117 | } while (0) | ||
89 | static inline void marker_update_probe_range(struct marker *begin, | 118 | static inline void marker_update_probe_range(struct marker *begin, |
90 | struct marker *end) | 119 | struct marker *end) |
91 | { } | 120 | { } |
@@ -118,6 +147,20 @@ static inline void marker_update_probe_range(struct marker *begin, | |||
118 | __trace_mark(1, name, NULL, format, ## args) | 147 | __trace_mark(1, name, NULL, format, ## args) |
119 | 148 | ||
120 | /** | 149 | /** |
150 | * trace_mark_tp - Marker in a tracepoint callback | ||
151 | * @name: marker name, not quoted. | ||
152 | * @tp_name: tracepoint name, not quoted. | ||
153 | * @tp_cb: tracepoint callback. Should have an associated global symbol so it | ||
154 | * is not optimized away by the compiler (should not be static). | ||
155 | * @format: format string | ||
156 | * @args...: variable argument list | ||
157 | * | ||
158 | * Places a marker in a tracepoint callback. | ||
159 | */ | ||
160 | #define trace_mark_tp(name, tp_name, tp_cb, format, args...) \ | ||
161 | __trace_mark_tp(name, NULL, tp_name, tp_cb, format, ## args) | ||
162 | |||
163 | /** | ||
121 | * MARK_NOARGS - Format string for a marker with no argument. | 164 | * MARK_NOARGS - Format string for a marker with no argument. |
122 | */ | 165 | */ |
123 | #define MARK_NOARGS " " | 166 | #define MARK_NOARGS " " |