diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-generic/vmlinux.lds.h | 6 | ||||
-rw-r--r-- | include/linux/module.h | 17 | ||||
-rw-r--r-- | include/linux/tracepoint.h | 127 |
3 files changed, 149 insertions, 1 deletions
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 7440a0dceddb..3d8e472a09c8 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
@@ -52,7 +52,10 @@ | |||
52 | . = ALIGN(8); \ | 52 | . = ALIGN(8); \ |
53 | VMLINUX_SYMBOL(__start___markers) = .; \ | 53 | VMLINUX_SYMBOL(__start___markers) = .; \ |
54 | *(__markers) \ | 54 | *(__markers) \ |
55 | VMLINUX_SYMBOL(__stop___markers) = .; | 55 | VMLINUX_SYMBOL(__stop___markers) = .; \ |
56 | VMLINUX_SYMBOL(__start___tracepoints) = .; \ | ||
57 | *(__tracepoints) \ | ||
58 | VMLINUX_SYMBOL(__stop___tracepoints) = .; | ||
56 | 59 | ||
57 | #define RO_DATA(align) \ | 60 | #define RO_DATA(align) \ |
58 | . = ALIGN((align)); \ | 61 | . = ALIGN((align)); \ |
@@ -61,6 +64,7 @@ | |||
61 | *(.rodata) *(.rodata.*) \ | 64 | *(.rodata) *(.rodata.*) \ |
62 | *(__vermagic) /* Kernel version magic */ \ | 65 | *(__vermagic) /* Kernel version magic */ \ |
63 | *(__markers_strings) /* Markers: strings */ \ | 66 | *(__markers_strings) /* Markers: strings */ \ |
67 | *(__tracepoints_strings)/* Tracepoints: strings */ \ | ||
64 | } \ | 68 | } \ |
65 | \ | 69 | \ |
66 | .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \ | 70 | .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \ |
diff --git a/include/linux/module.h b/include/linux/module.h index 68e09557c951..8b6113503863 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/kobject.h> | 16 | #include <linux/kobject.h> |
17 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
18 | #include <linux/marker.h> | 18 | #include <linux/marker.h> |
19 | #include <linux/tracepoint.h> | ||
19 | #include <asm/local.h> | 20 | #include <asm/local.h> |
20 | 21 | ||
21 | #include <asm/module.h> | 22 | #include <asm/module.h> |
@@ -331,6 +332,10 @@ struct module | |||
331 | struct marker *markers; | 332 | struct marker *markers; |
332 | unsigned int num_markers; | 333 | unsigned int num_markers; |
333 | #endif | 334 | #endif |
335 | #ifdef CONFIG_TRACEPOINTS | ||
336 | struct tracepoint *tracepoints; | ||
337 | unsigned int num_tracepoints; | ||
338 | #endif | ||
334 | 339 | ||
335 | #ifdef CONFIG_MODULE_UNLOAD | 340 | #ifdef CONFIG_MODULE_UNLOAD |
336 | /* What modules depend on me? */ | 341 | /* What modules depend on me? */ |
@@ -454,6 +459,9 @@ extern void print_modules(void); | |||
454 | 459 | ||
455 | extern void module_update_markers(void); | 460 | extern void module_update_markers(void); |
456 | 461 | ||
462 | extern void module_update_tracepoints(void); | ||
463 | extern int module_get_iter_tracepoints(struct tracepoint_iter *iter); | ||
464 | |||
457 | #else /* !CONFIG_MODULES... */ | 465 | #else /* !CONFIG_MODULES... */ |
458 | #define EXPORT_SYMBOL(sym) | 466 | #define EXPORT_SYMBOL(sym) |
459 | #define EXPORT_SYMBOL_GPL(sym) | 467 | #define EXPORT_SYMBOL_GPL(sym) |
@@ -558,6 +566,15 @@ static inline void module_update_markers(void) | |||
558 | { | 566 | { |
559 | } | 567 | } |
560 | 568 | ||
569 | static inline void module_update_tracepoints(void) | ||
570 | { | ||
571 | } | ||
572 | |||
573 | static inline int module_get_iter_tracepoints(struct tracepoint_iter *iter) | ||
574 | { | ||
575 | return 0; | ||
576 | } | ||
577 | |||
561 | #endif /* CONFIG_MODULES */ | 578 | #endif /* CONFIG_MODULES */ |
562 | 579 | ||
563 | struct device_driver; | 580 | struct device_driver; |
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h new file mode 100644 index 000000000000..e623a6fca5c3 --- /dev/null +++ b/include/linux/tracepoint.h | |||
@@ -0,0 +1,127 @@ | |||
1 | #ifndef _LINUX_TRACEPOINT_H | ||
2 | #define _LINUX_TRACEPOINT_H | ||
3 | |||
4 | /* | ||
5 | * Kernel Tracepoint API. | ||
6 | * | ||
7 | * See Documentation/tracepoint.txt. | ||
8 | * | ||
9 | * (C) Copyright 2008 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> | ||
10 | * | ||
11 | * Heavily inspired from the Linux Kernel Markers. | ||
12 | * | ||
13 | * This file is released under the GPLv2. | ||
14 | * See the file COPYING for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/types.h> | ||
18 | #include <linux/rcupdate.h> | ||
19 | |||
20 | struct module; | ||
21 | struct tracepoint; | ||
22 | |||
23 | struct tracepoint { | ||
24 | const char *name; /* Tracepoint name */ | ||
25 | int state; /* State. */ | ||
26 | void **funcs; | ||
27 | } __attribute__((aligned(8))); | ||
28 | |||
29 | |||
30 | #define TPPROTO(args...) args | ||
31 | #define TPARGS(args...) args | ||
32 | |||
33 | #ifdef CONFIG_TRACEPOINTS | ||
34 | |||
35 | /* | ||
36 | * it_func[0] is never NULL because there is at least one element in the array | ||
37 | * when the array itself is non NULL. | ||
38 | */ | ||
39 | #define __DO_TRACE(tp, proto, args) \ | ||
40 | do { \ | ||
41 | void **it_func; \ | ||
42 | \ | ||
43 | rcu_read_lock_sched(); \ | ||
44 | it_func = rcu_dereference((tp)->funcs); \ | ||
45 | if (it_func) { \ | ||
46 | do { \ | ||
47 | ((void(*)(proto))(*it_func))(args); \ | ||
48 | } while (*(++it_func)); \ | ||
49 | } \ | ||
50 | rcu_read_unlock_sched(); \ | ||
51 | } while (0) | ||
52 | |||
53 | /* | ||
54 | * Make sure the alignment of the structure in the __tracepoints section will | ||
55 | * not add unwanted padding between the beginning of the section and the | ||
56 | * structure. Force alignment to the same alignment as the section start. | ||
57 | */ | ||
58 | #define DEFINE_TRACE(name, proto, args) \ | ||
59 | static inline void trace_##name(proto) \ | ||
60 | { \ | ||
61 | static const char __tpstrtab_##name[] \ | ||
62 | __attribute__((section("__tracepoints_strings"))) \ | ||
63 | = #name ":" #proto; \ | ||
64 | static struct tracepoint __tracepoint_##name \ | ||
65 | __attribute__((section("__tracepoints"), aligned(8))) = \ | ||
66 | { __tpstrtab_##name, 0, NULL }; \ | ||
67 | if (unlikely(__tracepoint_##name.state)) \ | ||
68 | __DO_TRACE(&__tracepoint_##name, \ | ||
69 | TPPROTO(proto), TPARGS(args)); \ | ||
70 | } \ | ||
71 | static inline int register_trace_##name(void (*probe)(proto)) \ | ||
72 | { \ | ||
73 | return tracepoint_probe_register(#name ":" #proto, \ | ||
74 | (void *)probe); \ | ||
75 | } \ | ||
76 | static inline void unregister_trace_##name(void (*probe)(proto))\ | ||
77 | { \ | ||
78 | tracepoint_probe_unregister(#name ":" #proto, \ | ||
79 | (void *)probe); \ | ||
80 | } | ||
81 | |||
82 | extern void tracepoint_update_probe_range(struct tracepoint *begin, | ||
83 | struct tracepoint *end); | ||
84 | |||
85 | #else /* !CONFIG_TRACEPOINTS */ | ||
86 | #define DEFINE_TRACE(name, proto, args) \ | ||
87 | static inline void _do_trace_##name(struct tracepoint *tp, proto) \ | ||
88 | { } \ | ||
89 | static inline void trace_##name(proto) \ | ||
90 | { } \ | ||
91 | static inline int register_trace_##name(void (*probe)(proto)) \ | ||
92 | { \ | ||
93 | return -ENOSYS; \ | ||
94 | } \ | ||
95 | static inline void unregister_trace_##name(void (*probe)(proto))\ | ||
96 | { } | ||
97 | |||
98 | static inline void tracepoint_update_probe_range(struct tracepoint *begin, | ||
99 | struct tracepoint *end) | ||
100 | { } | ||
101 | #endif /* CONFIG_TRACEPOINTS */ | ||
102 | |||
103 | /* | ||
104 | * Connect a probe to a tracepoint. | ||
105 | * Internal API, should not be used directly. | ||
106 | */ | ||
107 | extern int tracepoint_probe_register(const char *name, void *probe); | ||
108 | |||
109 | /* | ||
110 | * Disconnect a probe from a tracepoint. | ||
111 | * Internal API, should not be used directly. | ||
112 | */ | ||
113 | extern int tracepoint_probe_unregister(const char *name, void *probe); | ||
114 | |||
115 | struct tracepoint_iter { | ||
116 | struct module *module; | ||
117 | struct tracepoint *tracepoint; | ||
118 | }; | ||
119 | |||
120 | extern void tracepoint_iter_start(struct tracepoint_iter *iter); | ||
121 | extern void tracepoint_iter_next(struct tracepoint_iter *iter); | ||
122 | extern void tracepoint_iter_stop(struct tracepoint_iter *iter); | ||
123 | extern void tracepoint_iter_reset(struct tracepoint_iter *iter); | ||
124 | extern int tracepoint_get_iter_range(struct tracepoint **tracepoint, | ||
125 | struct tracepoint *begin, struct tracepoint *end); | ||
126 | |||
127 | #endif | ||