Commit | Line | Data |
---|---|---|
5e0cbfb0 PP |
1 | --- |
2 | id: mainline-trace-event | |
3 | --- | |
4 | ||
5 | The first step is to define tracepoints using the mainline Linux | |
6 | `TRACE_EVENT()` macro and insert tracepoints where you want them. | |
7 | Your tracepoint definitions reside in a header file in | |
8 | `include/trace/events`. If you're adding tracepoints to an existing | |
9 | subsystem, edit its appropriate header file. | |
10 | ||
11 | As an example, the following header file (let's call it | |
12 | `include/trace/events/hello.h`) defines one tracepoint using | |
13 | `TRACE_EVENT()`: | |
14 | ||
15 | ~~~ c | |
16 | /* subsystem name is "hello" */ | |
17 | #undef TRACE_SYSTEM | |
18 | #define TRACE_SYSTEM hello | |
19 | ||
20 | #if !defined(_TRACE_HELLO_H) || defined(TRACE_HEADER_MULTI_READ) | |
21 | #define _TRACE_HELLO_H | |
22 | ||
23 | #include <linux/tracepoint.h> | |
24 | ||
25 | TRACE_EVENT( | |
26 | /* "hello" is the subsystem name, "world" is the event name */ | |
27 | hello_world, | |
28 | ||
29 | /* tracepoint function prototype */ | |
30 | TP_PROTO(int foo, const char* bar), | |
31 | ||
32 | /* arguments for this tracepoint */ | |
33 | TP_ARGS(foo, bar), | |
34 | ||
35 | /* LTTng doesn't need those */ | |
36 | TP_STRUCT__entry(), | |
37 | TP_fast_assign(), | |
38 | TP_printk("", 0) | |
39 | ); | |
40 | ||
41 | #endif | |
42 | ||
43 | /* this part must be outside protection */ | |
44 | #include <trace/define_trace.h> | |
45 | ~~~ | |
46 | ||
47 | Notice that we don't use any of the last three arguments: they | |
48 | are left empty here because LTTng doesn't need them. You would only fill | |
49 | `TP_STRUCT__entry()`, `TP_fast_assign()` and `TP_printk()` if you were | |
50 | to also use this tracepoint for ftrace/perf. | |
51 | ||
52 | Once this is done, you may place calls to `trace_hello_world()` | |
53 | wherever you want in the Linux source code. As an example, let us place | |
54 | such a tracepoint in the `usb_probe_device()` static function | |
55 | (`drivers/usb/core/driver.c`): | |
56 | ||
57 | ~~~ c | |
58 | /* called from driver core with dev locked */ | |
59 | static int usb_probe_device(struct device *dev) | |
60 | { | |
61 | struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); | |
62 | struct usb_device *udev = to_usb_device(dev); | |
63 | int error = 0; | |
64 | ||
65 | trace_hello_world(udev->devnum, udev->product); | |
66 | ||
67 | /* ... */ | |
68 | } | |
69 | ~~~ | |
70 | ||
71 | This tracepoint should fire every time a USB device is plugged in. | |
72 | ||
73 | At the top of `driver.c`, we need to include our actual tracepoint | |
74 | definition and, in this case (one place per subsystem), define | |
47bfcb75 | 75 | `CREATE_TRACE_POINTS`, which creates our tracepoint: |
5e0cbfb0 PP |
76 | |
77 | ~~~ c | |
78 | /* ... */ | |
79 | ||
80 | #include "usb.h" | |
81 | ||
82 | #define CREATE_TRACE_POINTS | |
83 | #include <trace/events/hello.h> | |
84 | ||
85 | /* ... */ | |
86 | ~~~ | |
87 | ||
88 | Build your custom Linux kernel. In order to use LTTng, make sure the | |
89 | following kernel configuration options are enabled: | |
90 | ||
91 | * `CONFIG_MODULES` (loadable module support) | |
92 | * `CONFIG_KALLSYMS` (load all symbols for debugging/kksymoops) | |
93 | * `CONFIG_HIGH_RES_TIMERS` (high resolution timer support) | |
94 | * `CONFIG_TRACEPOINTS` (kernel tracepoint instrumentation) | |
95 | ||
96 | Boot the custom kernel. The directory | |
97 | `/sys/kernel/debug/tracing/events/hello` should exist if everything | |
98 | went right, with a `hello_world` subdirectory. |