diff options
author | Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> | 2007-10-19 02:41:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 14:53:54 -0400 |
commit | 8256e47cdc8923e9959eb1d7f95d80da538add80 (patch) | |
tree | 4702aa3ad7c9025f70314f1146e551b4e1dfcbb2 /include | |
parent | 09cadedbdc01f1a4bea1f427d4fb4642eaa19da9 (diff) |
Linux Kernel Markers
The marker activation functions sits in kernel/marker.c. A hash table is used
to keep track of the registered probes and armed markers, so the markers
within a newly loaded module that should be active can be activated at module
load time.
marker_query has been removed. marker_get_first, marker_get_next and
marker_release should be used as iterators on the markers.
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Acked-by: "Frank Ch. Eigler" <fche@redhat.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Mike Mason <mmlnx@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-generic/vmlinux.lds.h | 7 | ||||
-rw-r--r-- | include/linux/marker.h | 130 | ||||
-rw-r--r-- | include/linux/module.h | 12 |
3 files changed, 148 insertions, 1 deletions
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 5615440027ec..9f584cc5c5fb 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
@@ -12,7 +12,11 @@ | |||
12 | /* .data section */ | 12 | /* .data section */ |
13 | #define DATA_DATA \ | 13 | #define DATA_DATA \ |
14 | *(.data) \ | 14 | *(.data) \ |
15 | *(.data.init.refok) | 15 | *(.data.init.refok) \ |
16 | . = ALIGN(8); \ | ||
17 | VMLINUX_SYMBOL(__start___markers) = .; \ | ||
18 | *(__markers) \ | ||
19 | VMLINUX_SYMBOL(__stop___markers) = .; | ||
16 | 20 | ||
17 | #define RO_DATA(align) \ | 21 | #define RO_DATA(align) \ |
18 | . = ALIGN((align)); \ | 22 | . = ALIGN((align)); \ |
@@ -20,6 +24,7 @@ | |||
20 | VMLINUX_SYMBOL(__start_rodata) = .; \ | 24 | VMLINUX_SYMBOL(__start_rodata) = .; \ |
21 | *(.rodata) *(.rodata.*) \ | 25 | *(.rodata) *(.rodata.*) \ |
22 | *(__vermagic) /* Kernel version magic */ \ | 26 | *(__vermagic) /* Kernel version magic */ \ |
27 | *(__markers_strings) /* Markers: strings */ \ | ||
23 | } \ | 28 | } \ |
24 | \ | 29 | \ |
25 | .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \ | 30 | .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \ |
diff --git a/include/linux/marker.h b/include/linux/marker.h new file mode 100644 index 000000000000..8038d89b835d --- /dev/null +++ b/include/linux/marker.h | |||
@@ -0,0 +1,130 @@ | |||
1 | #ifndef _LINUX_MARKER_H | ||
2 | #define _LINUX_MARKER_H | ||
3 | |||
4 | /* | ||
5 | * Code markup for dynamic and static tracing. | ||
6 | * | ||
7 | * See Documentation/marker.txt. | ||
8 | * | ||
9 | * (C) Copyright 2006 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> | ||
10 | * | ||
11 | * This file is released under the GPLv2. | ||
12 | * See the file COPYING for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/types.h> | ||
16 | |||
17 | struct module; | ||
18 | struct marker; | ||
19 | |||
20 | /** | ||
21 | * marker_probe_func - Type of a marker probe function | ||
22 | * @mdata: pointer of type struct marker | ||
23 | * @private_data: caller site private data | ||
24 | * @fmt: format string | ||
25 | * @...: variable argument list | ||
26 | * | ||
27 | * Type of marker probe functions. They receive the mdata and need to parse the | ||
28 | * format string to recover the variable argument list. | ||
29 | */ | ||
30 | typedef void marker_probe_func(const struct marker *mdata, | ||
31 | void *private_data, const char *fmt, ...); | ||
32 | |||
33 | struct marker { | ||
34 | const char *name; /* Marker name */ | ||
35 | const char *format; /* Marker format string, describing the | ||
36 | * variable argument list. | ||
37 | */ | ||
38 | char state; /* Marker state. */ | ||
39 | marker_probe_func *call;/* Probe handler function pointer */ | ||
40 | void *private; /* Private probe data */ | ||
41 | } __attribute__((aligned(8))); | ||
42 | |||
43 | #ifdef CONFIG_MARKERS | ||
44 | |||
45 | /* | ||
46 | * Note : the empty asm volatile with read constraint is used here instead of a | ||
47 | * "used" attribute to fix a gcc 4.1.x bug. | ||
48 | * Make sure the alignment of the structure in the __markers section will | ||
49 | * not add unwanted padding between the beginning of the section and the | ||
50 | * structure. Force alignment to the same alignment as the section start. | ||
51 | */ | ||
52 | #define __trace_mark(name, call_data, format, args...) \ | ||
53 | do { \ | ||
54 | static const char __mstrtab_name_##name[] \ | ||
55 | __attribute__((section("__markers_strings"))) \ | ||
56 | = #name; \ | ||
57 | static const char __mstrtab_format_##name[] \ | ||
58 | __attribute__((section("__markers_strings"))) \ | ||
59 | = format; \ | ||
60 | static struct marker __mark_##name \ | ||
61 | __attribute__((section("__markers"), aligned(8))) = \ | ||
62 | { __mstrtab_name_##name, __mstrtab_format_##name, \ | ||
63 | 0, __mark_empty_function, NULL }; \ | ||
64 | asm volatile("" : : "i" (&__mark_##name)); \ | ||
65 | __mark_check_format(format, ## args); \ | ||
66 | if (unlikely(__mark_##name.state)) { \ | ||
67 | preempt_disable(); \ | ||
68 | (*__mark_##name.call) \ | ||
69 | (&__mark_##name, call_data, \ | ||
70 | format, ## args); \ | ||
71 | preempt_enable(); \ | ||
72 | } \ | ||
73 | } while (0) | ||
74 | |||
75 | extern void marker_update_probe_range(struct marker *begin, | ||
76 | struct marker *end, struct module *probe_module, int *refcount); | ||
77 | #else /* !CONFIG_MARKERS */ | ||
78 | #define __trace_mark(name, call_data, format, args...) \ | ||
79 | __mark_check_format(format, ## args) | ||
80 | static inline void marker_update_probe_range(struct marker *begin, | ||
81 | struct marker *end, struct module *probe_module, int *refcount) | ||
82 | { } | ||
83 | #endif /* CONFIG_MARKERS */ | ||
84 | |||
85 | /** | ||
86 | * trace_mark - Marker | ||
87 | * @name: marker name, not quoted. | ||
88 | * @format: format string | ||
89 | * @args...: variable argument list | ||
90 | * | ||
91 | * Places a marker. | ||
92 | */ | ||
93 | #define trace_mark(name, format, args...) \ | ||
94 | __trace_mark(name, NULL, format, ## args) | ||
95 | |||
96 | #define MARK_MAX_FORMAT_LEN 1024 | ||
97 | |||
98 | /** | ||
99 | * MARK_NOARGS - Format string for a marker with no argument. | ||
100 | */ | ||
101 | #define MARK_NOARGS " " | ||
102 | |||
103 | /* To be used for string format validity checking with gcc */ | ||
104 | static inline void __printf(1, 2) __mark_check_format(const char *fmt, ...) | ||
105 | { | ||
106 | } | ||
107 | |||
108 | extern marker_probe_func __mark_empty_function; | ||
109 | |||
110 | /* | ||
111 | * Connect a probe to a marker. | ||
112 | * private data pointer must be a valid allocated memory address, or NULL. | ||
113 | */ | ||
114 | extern int marker_probe_register(const char *name, const char *format, | ||
115 | marker_probe_func *probe, void *private); | ||
116 | |||
117 | /* | ||
118 | * Returns the private data given to marker_probe_register. | ||
119 | */ | ||
120 | extern void *marker_probe_unregister(const char *name); | ||
121 | /* | ||
122 | * Unregister a marker by providing the registered private data. | ||
123 | */ | ||
124 | extern void *marker_probe_unregister_private_data(void *private); | ||
125 | |||
126 | extern int marker_arm(const char *name); | ||
127 | extern int marker_disarm(const char *name); | ||
128 | extern void *marker_get_private_data(const char *name); | ||
129 | |||
130 | #endif | ||
diff --git a/include/linux/module.h b/include/linux/module.h index 642f325e4917..2cbc0b87e329 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/stringify.h> | 15 | #include <linux/stringify.h> |
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 <asm/local.h> | 19 | #include <asm/local.h> |
19 | 20 | ||
20 | #include <asm/module.h> | 21 | #include <asm/module.h> |
@@ -354,6 +355,10 @@ struct module | |||
354 | /* The command line arguments (may be mangled). People like | 355 | /* The command line arguments (may be mangled). People like |
355 | keeping pointers to this stuff */ | 356 | keeping pointers to this stuff */ |
356 | char *args; | 357 | char *args; |
358 | #ifdef CONFIG_MARKERS | ||
359 | struct marker *markers; | ||
360 | unsigned int num_markers; | ||
361 | #endif | ||
357 | }; | 362 | }; |
358 | #ifndef MODULE_ARCH_INIT | 363 | #ifndef MODULE_ARCH_INIT |
359 | #define MODULE_ARCH_INIT {} | 364 | #define MODULE_ARCH_INIT {} |
@@ -457,6 +462,8 @@ int unregister_module_notifier(struct notifier_block * nb); | |||
457 | 462 | ||
458 | extern void print_modules(void); | 463 | extern void print_modules(void); |
459 | 464 | ||
465 | extern void module_update_markers(struct module *probe_module, int *refcount); | ||
466 | |||
460 | #else /* !CONFIG_MODULES... */ | 467 | #else /* !CONFIG_MODULES... */ |
461 | #define EXPORT_SYMBOL(sym) | 468 | #define EXPORT_SYMBOL(sym) |
462 | #define EXPORT_SYMBOL_GPL(sym) | 469 | #define EXPORT_SYMBOL_GPL(sym) |
@@ -556,6 +563,11 @@ static inline void print_modules(void) | |||
556 | { | 563 | { |
557 | } | 564 | } |
558 | 565 | ||
566 | static inline void module_update_markers(struct module *probe_module, | ||
567 | int *refcount) | ||
568 | { | ||
569 | } | ||
570 | |||
559 | #endif /* CONFIG_MODULES */ | 571 | #endif /* CONFIG_MODULES */ |
560 | 572 | ||
561 | struct device_driver; | 573 | struct device_driver; |