source: rtems-docs/user/tracing/eventrecording.rst @ 58bf83e

Last change on this file since 58bf83e was 58bf83e, checked in by Sebastian Huber <sebastian.huber@…>, on 12/22/20 at 06:17:43

user: Mention use of LLVM

  • Property mode set to 100644
File size: 11.4 KB
Line 
1.. SPDX-License-Identifier: CC-BY-SA-4.0
2
3.. Copyright (C) 2019, 2020 embedded brains GmbH
4.. Copyright (C) 2019 Sebastian Huber
5
6.. _EventRecording:
7
8Event Recording
9===============
10
11The `event recording` support focuses on the recording of high frequency
12events such as
13
14     * thread switches,
15     * thread queue enqueue and surrender,
16     * interrupt entry and exit,
17     * heap/workspace memory allocate/free,
18     * UMA zone allocate/free,
19     * Ethernet packet input/output, and
20     * etc.
21
22There is a fixed set of 512 system reserved and 512 user defined events which
23are identified by an event number (:c:type:`rtems_record_event`).
24
25The event recording support allows post-mortem analysis in fatal error
26handlers, e.g. the last events are in the record buffers, the newest event
27overwrites the oldest event.  It is possible to detect record buffer overflows
28for consumers that expect a continuous stream of events, e.g. to display the
29system state changes in real-time.
30
31The implementation supports high-end SMP machines (more than 1GHz processor
32frequency, more than four processors).  It uses per-processor ring buffers to
33record the events.  Synchronization is done without atomic read-modify-write
34operations.  The CPU counter is used to get the time of events. It is combined
35with periodic uptime events to synchronize it with the monotonic system clock
36(:c:macro:`CLOCK_MONOTONIC`).
37
38To use the event recording three things come into play. Firstly, there is the
39generation of event records on the target system (the application running with
40RTEMS).  Secondly, means to transfer the recorded events to the host computer
41for analysis.  Thirdly, the analysis of the recorded events on the host
42computer.
43
44Target System: Configuration and Event Generation
45-------------------------------------------------
46
47The application enables the event recording support via the configuration
48option :c:macro:`CONFIGURE_RECORD_PER_PROCESSOR_ITEMS`.  The configuration
49option :c:macro:`CONFIGURE_RECORD_EXTENSIONS_ENABLED` enables the generation of
50thread create, start, restart, delete, switch, begin, exitted and terminate
51events.  Dumps of the event records in a fatal error handler can be enabled by
52the mutually exclusive :c:macro:`CONFIGURE_RECORD_FATAL_DUMP_BASE64` and
53:c:macro:`CONFIGURE_RECORD_FATAL_DUMP_BASE64_ZLIB` configuration options.
54
55Custom events can be recorded for example with the
56:c:func:`rtems_record_produce`, :c:func:`rtems_record_line`,
57:c:func:`rtems_record_caller`, etc. functions.
58
59.. code-block:: c
60
61    #include <rtems/record.h>
62
63    void f( void )
64    {
65      rtems_record_produce( RTEMS_RECORD_USER( 0 ), 123 );
66      rtems_record_line();
67      rtems_record_caller();
68    }
69
70The variants of :c:func:`rtems_record_line` and :c:func:`rtems_record_caller`
71can be used to easily generate control flow events in the area of interest.
72The :file:`rtems-record-lttng` tool can use these events to associate source
73code files and line numbers to them using the ELF file of the application.
74
75The following code can be used together with the GCC option
76``-finstrument-functions`` to generate function entry/exit events for
77instrumented functions:
78
79.. code-block:: c
80
81   __attribute__(( __no_instrument_function__ ))
82   void __cyg_profile_func_enter( void *this_fn, void *call_site )
83   {
84     rtems_record_produce_2(
85       RTEMS_RECORD_CALLER,
86       (rtems_record_data) call_site,
87       RTEMS_RECORD_FUNCTION_ENTRY,
88       (rtems_record_data) this_fn
89     );
90   }
91
92   __attribute__(( __no_instrument_function__ ))
93   void __cyg_profile_func_exit( void *this_fn, void *call_site )
94   {
95     rtems_record_produce(
96       RTEMS_RECORD_FUNCTION_EXIT,
97       (rtems_record_data) this_fn
98     );
99   }
100
101To generate interrupt handler entry/exit events, the following patch can be
102used:
103
104.. code-block:: diff
105
106    diff --git a/bsps/arm/shared/clock/clock-armv7m.c b/bsps/arm/shared/clock/clock-armv7m.c
107    index 255de1ca42..0d37c63ac6 100644
108    --- a/bsps/arm/shared/clock/clock-armv7m.c
109    +++ b/bsps/arm/shared/clock/clock-armv7m.c
110    @@ -29,6 +29,7 @@
111     #include <bsp/clock-armv7m.h>
112
113     #include <rtems.h>
114    +#include <rtems/record.h>
115     #include <rtems/sysinit.h>
116
117     #ifdef ARM_MULTILIB_ARCH_V7M
118    @@ -45,9 +46,11 @@ static uint32_t _ARMV7M_TC_get_timecount(struct timecounter *base)
119
120     void _ARMV7M_Clock_handler(void)
121     {
122    +  rtems_record_produce(RTEMS_RECORD_INTERRUPT_ENTRY, ARMV7M_VECTOR_SYSTICK);
123       _ARMV7M_Interrupt_service_enter();
124       Clock_isr(NULL);
125       _ARMV7M_Interrupt_service_leave();
126    +  rtems_record_produce(RTEMS_RECORD_INTERRUPT_EXIT, ARMV7M_VECTOR_SYSTICK);
127     }
128
129     static void _ARMV7M_Clock_handler_install(void)
130    diff --git a/bsps/include/bsp/irq-generic.h b/bsps/include/bsp/irq-generic.h
131    index 31835d07ba..2ab2f78b65 100644
132    --- a/bsps/include/bsp/irq-generic.h
133    +++ b/bsps/include/bsp/irq-generic.h
134    @@ -30,6 +30,7 @@
135     #include <stdbool.h>
136
137     #include <rtems/irq-extension.h>
138    +#include <rtems/record.h>
139     #include <rtems/score/assert.h>
140
141     #ifdef RTEMS_SMP
142    @@ -258,6 +259,7 @@ void bsp_interrupt_vector_disable(rtems_vector_number vector);
143      */
144     static inline void bsp_interrupt_handler_dispatch(rtems_vector_number vector)
145     {
146    +  rtems_record_produce(RTEMS_RECORD_INTERRUPT_ENTRY, vector);
147       if (bsp_interrupt_is_valid_vector(vector)) {
148         const bsp_interrupt_handler_entry *e =
149           &bsp_interrupt_handler_table [bsp_interrupt_handler_index(vector)];
150    @@ -276,6 +278,7 @@ static inline void bsp_interrupt_handler_dispatch(rtems_vector_number vector)
151       } else {
152         bsp_interrupt_handler_default(vector);
153       }
154    +  rtems_record_produce(RTEMS_RECORD_INTERRUPT_EXIT, vector);
155     }
156
157     /**
158
159Transfer of Event Records to the Host Computer
160----------------------------------------------
161
162Recorded events can be sent to a host computer with a record server started by
163:c:func:`rtems_record_start_server` via a TCP connection.
164
165In the fatal error handler, the event records can be dumped via
166:c:func:`rtems_putc` in Base64 encoding.  Optionally, the event records can be
167compressed via zlib before they are dumped in Base64 encoding.  The compression
168needs roughly 512KiB of statically allocated memory.
169
170Analysis of Event Records on the Host Computer
171----------------------------------------------
172
173Use the command line tool :file:`rtems-record-lttng` to get recorded events
174from the record server running on the target system or from a file to convert
175the event records into CTF.  It can be also used to read the dumps in Base64
176encoding generated by the fatal error handler.  The tool outputs the event
177records in the `Common Trace Format (CTF) <https://diamon.org/ctf/>`_ with some
178extra support for the
179`Linux Trace Toolkit Next Generation (LTTng) <https://lttng.org/>`_.  This
180format can be analysed using `babeltrace <https://babeltrace.org/>`_ or
181`Eclipse Trace Compass <https://www.eclipse.org/tracecompass/>`_.
182The command line tool :file:`rtems-record-lttng` optionally uses
183`LLVM <https://www.llvm.org/>`_ to translate addresses to functions and source
184file locations.  Make sure you have the LLVM development package installed when
185you build the RTEMS Tools to enable this feature.
186
187For example, to get the event records from the record server running on the
188target use:
189
190.. code-block:: none
191
192    mkdir new-trace
193    cd new-trace
194    rtems-record-lttng -e application.exe -H 192.168.188.84 -l 100000
195
196If everything is set up correctly, then the command produces a :file:`metadata`
197file and one stream file :file:`stream_0`, etc. for each processor which
198generated event records.
199
200.. code-block:: none
201
202    $ ls -l
203    total 120
204    -rw-r--r-- 1 user group 108339 Apr 11 15:28 metadata
205    -rw-r--r-- 1 user group   8701 Apr 11 15:28 stream_0
206
207This output in CTF can be used by :file:`babeltrace` and
208`Eclipse Trace Compass` for further analysis, for example:
209
210.. code-block:: none
211
212    $ babeltrace .
213    [07:28:15.909340000] (+?.?????????) RTEMS THREAD_STACK_CURRENT: { cpu_id = 0 }, { data = 0xB10 }
214    [07:28:15.909340000] (+0.000000000) RTEMS sched_switch: { cpu_id = 0 }, { prev_comm = "UI1 ", prev_tid = 167837697, prev_prio = 0, prev_state = 0, next_comm = "IDLE/0", next_tid = 0, next_prio = 0 }
215    [07:28:15.909519999] (+0.000179999) RTEMS THREAD_STACK_CURRENT: { cpu_id = 0 }, { data = 0xD68 }
216    [07:28:15.909519999] (+0.000000000) RTEMS sched_switch: { cpu_id = 0 }, { prev_comm = "IDLE/0", prev_tid = 0, prev_prio = 0, prev_state = 1026, next_comm = "UI1 ", next_tid = 167837697, next_prio = 0 }
217    [07:28:15.909579999] (+0.000060000) RTEMS THREAD_STACK_CURRENT: { cpu_id = 0 }, { data = 0xB10 }
218    ...
219    [07:28:15.999940999] (+0.000000000) RTEMS USER_4: { cpu_id = 0 }, { data = 0x4000192C }
220    [07:28:15.999940999] (+0.000000000) RTEMS RETURN_0: { cpu_id = 0 }, { data = 0x0 }
221    [07:28:15.999940999] (+0.000000000) RTEMS RETURN_1: { cpu_id = 0 }, { data = 0x1 }
222    [07:28:15.999940999] (+0.000000000) RTEMS RETURN_2: { cpu_id = 0 }, { data = 0x2 }
223    [07:28:15.999940999] (+0.000000000) RTEMS RETURN_3: { cpu_id = 0 }, { data = 0x3 }
224    [07:28:15.999940999] (+0.000000000) RTEMS RETURN_4: { cpu_id = 0 }, { data = 0x4 }
225    [07:28:15.999940999] (+0.000000000) RTEMS RETURN_5: { cpu_id = 0 }, { data = 0x5 }
226    [07:28:15.999940999] (+0.000000000) RTEMS RETURN_6: { cpu_id = 0 }, { data = 0x6 }
227    [07:28:15.999940999] (+0.000000000) RTEMS RETURN_7: { cpu_id = 0 }, { data = 0x7 }
228    [07:28:15.999940999] (+0.000000000) RTEMS RETURN_8: { cpu_id = 0 }, { data = 0x8 }
229    [07:28:15.999940999] (+0.000000000) RTEMS RETURN_9: { cpu_id = 0 }, { data = 0x9 }
230    [07:28:15.999940999] (+0.000000000) RTEMS ISR_DISABLE: { cpu_id = 0 }, { code = "generate_events at init.c:154" }
231    [07:28:15.999940999] (+0.000000000) RTEMS ISR_ENABLE: { cpu_id = 0 }, { code = "Init at init.c:181" }
232
233A dump from the fatal error handler looks like this:
234
235.. code-block:: none
236
237    *** BEGIN OF RECORDS BASE64 ZLIB ***
238    eNqtlE1vE1cUhsdJWgg0jU2GABILpxUVkaJcTxzH8QqThKpRKTIJlcoyeIKIhGCCEFnAAtAoKgXa
239    phqx6gKk/AAXWHTpTMYZlg0rdpBdF7Dvsuec91jYFEo+HOnq0b33Oe/9mOtks9ns7Y1TK5ZlJah1
240    Uluw8HfJstqYA1b3WJG4a+p4aZpJbZzaXOlrw+4cte+p2Zcuz15kUstS3FhmZGiWOTs6nGM65Xye
241    6TqZEeZQNnOOWZh1y8KZfEHG3ewMszyE+XJ2hHNyg7lBrs9lhtIZpuMUHObR9LDwuxNnppgDufQ0
242    c2x6Ko35nLBcKOSEeXeYOXM+P8o8lR7oZ85dXJB1HDfN6+aGnbx4/YUR3t/+zgTfUaL3xMmJSe7v
243    0X7ameTzX9N7m6d7WyNetqyOI93HVgx7xKOWtTdJHOSc7rElo6TxrgvEQfHGbxkl/PFb8F/2GSX8
244    l33wX6WMEv6rlPjJ638YpfhE8ZM3Hhml+ETxUwdOG6X4RPFTB48bpfhE+E82jBL+kw34T9eNEv7T
245    dfH3leaNUnyi+PtOzxil+ET4r1NGCf91Cv6bhFHCf5MQv+fHR0YpPlH8njtLRik+UXz7iGOU4hPF
246    t7/qM0rxifCr60YJv7oOv/rX2aLVk1QetqvP5RFoP0N9/l2R95x/TG32SsTjo8Td4qE/0dDvFB/j
247    Z94zvqch58L/zO8ltqt3cxPeZ8QO9X/fgt9F/ETrqtuo+5z4qdb/vYP6bv7fZIcVyrFtInLCCnLC
248    CnLCCnLCCnLCCnLCCnLCSj0nSdytecUW5qX4/yyxt2gdGtD8b97p/2CHjy1dr3Hco3G8p/Bxm67f
249    OH+jYZ+N4/fes//G+YcfPN/qMrzVZfb+JMJbXYa3ulz3cA/N/otN+Li35rp/tlCH+26q3394G/X4
250    Xs05EzvIwXdvzvNakId3FAXIjQLOfUhEbhQgNwqQGwXIjQLkRgFyowC5UYDcKKjn4n1GD9qRX2c9
251    /91+fb0Pjdf38bH5+j436+l5aovwaz78mg+/5sOv+fBrvvo+zr/tOh/3tuN6H/feshwf36/leT7e
252    Q22xQ3LXrii9O5L/to/11jys9x/P+wnj3l3Zx0fnvXuyz0173n05z5Z972c5/7brvF/k3nZc7/0q
253    9x6fR07sIid2kRO7yIld5MQucmIXObGLnNjVHHdJvl/L89zf5D3E7rdF6+BV4knJf1b6Uuqelb7g
254    df4FFmd4DQ==
255    *** END OF RECORDS BASE64 ZLIB ***
256
257Copy everything between the ``*** BEGIN OF RECORDS BASE64 ZLIB ***`` and the
258``*** END OF RECORDS BASE64 ZLIB ***`` markers into a file, for example
259:file:`dump.txt`.  Use this command to convert the event records into the CTF
260for further analysis:
261
262.. code-block:: none
263
264    rtems-record-lttng -e application.exe -b -z dump.txt
Note: See TracBrowser for help on using the repository browser.