aboutsummaryrefslogtreecommitdiffstats
path: root/samples
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-03-04 14:00:05 -0500
committerIngo Molnar <mingo@kernel.org>2015-03-04 14:00:05 -0500
commit0bbdb4258bd116d8cd5d209e8d5b29bae516e5b3 (patch)
treec607302701f7a7942f2e76391fdb406ec86628d5 /samples
parentbd624d75db21ea5402f9ecf4450b311794d80352 (diff)
parent13a7a6ac0a11197edcd0f756a035f472b42cdf8b (diff)
Merge tag 'v4.0-rc2' into timers/core, to refresh the tree before pulling more changes
Diffstat (limited to 'samples')
-rw-r--r--samples/Kconfig7
-rw-r--r--samples/Makefile2
-rw-r--r--samples/bpf/test_maps.c4
-rw-r--r--samples/livepatch/Makefile1
-rw-r--r--samples/livepatch/livepatch-sample.c91
-rw-r--r--samples/seccomp/bpf-fancy.c4
-rw-r--r--samples/seccomp/bpf-helper.c6
-rw-r--r--samples/trace_events/trace-events-sample.c80
-rw-r--r--samples/trace_events/trace-events-sample.h328
9 files changed, 505 insertions, 18 deletions
diff --git a/samples/Kconfig b/samples/Kconfig
index 6181c2cc9ca0..224ebb46bed5 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -63,4 +63,11 @@ config SAMPLE_RPMSG_CLIENT
63 to communicate with an AMP-configured remote processor over 63 to communicate with an AMP-configured remote processor over
64 the rpmsg bus. 64 the rpmsg bus.
65 65
66config SAMPLE_LIVEPATCH
67 tristate "Build live patching sample -- loadable modules only"
68 depends on LIVEPATCH && m
69 help
70 Builds a sample live patch that replaces the procfs handler
71 for /proc/cmdline to print "this has been live patched".
72
66endif # SAMPLES 73endif # SAMPLES
diff --git a/samples/Makefile b/samples/Makefile
index 1a60c62e2045..f00257bcc5a7 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -1,4 +1,4 @@
1# Makefile for Linux samples code 1# Makefile for Linux samples code
2 2
3obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ \ 3obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \
4 hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ 4 hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/
diff --git a/samples/bpf/test_maps.c b/samples/bpf/test_maps.c
index e286b42307f3..6299ee95cd11 100644
--- a/samples/bpf/test_maps.c
+++ b/samples/bpf/test_maps.c
@@ -69,9 +69,9 @@ static void test_hashmap_sanity(int i, void *data)
69 69
70 /* iterate over two elements */ 70 /* iterate over two elements */
71 assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 && 71 assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 &&
72 next_key == 2); 72 (next_key == 1 || next_key == 2));
73 assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 && 73 assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 &&
74 next_key == 1); 74 (next_key == 1 || next_key == 2));
75 assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 && 75 assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 &&
76 errno == ENOENT); 76 errno == ENOENT);
77 77
diff --git a/samples/livepatch/Makefile b/samples/livepatch/Makefile
new file mode 100644
index 000000000000..10319d7ea0b1
--- /dev/null
+++ b/samples/livepatch/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_SAMPLE_LIVEPATCH) += livepatch-sample.o
diff --git a/samples/livepatch/livepatch-sample.c b/samples/livepatch/livepatch-sample.c
new file mode 100644
index 000000000000..fb8c8614e728
--- /dev/null
+++ b/samples/livepatch/livepatch-sample.c
@@ -0,0 +1,91 @@
1/*
2 * livepatch-sample.c - Kernel Live Patching Sample Module
3 *
4 * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/module.h>
21#include <linux/kernel.h>
22#include <linux/livepatch.h>
23
24/*
25 * This (dumb) live patch overrides the function that prints the
26 * kernel boot cmdline when /proc/cmdline is read.
27 *
28 * Example:
29 *
30 * $ cat /proc/cmdline
31 * <your cmdline>
32 *
33 * $ insmod livepatch-sample.ko
34 * $ cat /proc/cmdline
35 * this has been live patched
36 *
37 * $ echo 0 > /sys/kernel/livepatch/livepatch_sample/enabled
38 * $ cat /proc/cmdline
39 * <your cmdline>
40 */
41
42#include <linux/seq_file.h>
43static int livepatch_cmdline_proc_show(struct seq_file *m, void *v)
44{
45 seq_printf(m, "%s\n", "this has been live patched");
46 return 0;
47}
48
49static struct klp_func funcs[] = {
50 {
51 .old_name = "cmdline_proc_show",
52 .new_func = livepatch_cmdline_proc_show,
53 }, { }
54};
55
56static struct klp_object objs[] = {
57 {
58 /* name being NULL means vmlinux */
59 .funcs = funcs,
60 }, { }
61};
62
63static struct klp_patch patch = {
64 .mod = THIS_MODULE,
65 .objs = objs,
66};
67
68static int livepatch_init(void)
69{
70 int ret;
71
72 ret = klp_register_patch(&patch);
73 if (ret)
74 return ret;
75 ret = klp_enable_patch(&patch);
76 if (ret) {
77 WARN_ON(klp_unregister_patch(&patch));
78 return ret;
79 }
80 return 0;
81}
82
83static void livepatch_exit(void)
84{
85 WARN_ON(klp_disable_patch(&patch));
86 WARN_ON(klp_unregister_patch(&patch));
87}
88
89module_init(livepatch_init);
90module_exit(livepatch_exit);
91MODULE_LICENSE("GPL");
diff --git a/samples/seccomp/bpf-fancy.c b/samples/seccomp/bpf-fancy.c
index 8eb483aaec46..e8b24f443709 100644
--- a/samples/seccomp/bpf-fancy.c
+++ b/samples/seccomp/bpf-fancy.c
@@ -25,7 +25,9 @@
25 25
26int main(int argc, char **argv) 26int main(int argc, char **argv)
27{ 27{
28 struct bpf_labels l; 28 struct bpf_labels l = {
29 .count = 0,
30 };
29 static const char msg1[] = "Please type something: "; 31 static const char msg1[] = "Please type something: ";
30 static const char msg2[] = "You typed: "; 32 static const char msg2[] = "You typed: ";
31 char buf[256]; 33 char buf[256];
diff --git a/samples/seccomp/bpf-helper.c b/samples/seccomp/bpf-helper.c
index 579cfe331886..05cb4d5ff9f5 100644
--- a/samples/seccomp/bpf-helper.c
+++ b/samples/seccomp/bpf-helper.c
@@ -10,6 +10,7 @@
10 */ 10 */
11 11
12#include <stdio.h> 12#include <stdio.h>
13#include <stdlib.h>
13#include <string.h> 14#include <string.h>
14 15
15#include "bpf-helper.h" 16#include "bpf-helper.h"
@@ -63,6 +64,11 @@ __u32 seccomp_bpf_label(struct bpf_labels *labels, const char *label)
63{ 64{
64 struct __bpf_label *begin = labels->labels, *end; 65 struct __bpf_label *begin = labels->labels, *end;
65 int id; 66 int id;
67
68 if (labels->count == BPF_LABELS_MAX) {
69 fprintf(stderr, "Too many labels\n");
70 exit(1);
71 }
66 if (labels->count == 0) { 72 if (labels->count == 0) {
67 begin->label = label; 73 begin->label = label;
68 begin->location = 0xffffffff; 74 begin->location = 0xffffffff;
diff --git a/samples/trace_events/trace-events-sample.c b/samples/trace_events/trace-events-sample.c
index aabc4e970911..880a7d1d27d2 100644
--- a/samples/trace_events/trace-events-sample.c
+++ b/samples/trace_events/trace-events-sample.c
@@ -10,12 +10,38 @@
10#define CREATE_TRACE_POINTS 10#define CREATE_TRACE_POINTS
11#include "trace-events-sample.h" 11#include "trace-events-sample.h"
12 12
13static const char *random_strings[] = {
14 "Mother Goose",
15 "Snoopy",
16 "Gandalf",
17 "Frodo",
18 "One ring to rule them all"
19};
13 20
14static void simple_thread_func(int cnt) 21static void simple_thread_func(int cnt)
15{ 22{
23 int array[6];
24 int len = cnt % 5;
25 int i;
26
16 set_current_state(TASK_INTERRUPTIBLE); 27 set_current_state(TASK_INTERRUPTIBLE);
17 schedule_timeout(HZ); 28 schedule_timeout(HZ);
18 trace_foo_bar("hello", cnt); 29
30 for (i = 0; i < len; i++)
31 array[i] = i + 1;
32 array[i] = 0;
33
34 /* Silly tracepoints */
35 trace_foo_bar("hello", cnt, array, random_strings[len],
36 tsk_cpus_allowed(current));
37
38 trace_foo_with_template_simple("HELLO", cnt);
39
40 trace_foo_bar_with_cond("Some times print", cnt);
41
42 trace_foo_with_template_cond("prints other times", cnt);
43
44 trace_foo_with_template_print("I have to be different", cnt);
19} 45}
20 46
21static int simple_thread(void *arg) 47static int simple_thread(void *arg)
@@ -29,6 +55,53 @@ static int simple_thread(void *arg)
29} 55}
30 56
31static struct task_struct *simple_tsk; 57static struct task_struct *simple_tsk;
58static struct task_struct *simple_tsk_fn;
59
60static void simple_thread_func_fn(int cnt)
61{
62 set_current_state(TASK_INTERRUPTIBLE);
63 schedule_timeout(HZ);
64
65 /* More silly tracepoints */
66 trace_foo_bar_with_fn("Look at me", cnt);
67 trace_foo_with_template_fn("Look at me too", cnt);
68}
69
70static int simple_thread_fn(void *arg)
71{
72 int cnt = 0;
73
74 while (!kthread_should_stop())
75 simple_thread_func_fn(cnt++);
76
77 return 0;
78}
79
80static DEFINE_MUTEX(thread_mutex);
81
82void foo_bar_reg(void)
83{
84 pr_info("Starting thread for foo_bar_fn\n");
85 /*
86 * We shouldn't be able to start a trace when the module is
87 * unloading (there's other locks to prevent that). But
88 * for consistency sake, we still take the thread_mutex.
89 */
90 mutex_lock(&thread_mutex);
91 simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn");
92 mutex_unlock(&thread_mutex);
93}
94
95void foo_bar_unreg(void)
96{
97 pr_info("Killing thread for foo_bar_fn\n");
98 /* protect against module unloading */
99 mutex_lock(&thread_mutex);
100 if (simple_tsk_fn)
101 kthread_stop(simple_tsk_fn);
102 simple_tsk_fn = NULL;
103 mutex_unlock(&thread_mutex);
104}
32 105
33static int __init trace_event_init(void) 106static int __init trace_event_init(void)
34{ 107{
@@ -42,6 +115,11 @@ static int __init trace_event_init(void)
42static void __exit trace_event_exit(void) 115static void __exit trace_event_exit(void)
43{ 116{
44 kthread_stop(simple_tsk); 117 kthread_stop(simple_tsk);
118 mutex_lock(&thread_mutex);
119 if (simple_tsk_fn)
120 kthread_stop(simple_tsk_fn);
121 simple_tsk_fn = NULL;
122 mutex_unlock(&thread_mutex);
45} 123}
46 124
47module_init(trace_event_init); 125module_init(trace_event_init);
diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h
index 476429281389..a2c8b02b6359 100644
--- a/samples/trace_events/trace-events-sample.h
+++ b/samples/trace_events/trace-events-sample.h
@@ -1,6 +1,6 @@
1/* 1/*
2 * If TRACE_SYSTEM is defined, that will be the directory created 2 * If TRACE_SYSTEM is defined, that will be the directory created
3 * in the ftrace directory under /sys/kernel/debug/tracing/events/<system> 3 * in the ftrace directory under /sys/kernel/tracing/events/<system>
4 * 4 *
5 * The define_trace.h below will also look for a file name of 5 * The define_trace.h below will also look for a file name of
6 * TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here. 6 * TRACE_SYSTEM.h where TRACE_SYSTEM is what is defined here.
@@ -54,45 +54,347 @@
54 * Here it is simply "foo, bar". 54 * Here it is simply "foo, bar".
55 * 55 *
56 * struct: This defines the way the data will be stored in the ring buffer. 56 * struct: This defines the way the data will be stored in the ring buffer.
57 * There are currently two types of elements. __field and __array. 57 * The items declared here become part of a special structure
58 * a __field is broken up into (type, name). Where type can be any 58 * called "__entry", which can be used in the fast_assign part of the
59 * primitive type (integer, long or pointer). __field_struct() can 59 * TRACE_EVENT macro.
60 * be any static complex data value (struct, union, but not an array). 60 *
61 * For an array. there are three fields. (type, name, size). The 61 * Here are the currently defined types you can use:
62 * type of elements in the array, the name of the field and the size 62 *
63 * of the array. 63 * __field : Is broken up into type and name. Where type can be any
64 * primitive type (integer, long or pointer).
65 *
66 * __field(int, foo)
67 *
68 * __entry->foo = 5;
69 *
70 * __field_struct : This can be any static complex data type (struct, union
71 * but not an array). Be careful using complex types, as each
72 * event is limited in size, and copying large amounts of data
73 * into the ring buffer can slow things down.
74 *
75 * __field_struct(struct bar, foo)
76 *
77 * __entry->bar.x = y;
78
79 * __array: There are three fields (type, name, size). The type is the
80 * type of elements in teh array, the name is the name of the array.
81 * size is the number of items in the array (not the total size).
82 *
83 * __array( char, foo, 10) is the same as saying: char foo[10];
84 *
85 * Assigning arrays can be done like any array:
86 *
87 * __entry->foo[0] = 'a';
88 *
89 * memcpy(__entry->foo, bar, 10);
90 *
91 * __dynamic_array: This is similar to array, but can vary is size from
92 * instance to instance of the tracepoint being called.
93 * Like __array, this too has three elements (type, name, size);
94 * type is the type of the element, name is the name of the array.
95 * The size is different than __array. It is not a static number,
96 * but the algorithm to figure out the length of the array for the
97 * specific instance of tracepoint. Again, size is the numebr of
98 * items in the array, not the total length in bytes.
99 *
100 * __dynamic_array( int, foo, bar) is similar to: int foo[bar];
101 *
102 * Note, unlike arrays, you must use the __get_dynamic_array() macro
103 * to access the array.
104 *
105 * memcpy(__get_dynamic_array(foo), bar, 10);
106 *
107 * Notice, that "__entry" is not needed here.
108 *
109 * __string: This is a special kind of __dynamic_array. It expects to
110 * have a nul terminated character array passed to it (it allows
111 * for NULL too, which would be converted into "(null)"). __string
112 * takes two paramenter (name, src), where name is the name of
113 * the string saved, and src is the string to copy into the
114 * ring buffer.
115 *
116 * __string(foo, bar) is similar to: strcpy(foo, bar)
117 *
118 * To assign a string, use the helper macro __assign_str().
119 *
120 * __assign_str(foo, bar);
121 *
122 * In most cases, the __assign_str() macro will take the same
123 * parameters as the __string() macro had to declare the string.
124 *
125 * __bitmask: This is another kind of __dynamic_array, but it expects
126 * an array of longs, and the number of bits to parse. It takes
127 * two parameters (name, nr_bits), where name is the name of the
128 * bitmask to save, and the nr_bits is the number of bits to record.
129 *
130 * __bitmask(target_cpu, nr_cpumask_bits)
131 *
132 * To assign a bitmask, use the __assign_bitmask() helper macro.
133 *
134 * __assign_bitmask(target_cpus, cpumask_bits(bar), nr_cpumask_bits);
64 * 135 *
65 * __array( char, foo, 10) is the same as saying char foo[10].
66 * 136 *
67 * fast_assign: This is a C like function that is used to store the items 137 * fast_assign: This is a C like function that is used to store the items
68 * into the ring buffer. 138 * into the ring buffer. A special variable called "__entry" will be the
139 * structure that points into the ring buffer and has the same fields as
140 * described by the struct part of TRACE_EVENT above.
69 * 141 *
70 * printk: This is a way to print out the data in pretty print. This is 142 * printk: This is a way to print out the data in pretty print. This is
71 * useful if the system crashes and you are logging via a serial line, 143 * useful if the system crashes and you are logging via a serial line,
72 * the data can be printed to the console using this "printk" method. 144 * the data can be printed to the console using this "printk" method.
145 * This is also used to print out the data from the trace files.
146 * Again, the __entry macro is used to access the data from the ring buffer.
147 *
148 * Note, __dynamic_array, __string, and __bitmask require special helpers
149 * to access the data.
150 *
151 * For __dynamic_array(int, foo, bar) use __get_dynamic_array(foo)
152 * Use __get_dynamic_array_len(foo) to get the length of the array
153 * saved.
154 *
155 * For __string(foo, bar) use __get_str(foo)
156 *
157 * For __bitmask(target_cpus, nr_cpumask_bits) use __get_bitmask(target_cpus)
158 *
73 * 159 *
74 * Note, that for both the assign and the printk, __entry is the handler 160 * Note, that for both the assign and the printk, __entry is the handler
75 * to the data structure in the ring buffer, and is defined by the 161 * to the data structure in the ring buffer, and is defined by the
76 * TP_STRUCT__entry. 162 * TP_STRUCT__entry.
77 */ 163 */
164
165/*
166 * It is OK to have helper functions in the file, but they need to be protected
167 * from being defined more than once. Remember, this file gets included more
168 * than once.
169 */
170#ifndef __TRACE_EVENT_SAMPLE_HELPER_FUNCTIONS
171#define __TRACE_EVENT_SAMPLE_HELPER_FUNCTIONS
172static inline int __length_of(const int *list)
173{
174 int i;
175
176 if (!list)
177 return 0;
178
179 for (i = 0; list[i]; i++)
180 ;
181 return i;
182}
183#endif
184
78TRACE_EVENT(foo_bar, 185TRACE_EVENT(foo_bar,
79 186
80 TP_PROTO(char *foo, int bar), 187 TP_PROTO(const char *foo, int bar, const int *lst,
188 const char *string, const struct cpumask *mask),
81 189
82 TP_ARGS(foo, bar), 190 TP_ARGS(foo, bar, lst, string, mask),
83 191
84 TP_STRUCT__entry( 192 TP_STRUCT__entry(
85 __array( char, foo, 10 ) 193 __array( char, foo, 10 )
86 __field( int, bar ) 194 __field( int, bar )
195 __dynamic_array(int, list, __length_of(lst))
196 __string( str, string )
197 __bitmask( cpus, num_possible_cpus() )
87 ), 198 ),
88 199
89 TP_fast_assign( 200 TP_fast_assign(
90 strlcpy(__entry->foo, foo, 10); 201 strlcpy(__entry->foo, foo, 10);
91 __entry->bar = bar; 202 __entry->bar = bar;
203 memcpy(__get_dynamic_array(list), lst,
204 __length_of(lst) * sizeof(int));
205 __assign_str(str, string);
206 __assign_bitmask(cpus, cpumask_bits(mask), num_possible_cpus());
207 ),
208
209 TP_printk("foo %s %d %s %s (%s)", __entry->foo, __entry->bar,
210 __print_array(__get_dynamic_array(list),
211 __get_dynamic_array_len(list),
212 sizeof(int)),
213 __get_str(str), __get_bitmask(cpus))
214);
215
216/*
217 * There may be a case where a tracepoint should only be called if
218 * some condition is set. Otherwise the tracepoint should not be called.
219 * But to do something like:
220 *
221 * if (cond)
222 * trace_foo();
223 *
224 * Would cause a little overhead when tracing is not enabled, and that
225 * overhead, even if small, is not something we want. As tracepoints
226 * use static branch (aka jump_labels), where no branch is taken to
227 * skip the tracepoint when not enabled, and a jmp is placed to jump
228 * to the tracepoint code when it is enabled, having a if statement
229 * nullifies that optimization. It would be nice to place that
230 * condition within the static branch. This is where TRACE_EVENT_CONDITION
231 * comes in.
232 *
233 * TRACE_EVENT_CONDITION() is just like TRACE_EVENT, except it adds another
234 * parameter just after args. Where TRACE_EVENT has:
235 *
236 * TRACE_EVENT(name, proto, args, struct, assign, printk)
237 *
238 * the CONDITION version has:
239 *
240 * TRACE_EVENT_CONDITION(name, proto, args, cond, struct, assign, printk)
241 *
242 * Everything is the same as TRACE_EVENT except for the new cond. Think
243 * of the cond variable as:
244 *
245 * if (cond)
246 * trace_foo_bar_with_cond();
247 *
248 * Except that the logic for the if branch is placed after the static branch.
249 * That is, the if statement that processes the condition will not be
250 * executed unless that traecpoint is enabled. Otherwise it still remains
251 * a nop.
252 */
253TRACE_EVENT_CONDITION(foo_bar_with_cond,
254
255 TP_PROTO(const char *foo, int bar),
256
257 TP_ARGS(foo, bar),
258
259 TP_CONDITION(!(bar % 10)),
260
261 TP_STRUCT__entry(
262 __string( foo, foo )
263 __field( int, bar )
264 ),
265
266 TP_fast_assign(
267 __assign_str(foo, foo);
268 __entry->bar = bar;
269 ),
270
271 TP_printk("foo %s %d", __get_str(foo), __entry->bar)
272);
273
274void foo_bar_reg(void);
275void foo_bar_unreg(void);
276
277/*
278 * Now in the case that some function needs to be called when the
279 * tracepoint is enabled and/or when it is disabled, the
280 * TRACE_EVENT_FN() serves this purpose. This is just like TRACE_EVENT()
281 * but adds two more parameters at the end:
282 *
283 * TRACE_EVENT_FN( name, proto, args, struct, assign, printk, reg, unreg)
284 *
285 * reg and unreg are functions with the prototype of:
286 *
287 * void reg(void)
288 *
289 * The reg function gets called before the tracepoint is enabled, and
290 * the unreg function gets called after the tracepoint is disabled.
291 *
292 * Note, reg and unreg are allowed to be NULL. If you only need to
293 * call a function before enabling, or after disabling, just set one
294 * function and pass in NULL for the other parameter.
295 */
296TRACE_EVENT_FN(foo_bar_with_fn,
297
298 TP_PROTO(const char *foo, int bar),
299
300 TP_ARGS(foo, bar),
301
302 TP_STRUCT__entry(
303 __string( foo, foo )
304 __field( int, bar )
305 ),
306
307 TP_fast_assign(
308 __assign_str(foo, foo);
309 __entry->bar = bar;
310 ),
311
312 TP_printk("foo %s %d", __get_str(foo), __entry->bar),
313
314 foo_bar_reg, foo_bar_unreg
315);
316
317/*
318 * Each TRACE_EVENT macro creates several helper functions to produce
319 * the code to add the tracepoint, create the files in the trace
320 * directory, hook it to perf, assign the values and to print out
321 * the raw data from the ring buffer. To prevent too much bloat,
322 * if there are more than one tracepoint that uses the same format
323 * for the proto, args, struct, assign and printk, and only the name
324 * is different, it is highly recommended to use the DECLARE_EVENT_CLASS
325 *
326 * DECLARE_EVENT_CLASS() macro creates most of the functions for the
327 * tracepoint. Then DEFINE_EVENT() is use to hook a tracepoint to those
328 * functions. This DEFINE_EVENT() is an instance of the class and can
329 * be enabled and disabled separately from other events (either TRACE_EVENT
330 * or other DEFINE_EVENT()s).
331 *
332 * Note, TRACE_EVENT() itself is simply defined as:
333 *
334 * #define TRACE_EVENT(name, proto, args, tstruct, assign, printk) \
335 * DEFINE_EVENT_CLASS(name, proto, args, tstruct, assign, printk); \
336 * DEFINE_EVENT(name, name, proto, args)
337 *
338 * The DEFINE_EVENT() also can be declared with conditions and reg functions:
339 *
340 * DEFINE_EVENT_CONDITION(template, name, proto, args, cond);
341 * DEFINE_EVENT_FN(template, name, proto, args, reg, unreg);
342 */
343DECLARE_EVENT_CLASS(foo_template,
344
345 TP_PROTO(const char *foo, int bar),
346
347 TP_ARGS(foo, bar),
348
349 TP_STRUCT__entry(
350 __string( foo, foo )
351 __field( int, bar )
352 ),
353
354 TP_fast_assign(
355 __assign_str(foo, foo);
356 __entry->bar = bar;
92 ), 357 ),
93 358
94 TP_printk("foo %s %d", __entry->foo, __entry->bar) 359 TP_printk("foo %s %d", __get_str(foo), __entry->bar)
95); 360);
361
362/*
363 * Here's a better way for the previous samples (except, the first
364 * exmaple had more fields and could not be used here).
365 */
366DEFINE_EVENT(foo_template, foo_with_template_simple,
367 TP_PROTO(const char *foo, int bar),
368 TP_ARGS(foo, bar));
369
370DEFINE_EVENT_CONDITION(foo_template, foo_with_template_cond,
371 TP_PROTO(const char *foo, int bar),
372 TP_ARGS(foo, bar),
373 TP_CONDITION(!(bar % 8)));
374
375
376DEFINE_EVENT_FN(foo_template, foo_with_template_fn,
377 TP_PROTO(const char *foo, int bar),
378 TP_ARGS(foo, bar),
379 foo_bar_reg, foo_bar_unreg);
380
381/*
382 * Anytime two events share basically the same values and have
383 * the same output, use the DECLARE_EVENT_CLASS() and DEFINE_EVENT()
384 * when ever possible.
385 */
386
387/*
388 * If the event is similar to the DECLARE_EVENT_CLASS, but you need
389 * to have a different output, then use DEFINE_EVENT_PRINT() which
390 * lets you override the TP_printk() of the class.
391 */
392
393DEFINE_EVENT_PRINT(foo_template, foo_with_template_print,
394 TP_PROTO(const char *foo, int bar),
395 TP_ARGS(foo, bar),
396 TP_printk("bar %s %d", __get_str(foo), __entry->bar));
397
96#endif 398#endif
97 399
98/***** NOTICE! The #if protection ends here. *****/ 400/***** NOTICE! The #if protection ends here. *****/