1.. _tracing:
2
3Tracing
4#######
5
6Overview
7********
8
9The tracing feature provides hooks that permits you to collect data from
10your application and allows tools running on a host to visualize the inner-working of
11the kernel and various subsystems.
12
13Every system has application-specific events to trace out.  Historically,
14that has implied:
15
161. Determining the application-specific payload,
172. Choosing suitable serialization-format,
183. Writing the on-target serialization code,
194. Deciding on and writing the I/O transport mechanics,
205. Writing the PC-side deserializer/parser,
216. Writing custom ad-hoc tools for filtering and presentation.
22
23An application can use one of the existing formats or define a custom format by
24overriding the macros declared in :zephyr_file:`include/zephyr/tracing/tracing.h`.
25
26Different formats, transports and host tools are available and supported in
27Zephyr.
28
29In fact, I/O varies greatly from system to system.  Therefore, it is
30instructive to create a taxonomy for I/O types when we must ensure the
31interface between payload/format (Top Layer) and the transport mechanics
32(bottom Layer) is generic and efficient enough to model these. See the
33*I/O taxonomy* section below.
34
35
36Serialization Formats
37**********************
38
39.. _ctf:
40
41Common Trace Format (CTF) Support
42=================================
43
44Common Trace Format, CTF, is an open format and language to describe trace
45formats. This enables tool reuse, of which line-textual (babeltrace) and
46graphical (TraceCompass) variants already exist.
47
48CTF should look familiar to C programmers but adds stronger typing.
49See `CTF - A Flexible, High-performance Binary Trace Format
50<http://diamon.org/ctf/>`_.
51
52
53CTF allows us to formally describe application specific payload and the
54serialization format, which enables common infrastructure for host tools
55and parsers and tools for filtering and presentation.
56
57
58A Generic Interface
59--------------------
60
61In CTF, an event is serialized to a packet containing one or more fields.
62As seen from *I/O taxonomy* section below, a bottom layer may:
63
64- perform actions at transaction-start (e.g. mutex-lock),
65- process each field in some way (e.g. sync-push emit, concat, enqueue to
66  thread-bound FIFO),
67- perform actions at transaction-stop (e.g. mutex-release, emit of concat
68  buffer).
69
70CTF Top-Layer Example
71----------------------
72
73The CTF_EVENT macro will serialize each argument to a field::
74
75  /* Example for illustration */
76  static inline void ctf_top_foo(uint32_t thread_id, ctf_bounded_string_t name)
77  {
78    CTF_EVENT(
79      CTF_LITERAL(uint8_t, 42),
80      thread_id,
81      name,
82      "hello, I was emitted from function: ",
83      __func__  /* __func__ is standard since C99 */
84    );
85  }
86
87How to serialize and emit fields as well as handling alignment, can be done
88internally and statically at compile-time in the bottom-layer.
89
90
91The CTF top layer is enabled using the configuration option
92:kconfig:option:`CONFIG_TRACING_CTF` and can be used with the different transport
93backends both in synchronous and asynchronous modes.
94
95
96SEGGER SystemView Support
97=========================
98
99Zephyr provides built-in support for `SEGGER SystemView`_ that can be enabled in
100any application for platforms that have the required hardware support.
101
102The payload and format used with SystemView is custom to the application and
103relies on RTT as a transport. Newer versions of SystemView support other
104transports, for example UART or using snapshot mode (both still not
105supported in Zephyr).
106
107To enable tracing support with `SEGGER SystemView`_ add the configuration option
108:kconfig:option:`CONFIG_SEGGER_SYSTEMVIEW` to your project configuration file and set
109it to *y*. For example, this can be added to the
110:zephyr:code-sample:`synchronization` sample to visualize fast switching between threads.
111SystemView can also be used for post-mortem tracing, which can be enabled with
112`CONFIG_SEGGER_SYSVIEW_POST_MORTEM_MODE`. In this mode, a debugger can
113be attached after the system has crashed using ``west attach`` after which the
114latest data from the internal RAM buffer can be loaded into SystemView::
115
116    CONFIG_STDOUT_CONSOLE=y
117    # enable to use thread names
118    CONFIG_THREAD_NAME=y
119    CONFIG_SEGGER_SYSTEMVIEW=y
120    CONFIG_USE_SEGGER_RTT=y
121    CONFIG_TRACING=y
122    # enable for post-mortem tracing
123    CONFIG_SEGGER_SYSVIEW_POST_MORTEM_MODE=n
124
125
126.. figure:: segger_systemview.png
127    :align: center
128    :alt: SEGGER SystemView
129    :figclass: align-center
130    :width: 80%
131
132.. _SEGGER SystemView: https://www.segger.com/products/development-tools/systemview/
133
134
135Recent versions of `SEGGER SystemView`_ come with an API translation table for
136Zephyr which is incomplete and does not match the current level of support
137available in Zephyr. To use the latest Zephyr API description table, copy the
138file available in the tree to your local configuration directory to override the
139builtin table::
140
141        # On Linux and MacOS
142        cp $ZEPHYR_BASE/subsys/tracing/sysview/SYSVIEW_Zephyr.txt ~/.config/SEGGER/
143
144User-Defined Tracing
145====================
146
147This tracing format allows the user to define functions to perform any work desired
148when a task is switched in or out, when an interrupt is entered or exited, and when the cpu
149is idle.
150
151Examples include:
152- simple toggling of GPIO for external scope tracing while minimizing extra cpu load
153- generating/outputting trace data in a non-standard or proprietary format that can
154not be supported by the other tracing systems
155
156The following functions can be defined by the user:
157
158.. code-block:: c
159
160   void sys_trace_thread_create_user(struct k_thread *thread);
161   void sys_trace_thread_abort_user(struct k_thread *thread);
162   void sys_trace_thread_suspend_user(struct k_thread *thread);
163   void sys_trace_thread_resume_user(struct k_thread *thread);
164   void sys_trace_thread_name_set_user(struct k_thread *thread);
165   void sys_trace_thread_switched_in_user(struct k_thread *thread);
166   void sys_trace_thread_switched_out_user(struct k_thread *thread);
167   void sys_trace_thread_info_user(struct k_thread *thread);
168   void sys_trace_thread_sched_ready_user(struct k_thread *thread);
169   void sys_trace_thread_pend_user(struct k_thread *thread);
170   void sys_trace_thread_priority_set_user(struct k_thread *thread, int prio);
171   void sys_trace_isr_enter_user(int nested_interrupts);
172   void sys_trace_isr_exit_user(int nested_interrupts);
173   void sys_trace_idle_user();
174
175Enable this format with the :kconfig:option:`CONFIG_TRACING_USER` option.
176
177Transport Backends
178******************
179
180The following backends are currently supported:
181
182* UART
183* USB
184* File (Using the native port with POSIX architecture based targets)
185* RTT (With SystemView)
186* RAM (buffer to be retrieved by a debugger)
187
188Using Tracing
189*************
190
191The sample :zephyr_file:`samples/subsys/tracing` demonstrates tracing with
192different formats and backends.
193
194To get started, the simplest way is to use the CTF format with the :ref:`native_sim <native_sim>`
195port, build the sample as follows:
196
197.. zephyr-app-commands::
198   :tool: all
199   :app: samples/subsys/tracing
200   :board: native_sim
201   :gen-args: -DCONF_FILE=prj_native_ctf.conf
202   :goals: build
203
204You can then run the resulting binary with the option ``-trace-file`` to generate
205the tracing data::
206
207    mkdir data
208    cp $ZEPHYR_BASE/subsys/tracing/ctf/tsdl/metadata data/
209    ./build/zephyr/zephyr.exe -trace-file=data/channel0_0
210
211The resulting CTF output can be visualized using babeltrace or TraceCompass
212by pointing the tool to the ``data`` directory with the metadata and trace files.
213
214Using RAM backend
215=================
216
217For devices that do not have available I/O for tracing such as USB or UART but have
218enough RAM to collect trace data, the ram backend can be enabled with configuration
219:kconfig:option:`CONFIG_TRACING_BACKEND_RAM`.
220Adjust :kconfig:option:`CONFIG_RAM_TRACING_BUFFER_SIZE` to be able to record enough traces for your needs.
221Then thanks to a runtime debugger such as gdb this buffer can be fetched from the target
222to an host computer::
223
224    (gdb) dump binary memory data/channel0_0 <ram_tracing_start> <ram_tracing_end>
225
226The resulting channel0_0 file have to be placed in a directory with the ``metadata``
227file like the other backend.
228
229Visualisation Tools
230*******************
231
232TraceCompass
233=============
234
235TraceCompass is an open source tool that visualizes CTF events such as thread
236scheduling and interrupts, and is helpful to find unintended interactions and
237resource conflicts on complex systems.
238
239See also the presentation by Ericsson,
240`Advanced Trouble-shooting Of Real-time Systems
241<https://wiki.eclipse.org/images/0/0e/TechTalkOnlineDemoFeb2017_v1.pdf>`_.
242
243
244
245Future LTTng Inspiration
246************************
247
248Currently, the top-layer provided here is quite simple and bare-bones,
249and needlessly copied from Zephyr's Segger SystemView debug module.
250
251For an OS like Zephyr, it would make sense to draw inspiration from
252Linux's LTTng and change the top-layer to serialize to the same format.
253Doing this would enable direct reuse of TraceCompass' canned analyses
254for Linux.  Alternatively, LTTng-analyses in TraceCompass could be
255customized to Zephyr.  It is ongoing work to enable TraceCompass
256visibility of Zephyr in a target-agnostic and open source way.
257
258
259I/O Taxonomy
260=============
261
262- Atomic Push/Produce/Write/Enqueue:
263
264  - synchronous:
265                  means data-transmission has completed with the return of the
266                  call.
267
268  - asynchronous:
269                  means data-transmission is pending or ongoing with the return
270                  of the call. Usually, interrupts/callbacks/signals or polling
271                  is used to determine completion.
272
273  - buffered:
274                  means data-transmissions are copied and grouped together to
275                  form a larger ones. Usually for amortizing overhead (burst
276                  dequeue) or jitter-mitigation (steady dequeue).
277
278  Examples:
279    - sync  unbuffered
280        E.g. PIO via GPIOs having steady stream, no extra FIFO memory needed.
281        Low jitter but may be less efficient (can't amortize the overhead of
282        writing).
283
284    - sync  buffered
285        E.g. ``fwrite()`` or enqueuing into FIFO.
286        Blockingly burst the FIFO when its buffer-waterlevel exceeds threshold.
287        Jitter due to bursts may lead to missed deadlines.
288
289    - async unbuffered
290        E.g. DMA, or zero-copying in shared memory.
291        Be careful of data hazards, race conditions, etc!
292
293    - async buffered
294        E.g. enqueuing into FIFO.
295
296
297
298- Atomic Pull/Consume/Read/Dequeue:
299
300  - synchronous:
301                  means data-reception has completed with the return of the call.
302
303  - asynchronous:
304                  means data-reception is pending or ongoing with the return of
305                  the call. Usually, interrupts/callbacks/signals or polling is
306                  used to determine completion.
307
308  - buffered:
309                  means data is copied-in in larger chunks than request-size.
310                  Usually for amortizing wait-time.
311
312  Examples:
313    - sync  unbuffered
314        E.g. Blocking read-call, ``fread()`` or SPI-read, zero-copying in shared
315        memory.
316
317    - sync  buffered
318        E.g. Blocking read-call with caching applied.
319        Makes sense if read pattern exhibits spatial locality.
320
321    - async unbuffered
322        E.g. zero-copying in shared memory.
323        Be careful of data hazards, race conditions, etc!
324
325    - async buffered
326        E.g. ``aio_read()`` or DMA.
327
328
329
330Unfortunately, I/O may not be atomic and may, therefore, require locking.
331Locking may not be needed if multiple independent channels are available.
332
333  - The system has non-atomic write and one shared channel
334        E.g. UART. Locking required.
335
336        ``lock(); emit(a); emit(b); emit(c); release();``
337
338  - The system has non-atomic write but many channels
339        E.g. Multi-UART. Lock-free if the bottom-layer maps each Zephyr
340        thread+ISR to its own channel, thus alleviating races as each
341        thread is sequentially consistent with itself.
342
343        ``emit(a,thread_id); emit(b,thread_id); emit(c,thread_id);``
344
345  - The system has atomic write     but one shared channel
346        E.g. ``native_sim`` or board with DMA. May or may not need locking.
347
348        ``emit(a ## b ## c); /* Concat to buffer */``
349
350        ``lock(); emit(a); emit(b); emit(c); release(); /* No extra mem */``
351
352  - The system has atomic write     and many channels
353        E.g. native_sim or board with multi-channel DMA. Lock-free.
354
355        ``emit(a ## b ## c, thread_id);``
356
357
358Object tracking
359***************
360
361The kernel can also maintain lists of objects that can be used to track
362their usage. Currently, the following lists can be enabled::
363
364  struct k_timer *_track_list_k_timer;
365  struct k_mem_slab *_track_list_k_mem_slab;
366  struct k_sem *_track_list_k_sem;
367  struct k_mutex *_track_list_k_mutex;
368  struct k_stack *_track_list_k_stack;
369  struct k_msgq *_track_list_k_msgq;
370  struct k_mbox *_track_list_k_mbox;
371  struct k_pipe *_track_list_k_pipe;
372  struct k_queue *_track_list_k_queue;
373  struct k_event *_track_list_k_event;
374
375Those global variables are the head of each list - they can be traversed
376with the help of macro ``SYS_PORT_TRACK_NEXT``. For instance, to traverse
377all initialized mutexes, one can write::
378
379  struct k_mutex *cur = _track_list_k_mutex;
380  while (cur != NULL) {
381    /* Do something */
382
383    cur = SYS_PORT_TRACK_NEXT(cur);
384  }
385
386To enable object tracking, enable :kconfig:option:`CONFIG_TRACING_OBJECT_TRACKING`.
387Note that each list can be enabled or disabled via their tracing
388configuration. For example, to disable tracking of semaphores, one can
389disable :kconfig:option:`CONFIG_TRACING_SEMAPHORE`.
390
391Object tracking is behind tracing configuration as it currently leverages
392tracing infrastructure to perform the tracking.
393
394API
395***
396
397
398Common
399======
400
401.. doxygengroup:: subsys_tracing_apis
402
403Threads
404=======
405
406.. doxygengroup:: subsys_tracing_apis_thread
407
408Work Queues
409===========
410
411.. doxygengroup:: subsys_tracing_apis_work
412
413Poll
414====
415
416.. doxygengroup:: subsys_tracing_apis_poll
417
418Semaphore
419=========
420
421.. doxygengroup:: subsys_tracing_apis_sem
422
423Mutex
424=====
425
426.. doxygengroup:: subsys_tracing_apis_mutex
427
428Condition Variables
429===================
430
431.. doxygengroup:: subsys_tracing_apis_condvar
432
433Queues
434======
435
436.. doxygengroup:: subsys_tracing_apis_queue
437
438FIFO
439====
440
441.. doxygengroup:: subsys_tracing_apis_fifo
442
443LIFO
444====
445.. doxygengroup:: subsys_tracing_apis_lifo
446
447Stacks
448======
449
450.. doxygengroup:: subsys_tracing_apis_stack
451
452Message Queues
453==============
454
455.. doxygengroup:: subsys_tracing_apis_msgq
456
457Mailbox
458=======
459
460.. doxygengroup:: subsys_tracing_apis_mbox
461
462Pipes
463======
464
465.. doxygengroup:: subsys_tracing_apis_pipe
466
467Heaps
468=====
469
470.. doxygengroup:: subsys_tracing_apis_heap
471
472Memory Slabs
473============
474
475.. doxygengroup:: subsys_tracing_apis_mslab
476
477Timers
478======
479
480.. doxygengroup:: subsys_tracing_apis_timer
481
482Object tracking
483===============
484
485.. doxygengroup:: subsys_tracing_object_tracking
486
487Syscalls
488========
489
490.. doxygengroup:: subsys_tracing_apis_syscall
491