diff options
-rw-r--r-- | include/linux/marker.h | 1 | ||||
-rw-r--r-- | samples/Kconfig | 5 | ||||
-rw-r--r-- | samples/Makefile | 3 | ||||
-rw-r--r-- | samples/markers/Makefile | 4 | ||||
-rw-r--r-- | samples/markers/marker-example.c | 54 | ||||
-rw-r--r-- | samples/markers/probe-example.c | 98 |
6 files changed, 164 insertions, 1 deletions
diff --git a/include/linux/marker.h b/include/linux/marker.h index 8038d89b835d..5f36cf946bcb 100644 --- a/include/linux/marker.h +++ b/include/linux/marker.h | |||
@@ -61,7 +61,6 @@ struct marker { | |||
61 | __attribute__((section("__markers"), aligned(8))) = \ | 61 | __attribute__((section("__markers"), aligned(8))) = \ |
62 | { __mstrtab_name_##name, __mstrtab_format_##name, \ | 62 | { __mstrtab_name_##name, __mstrtab_format_##name, \ |
63 | 0, __mark_empty_function, NULL }; \ | 63 | 0, __mark_empty_function, NULL }; \ |
64 | asm volatile("" : : "i" (&__mark_##name)); \ | ||
65 | __mark_check_format(format, ## args); \ | 64 | __mark_check_format(format, ## args); \ |
66 | if (unlikely(__mark_##name.state)) { \ | 65 | if (unlikely(__mark_##name.state)) { \ |
67 | preempt_disable(); \ | 66 | preempt_disable(); \ |
diff --git a/samples/Kconfig b/samples/Kconfig index b46b4cf4382f..57bb2236952c 100644 --- a/samples/Kconfig +++ b/samples/Kconfig | |||
@@ -7,5 +7,10 @@ menuconfig SAMPLES | |||
7 | 7 | ||
8 | if SAMPLES | 8 | if SAMPLES |
9 | 9 | ||
10 | config SAMPLE_MARKERS | ||
11 | tristate "Build markers examples -- loadable modules only" | ||
12 | depends on MARKERS && m | ||
13 | help | ||
14 | This build markers example modules. | ||
10 | 15 | ||
11 | endif # SAMPLES | 16 | endif # SAMPLES |
diff --git a/samples/Makefile b/samples/Makefile new file mode 100644 index 000000000000..5a4f0b6bcbed --- /dev/null +++ b/samples/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | # Makefile for Linux samples code | ||
2 | |||
3 | obj-$(CONFIG_SAMPLES) += markers/ | ||
diff --git a/samples/markers/Makefile b/samples/markers/Makefile new file mode 100644 index 000000000000..6d7231265f0f --- /dev/null +++ b/samples/markers/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # builds the kprobes example kernel modules; | ||
2 | # then to use one (as root): insmod <module_name.ko> | ||
3 | |||
4 | obj-$(CONFIG_SAMPLE_MARKERS) += probe-example.o marker-example.o | ||
diff --git a/samples/markers/marker-example.c b/samples/markers/marker-example.c new file mode 100644 index 000000000000..e787c6d16dd7 --- /dev/null +++ b/samples/markers/marker-example.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* marker-example.c | ||
2 | * | ||
3 | * Executes a marker when /proc/marker-example is opened. | ||
4 | * | ||
5 | * (C) Copyright 2007 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> | ||
6 | * | ||
7 | * This file is released under the GPLv2. | ||
8 | * See the file COPYING for more details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/marker.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/proc_fs.h> | ||
15 | |||
16 | struct proc_dir_entry *pentry_example; | ||
17 | |||
18 | static int my_open(struct inode *inode, struct file *file) | ||
19 | { | ||
20 | int i; | ||
21 | |||
22 | trace_mark(subsystem_event, "%d %s", 123, "example string"); | ||
23 | for (i = 0; i < 10; i++) | ||
24 | trace_mark(subsystem_eventb, MARK_NOARGS); | ||
25 | return -EPERM; | ||
26 | } | ||
27 | |||
28 | static struct file_operations mark_ops = { | ||
29 | .open = my_open, | ||
30 | }; | ||
31 | |||
32 | static int example_init(void) | ||
33 | { | ||
34 | printk(KERN_ALERT "example init\n"); | ||
35 | pentry_example = create_proc_entry("marker-example", 0444, NULL); | ||
36 | if (pentry_example) | ||
37 | pentry_example->proc_fops = &mark_ops; | ||
38 | else | ||
39 | return -EPERM; | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static void example_exit(void) | ||
44 | { | ||
45 | printk(KERN_ALERT "example exit\n"); | ||
46 | remove_proc_entry("marker-example", NULL); | ||
47 | } | ||
48 | |||
49 | module_init(example_init) | ||
50 | module_exit(example_exit) | ||
51 | |||
52 | MODULE_LICENSE("GPL"); | ||
53 | MODULE_AUTHOR("Mathieu Desnoyers"); | ||
54 | MODULE_DESCRIPTION("Marker example"); | ||
diff --git a/samples/markers/probe-example.c b/samples/markers/probe-example.c new file mode 100644 index 000000000000..238b2e384fc8 --- /dev/null +++ b/samples/markers/probe-example.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* probe-example.c | ||
2 | * | ||
3 | * Connects two functions to marker call sites. | ||
4 | * | ||
5 | * (C) Copyright 2007 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> | ||
6 | * | ||
7 | * This file is released under the GPLv2. | ||
8 | * See the file COPYING for more details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/sched.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/marker.h> | ||
15 | #include <asm/atomic.h> | ||
16 | |||
17 | struct probe_data { | ||
18 | const char *name; | ||
19 | const char *format; | ||
20 | marker_probe_func *probe_func; | ||
21 | }; | ||
22 | |||
23 | void probe_subsystem_event(const struct marker *mdata, void *private, | ||
24 | const char *format, ...) | ||
25 | { | ||
26 | va_list ap; | ||
27 | /* Declare args */ | ||
28 | unsigned int value; | ||
29 | const char *mystr; | ||
30 | |||
31 | /* Assign args */ | ||
32 | va_start(ap, format); | ||
33 | value = va_arg(ap, typeof(value)); | ||
34 | mystr = va_arg(ap, typeof(mystr)); | ||
35 | |||
36 | /* Call printk */ | ||
37 | printk(KERN_DEBUG "Value %u, string %s\n", value, mystr); | ||
38 | |||
39 | /* or count, check rights, serialize data in a buffer */ | ||
40 | |||
41 | va_end(ap); | ||
42 | } | ||
43 | |||
44 | atomic_t eventb_count = ATOMIC_INIT(0); | ||
45 | |||
46 | void probe_subsystem_eventb(const struct marker *mdata, void *private, | ||
47 | const char *format, ...) | ||
48 | { | ||
49 | /* Increment counter */ | ||
50 | atomic_inc(&eventb_count); | ||
51 | } | ||
52 | |||
53 | static struct probe_data probe_array[] = | ||
54 | { | ||
55 | { .name = "subsystem_event", | ||
56 | .format = "%d %s", | ||
57 | .probe_func = probe_subsystem_event }, | ||
58 | { .name = "subsystem_eventb", | ||
59 | .format = MARK_NOARGS, | ||
60 | .probe_func = probe_subsystem_eventb }, | ||
61 | }; | ||
62 | |||
63 | static int __init probe_init(void) | ||
64 | { | ||
65 | int result; | ||
66 | int i; | ||
67 | |||
68 | for (i = 0; i < ARRAY_SIZE(probe_array); i++) { | ||
69 | result = marker_probe_register(probe_array[i].name, | ||
70 | probe_array[i].format, | ||
71 | probe_array[i].probe_func, &probe_array[i]); | ||
72 | if (result) | ||
73 | printk(KERN_INFO "Unable to register probe %s\n", | ||
74 | probe_array[i].name); | ||
75 | result = marker_arm(probe_array[i].name); | ||
76 | if (result) | ||
77 | printk(KERN_INFO "Unable to arm probe %s\n", | ||
78 | probe_array[i].name); | ||
79 | } | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static void __exit probe_fini(void) | ||
84 | { | ||
85 | int i; | ||
86 | |||
87 | for (i = 0; i < ARRAY_SIZE(probe_array); i++) | ||
88 | marker_probe_unregister(probe_array[i].name); | ||
89 | printk(KERN_INFO "Number of event b : %u\n", | ||
90 | atomic_read(&eventb_count)); | ||
91 | } | ||
92 | |||
93 | module_init(probe_init); | ||
94 | module_exit(probe_fini); | ||
95 | |||
96 | MODULE_LICENSE("GPL"); | ||
97 | MODULE_AUTHOR("Mathieu Desnoyers"); | ||
98 | MODULE_DESCRIPTION("SUBSYSTEM Probe"); | ||