debug: CTF Tracing with POSIX backend
This commit implements a CTF-backend for Zephyr's tracing API. The CTF-backend itself is split in a middle-layer and a bottom-layer. - Middle-layer decides the payload in event transactions, - Bottom-layer implements the IO transport. A simple POSIX bottom-layer is provided so far. Signed-off-by: François Delawarde <fnde@oticon.com>
This commit is contained in:
parent
43c41d94ea
commit
4fac841869
16 changed files with 1010 additions and 3 deletions
|
@ -79,4 +79,11 @@ config SDL_DISPLAY
|
||||||
|
|
||||||
endif # DISPLAY
|
endif # DISPLAY
|
||||||
|
|
||||||
|
if TRACING_CTF
|
||||||
|
|
||||||
|
config TRACING_CTF_BOTTOM_POSIX
|
||||||
|
default y
|
||||||
|
|
||||||
|
endif # TRACING_CTF
|
||||||
|
|
||||||
endif # BOARD_NATIVE_POSIX
|
endif # BOARD_NATIVE_POSIX
|
||||||
|
|
236
doc/subsystems/tracing/ctf.rst
Normal file
236
doc/subsystems/tracing/ctf.rst
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
.. _ctf:
|
||||||
|
|
||||||
|
Common Trace Format for Zephyr
|
||||||
|
##############################
|
||||||
|
|
||||||
|
Common Trace Format, CTF, is an open format and language to describe trace
|
||||||
|
formats. This enables tool reuse, of which line-textual (babeltrace) and
|
||||||
|
graphical (TraceCompass) variants already exist.
|
||||||
|
|
||||||
|
CTF should look familiar to C programmers but adds stronger typing.
|
||||||
|
See `CTF - A Flexible, High-performance Binary Trace Format
|
||||||
|
<http://diamon.org/ctf/>`_.
|
||||||
|
|
||||||
|
Every system has application-specific events to trace out. Historically,
|
||||||
|
that has implied:
|
||||||
|
|
||||||
|
1. Determining the application-specific payload,
|
||||||
|
2. Choosing suitable serialization-format,
|
||||||
|
3. Writing the on-target serialization code,
|
||||||
|
4. Deciding on and writing the I/O transport mechanics,
|
||||||
|
5. Writing the PC-side deserializer/parser,
|
||||||
|
6. Writing custom ad-hoc tools for filtering and presentation.
|
||||||
|
|
||||||
|
CTF allows us to formally describe #1 and #2, which enables common
|
||||||
|
infrastructure for #5 and #6. This leaves #3 serialization code and #4
|
||||||
|
I/O mechanics up to a custom implementation.
|
||||||
|
|
||||||
|
This CTF debug module aims at providing a common #1 and #2 for Zephyr
|
||||||
|
("middle"), while providing a lean & generic interface for I/O ("bottom").
|
||||||
|
Currently, only one CTF bottom-layer exists, POSIX ``fwrite``, but many others
|
||||||
|
are possible:
|
||||||
|
|
||||||
|
- Async UART
|
||||||
|
- Async DMA
|
||||||
|
- Sync GPIO
|
||||||
|
- ... and many more.
|
||||||
|
|
||||||
|
In fact, I/O varies greatly from system to system. Therefore, it is
|
||||||
|
instructive to create a taxonomy for I/O types when we must ensure the
|
||||||
|
interface between CTF-middle and CTF-bottom is generic and efficient
|
||||||
|
enough to model these. See the *I/O taxonomy* section below.
|
||||||
|
|
||||||
|
|
||||||
|
A Generic Interface
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
In CTF, an event is serialized to a packet containing one or more fields.
|
||||||
|
As seen from *I/O taxonomy* section below, a bottom layer may:
|
||||||
|
|
||||||
|
- perform actions at transaction-start (e.g. mutex-lock),
|
||||||
|
- process each field in some way (e.g. sync-push emit, concat, enqueue to
|
||||||
|
thread-bound FIFO),
|
||||||
|
- perform actions at transaction-stop (e.g. mutex-release, emit of concat
|
||||||
|
buffer).
|
||||||
|
|
||||||
|
The bottom-layer then needs to implement the following macros:
|
||||||
|
|
||||||
|
- ``CTF_BOTTOM_LOCK``: No-op or how to lock the I/O transaction
|
||||||
|
- ``CTF_BOTTOM_UNLOCK``: No-op or how to release the I/O transaction
|
||||||
|
- ``CTF_BOTTOM_FIELDS``: Var-args of fields. May process each field with ``MAP``
|
||||||
|
- ``CTF_BOTTOM_TIMESTAMPED_INTERNALLY``: Tells where timestamping is done
|
||||||
|
|
||||||
|
These macros along with inline functions of the middle-layer can yield a
|
||||||
|
very low-overhead tracing infrastructure.
|
||||||
|
|
||||||
|
|
||||||
|
CTF Middle-Layer Example
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
The CTF_EVENT macro will serialize each argument to a field::
|
||||||
|
|
||||||
|
/* Example for illustration */
|
||||||
|
static inline void ctf_middle_foo(u32_t thread_id, ctf_bounded_string_t name)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, 42),
|
||||||
|
thread_id,
|
||||||
|
name,
|
||||||
|
"hello, I was emitted from function: ",
|
||||||
|
__func__ /* __func__ is standard since C99 */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
How to serialize and emit fields as well as handling alignment, can be done
|
||||||
|
internally and statically at compile-time in the bottom-layer.
|
||||||
|
|
||||||
|
|
||||||
|
How to Activate?
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Make sure ``CONFIG_TRACING_CTF=y`` is set (``CONFIG_TRACING_CTF_BOTTOM_POSIX=y``
|
||||||
|
is selected by default when using ``BOARD_NATIVE_POSIX``).
|
||||||
|
|
||||||
|
|
||||||
|
How to Use?
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The resulting CTF output can be visualized using babeltrace or TraceCompass:
|
||||||
|
|
||||||
|
- The CTF output file can be specified in native posix using the ``-ctf-path``
|
||||||
|
command line option
|
||||||
|
|
||||||
|
- Create a new empty directory and copy into it:
|
||||||
|
|
||||||
|
- The TSDL file (``subsys/debug/tracing/ctf/tsdl/metadata``)
|
||||||
|
|
||||||
|
- The CTF output file renaming it to ``channel0_0``
|
||||||
|
|
||||||
|
- The trace can be opened by pointing TraceCompass or babeltrace to this new
|
||||||
|
directory
|
||||||
|
|
||||||
|
|
||||||
|
What is TraceCompass?
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
TraceCompass is an open source tool that visualizes CTF events such as thread
|
||||||
|
scheduling and interrupts, and is helpful to find unintended interactions and
|
||||||
|
resource conflicts on complex systems.
|
||||||
|
|
||||||
|
See also the presentation by Ericsson,
|
||||||
|
`Advanced Trouble-shooting Of Real-time Systems
|
||||||
|
<https://wiki.eclipse.org/images/0/0e/TechTalkOnlineDemoFeb2017_v1.pdf>`_.
|
||||||
|
|
||||||
|
|
||||||
|
Future LTTng Inspiration
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Currently, the middle-layer provided here is quite simple and bare-bones,
|
||||||
|
and needlessly copied from Zephyr's Segger SystemView debug module.
|
||||||
|
|
||||||
|
For an OS like Zephyr, it would make sense to draw inspiration from
|
||||||
|
Linux's LTTng and change the middle-layer to serialize to the same format.
|
||||||
|
Doing this would enable direct reuse of TraceCompass' canned analyses
|
||||||
|
for Linux. Alternatively, LTTng-analyses in TraceCompass could be
|
||||||
|
customized to Zephyr. It is ongoing work to enable TraceCompass
|
||||||
|
visibility of Zephyr in a target-agnostic and open source way.
|
||||||
|
|
||||||
|
|
||||||
|
I/O Taxonomy
|
||||||
|
------------
|
||||||
|
|
||||||
|
- Atomic Push/Produce/Write/Enqueue:
|
||||||
|
|
||||||
|
- synchronous:
|
||||||
|
means data-transmission has completed with the return of the
|
||||||
|
call.
|
||||||
|
|
||||||
|
- asynchronous:
|
||||||
|
means data-transmission is pending or ongoing with the return
|
||||||
|
of the call. Usually, interrupts/callbacks/signals or polling
|
||||||
|
is used to determine completion.
|
||||||
|
|
||||||
|
- buffered:
|
||||||
|
means data-transmissions are copied and grouped together to
|
||||||
|
form a larger ones. Usually for amortizing overhead (burst
|
||||||
|
dequeue) or jitter-mitigation (steady dequeue).
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- sync unbuffered
|
||||||
|
E.g. PIO via GPIOs having steady stream, no extra FIFO memory needed.
|
||||||
|
Low jitter but may be less efficient (cant amortize the overhead of
|
||||||
|
writing).
|
||||||
|
|
||||||
|
- sync buffered
|
||||||
|
E.g. ``fwrite()`` or enqueuing into FIFO.
|
||||||
|
Blockingly burst the FIFO when its buffer-waterlevel exceeds threshold.
|
||||||
|
Jitter due to bursts may lead to missed deadlines.
|
||||||
|
|
||||||
|
- async unbuffered
|
||||||
|
E.g. DMA, or zero-copying in shared memory.
|
||||||
|
Be careful of data hazards, race conditions, etc!
|
||||||
|
|
||||||
|
- async buffered
|
||||||
|
E.g. enqueuing into FIFO.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- Atomic Pull/Consume/Read/Dequeue:
|
||||||
|
|
||||||
|
- synchronous:
|
||||||
|
means data-reception has completed with the return of the call.
|
||||||
|
|
||||||
|
- asynchronous:
|
||||||
|
means data-reception is pending or ongoing with the return of
|
||||||
|
the call. Usually, interrupts/callbacks/signals or polling is
|
||||||
|
used to determine completion.
|
||||||
|
|
||||||
|
- buffered:
|
||||||
|
means data is copied-in in larger chunks than request-size.
|
||||||
|
Usually for amortizing wait-time.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- sync unbuffered
|
||||||
|
E.g. Blocking read-call, ``fread()`` or SPI-read, zero-copying in shared
|
||||||
|
memory.
|
||||||
|
|
||||||
|
- sync buffered
|
||||||
|
E.g. Blocking read-call with caching applied.
|
||||||
|
Makes sense if read pattern exhibits spatial locality.
|
||||||
|
|
||||||
|
- async unbuffered
|
||||||
|
E.g. zero-copying in shared memory.
|
||||||
|
Be careful of data hazards, race conditions, etc!
|
||||||
|
|
||||||
|
- async buffered
|
||||||
|
E.g. ``aio_read()`` or DMA.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Unfortunately, I/O may not be atomic and may, therefore, require locking.
|
||||||
|
Locking may not be needed if multiple independent channels are available.
|
||||||
|
|
||||||
|
- The system has non-atomic write and one shared channel
|
||||||
|
E.g. UART. Locking required.
|
||||||
|
|
||||||
|
``lock(); emit(a); emit(b); emit(c); release();``
|
||||||
|
|
||||||
|
- The system has non-atomic write but many channels
|
||||||
|
E.g. Multi-UART. Lock-free if the bottom-layer maps each Zephyr
|
||||||
|
thread+ISR to its own channel, thus alleviating races as each
|
||||||
|
thread is sequentially consistent with itself.
|
||||||
|
|
||||||
|
``emit(a,thread_id); emit(b,thread_id); emit(c,thread_id);``
|
||||||
|
|
||||||
|
- The system has atomic write but one shared channel
|
||||||
|
E.g. ``native_posix`` or board with DMA. May or may not need locking.
|
||||||
|
|
||||||
|
``emit(a ## b ## c); /* Concat to buffer */``
|
||||||
|
|
||||||
|
``lock(); emit(a); emit(b); emit(c); release(); /* No extra mem */``
|
||||||
|
|
||||||
|
- The system has atomic write and many channels
|
||||||
|
E.g. native_posix or board with multi-channel DMA. Lock-free.
|
||||||
|
|
||||||
|
``emit(a ## b ## c, thread_id);``
|
||||||
|
|
|
@ -27,4 +27,13 @@ it to *y*. For example, this can be added to the
|
||||||
|
|
||||||
.. _SEGGER SystemView: https://www.segger.com/products/development-tools/systemview/
|
.. _SEGGER SystemView: https://www.segger.com/products/development-tools/systemview/
|
||||||
|
|
||||||
|
Common Trace Format (CTF) Support
|
||||||
|
*********************************
|
||||||
|
|
||||||
|
Documentation on CTF support can be found in the following subsection:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
ctf.rst
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@
|
||||||
* [3] https://en.wikipedia.org/wiki/Map_(higher-order_function)
|
* [3] https://en.wikipedia.org/wiki/Map_(higher-order_function)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _CTF_MAP_H
|
#ifndef EXT_DEBUG_CTF_CTF_MAP_H
|
||||||
#define _CTF_MAP_H
|
#define EXT_DEBUG_CTF_CTF_MAP_H
|
||||||
|
|
||||||
#define EVAL0(...) __VA_ARGS__
|
#define EVAL0(...) __VA_ARGS__
|
||||||
#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
|
#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
|
||||||
|
@ -78,4 +78,4 @@
|
||||||
*/
|
*/
|
||||||
#define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
#define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
||||||
|
|
||||||
#endif /* _CTF_MAP_H */
|
#endif /* EXT_DEBUG_CTF_CTF_MAP_H */
|
||||||
|
|
|
@ -33,6 +33,9 @@ void z_sys_trace_thread_switched_out(void);
|
||||||
#elif defined CONFIG_TRACING_CPU_STATS
|
#elif defined CONFIG_TRACING_CPU_STATS
|
||||||
#include "tracing_cpu_stats.h"
|
#include "tracing_cpu_stats.h"
|
||||||
|
|
||||||
|
#elif defined CONFIG_TRACING_CTF
|
||||||
|
#include "tracing_ctf.h"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -257,6 +257,21 @@ config TRACING_CPU_STATS_INTERVAL
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
config TRACING_CTF
|
||||||
|
bool "Tracing via Common Trace Format support"
|
||||||
|
select THREAD_MONITOR
|
||||||
|
select TRACING
|
||||||
|
help
|
||||||
|
Enable tracing to a Common Trace Format stream. In order to use it a
|
||||||
|
CTF bottom layer should be selected, such as TRACING_CTF_BOTTOM_POSIX.
|
||||||
|
|
||||||
|
config TRACING_CTF_BOTTOM_POSIX
|
||||||
|
bool "CTF backend for the native_posix port, using a file in the host filesystem"
|
||||||
|
depends on TRACING_CTF
|
||||||
|
depends on ARCH_POSIX
|
||||||
|
help
|
||||||
|
Enable POSIX backend for CTF tracing. It will output the CTF stream to a
|
||||||
|
file using fwrite.
|
||||||
|
|
||||||
|
|
||||||
source "subsys/debug/Kconfig.segger"
|
source "subsys/debug/Kconfig.segger"
|
||||||
|
|
|
@ -10,3 +10,5 @@ zephyr_sources_ifdef(
|
||||||
CONFIG_TRACING_CPU_STATS
|
CONFIG_TRACING_CPU_STATS
|
||||||
cpu_stats.c
|
cpu_stats.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_subdirectory_ifdef(CONFIG_TRACING_CTF ctf)
|
||||||
|
|
4
subsys/debug/tracing/ctf/CMakeLists.txt
Normal file
4
subsys/debug/tracing/ctf/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
zephyr_include_directories(.)
|
||||||
|
zephyr_sources(ctf_top.c)
|
||||||
|
|
||||||
|
add_subdirectory_ifdef(CONFIG_TRACING_CTF_BOTTOM_POSIX bottoms/posix)
|
2
subsys/debug/tracing/ctf/bottoms/posix/CMakeLists.txt
Normal file
2
subsys/debug/tracing/ctf/bottoms/posix/CMakeLists.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
zephyr_include_directories(.)
|
||||||
|
zephyr_sources(ctf_bottom.c)
|
59
subsys/debug/tracing/ctf/bottoms/posix/ctf_bottom.c
Normal file
59
subsys/debug/tracing/ctf/bottoms/posix/ctf_bottom.c
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Oticon A/S
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ctf_bottom.h"
|
||||||
|
#include "soc.h"
|
||||||
|
#include "cmdline.h" /* native_posix command line options header */
|
||||||
|
#include "posix_trace.h"
|
||||||
|
|
||||||
|
|
||||||
|
ctf_bottom_ctx_t ctf_bottom;
|
||||||
|
|
||||||
|
void ctf_bottom_configure(void)
|
||||||
|
{
|
||||||
|
if (ctf_bottom.pathname == NULL) {
|
||||||
|
ctf_bottom.pathname = "channel0_0";
|
||||||
|
}
|
||||||
|
|
||||||
|
ctf_bottom.ostream = fopen(ctf_bottom.pathname, "wb");
|
||||||
|
if (ctf_bottom.ostream == NULL) {
|
||||||
|
posix_print_error_and_exit("CTF trace: "
|
||||||
|
"Problem opening file %s.\n",
|
||||||
|
ctf_bottom.pathname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ctf_bottom_start(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* command line option to specify ctf output file */
|
||||||
|
void add_ctf_option(void)
|
||||||
|
{
|
||||||
|
static struct args_struct_t ctf_options[] = {
|
||||||
|
/*
|
||||||
|
* Fields:
|
||||||
|
* manual, mandatory, switch,
|
||||||
|
* option_name, var_name ,type,
|
||||||
|
* destination, callback,
|
||||||
|
* description
|
||||||
|
*/
|
||||||
|
{ .manual = false,
|
||||||
|
.is_mandatory = false,
|
||||||
|
.is_switch = false,
|
||||||
|
.option = "ctf-path",
|
||||||
|
.name = "file_name",
|
||||||
|
.type = 's',
|
||||||
|
.dest = (void *)&ctf_bottom.pathname,
|
||||||
|
.call_when_found = NULL,
|
||||||
|
.descript = "File name for CTF tracing output." },
|
||||||
|
ARG_TABLE_ENDMARKER
|
||||||
|
};
|
||||||
|
|
||||||
|
native_add_command_line_opts(ctf_options);
|
||||||
|
}
|
||||||
|
NATIVE_TASK(add_ctf_option, PRE_BOOT_1, 1);
|
||||||
|
|
76
subsys/debug/tracing/ctf/bottoms/posix/ctf_bottom.h
Normal file
76
subsys/debug/tracing/ctf/bottoms/posix/ctf_bottom.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Oticon A/S
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SUBSYS_DEBUG_TRACING_BOTTOMS_POSIX_CTF_BOTTOM_H
|
||||||
|
#define SUBSYS_DEBUG_TRACING_BOTTOMS_POSIX_CTF_BOTTOM_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include <ctf_map.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Obtain a field's size at compile-time.
|
||||||
|
* Internal to this bottom-layer.
|
||||||
|
*/
|
||||||
|
#define CTF_BOTTOM_INTERNAL_FIELD_SIZE(x) + sizeof(x)
|
||||||
|
|
||||||
|
/* Append a field to current event-packet.
|
||||||
|
* Internal to this bottom-layer.
|
||||||
|
*/
|
||||||
|
#define CTF_BOTTOM_INTERNAL_FIELD_APPEND(x) \
|
||||||
|
{ \
|
||||||
|
memcpy(epacket_cursor, &(x), sizeof(x)); \
|
||||||
|
epacket_cursor += sizeof(x); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gather fields to a contiguous event-packet, then atomically emit.
|
||||||
|
* Used by middle-layer.
|
||||||
|
*/
|
||||||
|
#define CTF_BOTTOM_FIELDS(...) \
|
||||||
|
{ \
|
||||||
|
u8_t epacket[0 MAP(CTF_BOTTOM_INTERNAL_FIELD_SIZE, ##__VA_ARGS__)]; \
|
||||||
|
u8_t *epacket_cursor = &epacket[0]; \
|
||||||
|
\
|
||||||
|
MAP(CTF_BOTTOM_INTERNAL_FIELD_APPEND, ##__VA_ARGS__) \
|
||||||
|
ctf_bottom_emit(epacket, sizeof(epacket)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No need for locking when ctf_bottom_emit does POSIX fwrite(3) which is thread
|
||||||
|
* safe. Used by middle-layer.
|
||||||
|
*/
|
||||||
|
#define CTF_BOTTOM_LOCK() { /* empty */ }
|
||||||
|
#define CTF_BOTTOM_UNLOCK() { /* empty */ }
|
||||||
|
|
||||||
|
/* On native_posix board, the code must sample time by itself.
|
||||||
|
* Used by middle-layer.
|
||||||
|
*/
|
||||||
|
#define CTF_BOTTOM_TIMESTAMPED_INTERNALLY
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *pathname;
|
||||||
|
FILE *ostream;
|
||||||
|
} ctf_bottom_ctx_t;
|
||||||
|
|
||||||
|
extern ctf_bottom_ctx_t ctf_bottom;
|
||||||
|
|
||||||
|
|
||||||
|
/* Configure initializes ctf_bottom context and opens the IO channel */
|
||||||
|
void ctf_bottom_configure(void);
|
||||||
|
|
||||||
|
/* Start a new trace stream */
|
||||||
|
void ctf_bottom_start(void);
|
||||||
|
|
||||||
|
/* Emit IO in system-specific way */
|
||||||
|
static inline void ctf_bottom_emit(const void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
/* Simplest possible example is atomic fwrite */
|
||||||
|
fwrite(ptr, size, 1, ctf_bottom.ostream);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SUBSYS_DEBUG_TRACING_BOTTOMS_POSIX_CTF_BOTTOM_H */
|
217
subsys/debug/tracing/ctf/ctf_middle.h
Normal file
217
subsys/debug/tracing/ctf/ctf_middle.h
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Oticon A/S
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SUBSYS_DEBUG_TRACING_CTF_MIDDLE_H
|
||||||
|
#define SUBSYS_DEBUG_TRACING_CTF_MIDDLE_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctf_bottom.h>
|
||||||
|
|
||||||
|
/* Limit strings to 20 bytes to optimize bandwidth */
|
||||||
|
#define CTF_MAX_STRING_LEN 20
|
||||||
|
|
||||||
|
/* Optionally enter into a critical region, decided by bottom layer */
|
||||||
|
#define CTF_CRITICAL_REGION(x) \
|
||||||
|
{ \
|
||||||
|
CTF_BOTTOM_LOCK(); \
|
||||||
|
x; \
|
||||||
|
CTF_BOTTOM_UNLOCK(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CTF_BOTTOM_TIMESTAMPED_EXTERNALLY
|
||||||
|
/* Emit CTF event using the bottom-level IO mechanics */
|
||||||
|
#define CTF_EVENT(...) \
|
||||||
|
{ \
|
||||||
|
CTF_CRITICAL_REGION(CTF_BOTTOM_FIELDS(__VA_ARGS__)) \
|
||||||
|
}
|
||||||
|
#endif /* CTF_BOTTOM_TIMESTAMPED_EXTERNALLY */
|
||||||
|
|
||||||
|
#ifdef CTF_BOTTOM_TIMESTAMPED_INTERNALLY
|
||||||
|
/* Emit CTF event using the bottom-level IO mechanics. Prefix by sample time */
|
||||||
|
#define CTF_EVENT(...) \
|
||||||
|
{ \
|
||||||
|
const u32_t tstamp = k_cycle_get_32(); \
|
||||||
|
CTF_CRITICAL_REGION(CTF_BOTTOM_FIELDS(tstamp, __VA_ARGS__)) \
|
||||||
|
}
|
||||||
|
#endif /* CTF_BOTTOM_TIMESTAMPED_INTERNALLY */
|
||||||
|
|
||||||
|
|
||||||
|
/* Anonymous compound literal with 1 member. Legal since C99.
|
||||||
|
* This permits us to take the address of literals, like so:
|
||||||
|
* &CTF_LITERAL(int, 1234)
|
||||||
|
*
|
||||||
|
* This may be required if a ctf_bottom layer uses memcpy.
|
||||||
|
*
|
||||||
|
* NOTE string literals already support address-of and sizeof,
|
||||||
|
* so string literals should not be wrapped with CTF_LITERAL.
|
||||||
|
*/
|
||||||
|
#define CTF_LITERAL(type, value) ((type) { (type)(value) })
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CTF_EVENT_THREAD_SWITCHED_OUT = 0x10,
|
||||||
|
CTF_EVENT_THREAD_SWITCHED_IN = 0x11,
|
||||||
|
CTF_EVENT_THREAD_PRIORITY_SET = 0x12,
|
||||||
|
CTF_EVENT_THREAD_CREATE = 0x13,
|
||||||
|
CTF_EVENT_THREAD_ABORT = 0x14,
|
||||||
|
CTF_EVENT_THREAD_SUSPEND = 0x15,
|
||||||
|
CTF_EVENT_THREAD_RESUME = 0x16,
|
||||||
|
CTF_EVENT_THREAD_READY = 0x17,
|
||||||
|
CTF_EVENT_THREAD_PENDING = 0x18,
|
||||||
|
CTF_EVENT_THREAD_INFO = 0x19,
|
||||||
|
CTF_EVENT_ISR_ENTER = 0x20,
|
||||||
|
CTF_EVENT_ISR_EXIT = 0x21,
|
||||||
|
CTF_EVENT_ISR_EXIT_TO_SCHEDULER = 0x22,
|
||||||
|
CTF_EVENT_IDLE = 0x30,
|
||||||
|
CTF_EVENT_ID_START_CALL = 0x41,
|
||||||
|
CTF_EVENT_ID_END_CALL = 0x42
|
||||||
|
} ctf_event_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char buf[CTF_MAX_STRING_LEN];
|
||||||
|
} ctf_bounded_string_t;
|
||||||
|
|
||||||
|
|
||||||
|
static inline void ctf_middle_thread_switched_out(u32_t thread_id)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_THREAD_SWITCHED_OUT),
|
||||||
|
thread_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_thread_switched_in(u32_t thread_id)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_THREAD_SWITCHED_IN),
|
||||||
|
thread_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_thread_priority_set(u32_t thread_id, s8_t prio)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_THREAD_PRIORITY_SET),
|
||||||
|
thread_id,
|
||||||
|
prio
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_thread_create(
|
||||||
|
u32_t thread_id,
|
||||||
|
s8_t prio,
|
||||||
|
ctf_bounded_string_t name
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_THREAD_CREATE),
|
||||||
|
thread_id,
|
||||||
|
name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_thread_abort(u32_t thread_id)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_THREAD_ABORT),
|
||||||
|
thread_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_thread_suspend(u32_t thread_id)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_THREAD_SUSPEND),
|
||||||
|
thread_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_thread_resume(u32_t thread_id)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_THREAD_RESUME),
|
||||||
|
thread_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_thread_ready(u32_t thread_id)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_THREAD_READY),
|
||||||
|
thread_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_thread_pend(u32_t thread_id)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_THREAD_PENDING),
|
||||||
|
thread_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_thread_info(
|
||||||
|
u32_t thread_id,
|
||||||
|
u32_t stack_base,
|
||||||
|
u32_t stack_size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_THREAD_INFO),
|
||||||
|
thread_id,
|
||||||
|
stack_base,
|
||||||
|
stack_size
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_isr_enter(void)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_ISR_ENTER)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_isr_exit(void)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_ISR_EXIT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_isr_exit_to_scheduler(void)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_ISR_EXIT_TO_SCHEDULER)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_idle(void)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_IDLE)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_void(u32_t id)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_ID_START_CALL),
|
||||||
|
id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ctf_middle_end_call(u32_t id)
|
||||||
|
{
|
||||||
|
CTF_EVENT(
|
||||||
|
CTF_LITERAL(u8_t, CTF_EVENT_ID_END_CALL),
|
||||||
|
id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SUBSYS_DEBUG_TRACING_CTF_MIDDLE_H */
|
177
subsys/debug/tracing/ctf/ctf_top.c
Normal file
177
subsys/debug/tracing/ctf/ctf_top.c
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Oticon A/S
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr.h>
|
||||||
|
#include <kernel_structs.h>
|
||||||
|
#include <init.h>
|
||||||
|
|
||||||
|
#include <ctf_middle.h>
|
||||||
|
#include "ctf_top.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CONFIG_SMP
|
||||||
|
extern k_tid_t const _idle_thread;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline int is_idle_thread(struct k_thread *thread)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
return thread->base.is_idle;
|
||||||
|
#else
|
||||||
|
return thread == _idle_thread;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_thread_switched_out(void)
|
||||||
|
{
|
||||||
|
struct k_thread *thread = k_current_get();
|
||||||
|
|
||||||
|
ctf_middle_thread_switched_out((u32_t)(uintptr_t)thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_thread_switched_in(void)
|
||||||
|
{
|
||||||
|
struct k_thread *thread = k_current_get();
|
||||||
|
|
||||||
|
ctf_middle_thread_switched_in((u32_t)(uintptr_t)thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_thread_priority_set(struct k_thread *thread)
|
||||||
|
{
|
||||||
|
ctf_middle_thread_priority_set((u32_t)(uintptr_t)thread,
|
||||||
|
thread->base.prio);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_thread_create(struct k_thread *thread)
|
||||||
|
{
|
||||||
|
ctf_bounded_string_t name = { "Unnamed thread" };
|
||||||
|
|
||||||
|
#if defined(CONFIG_THREAD_NAME)
|
||||||
|
if (thread->name != NULL) {
|
||||||
|
strncpy(name.buf, thread->name, sizeof(name.buf));
|
||||||
|
/* strncpy may not always null-terminate */
|
||||||
|
name.buf[sizeof(name.buf) - 1] = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ctf_middle_thread_create(
|
||||||
|
(u32_t)(uintptr_t)thread,
|
||||||
|
thread->base.prio,
|
||||||
|
name
|
||||||
|
);
|
||||||
|
|
||||||
|
#if defined(CONFIG_THREAD_STACK_INFO)
|
||||||
|
ctf_middle_thread_info(
|
||||||
|
(u32_t)(uintptr_t)thread,
|
||||||
|
thread->stack_info.size,
|
||||||
|
thread->stack_info.start
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_thread_abort(struct k_thread *thread)
|
||||||
|
{
|
||||||
|
ctf_middle_thread_abort((u32_t)(uintptr_t)thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_thread_suspend(struct k_thread *thread)
|
||||||
|
{
|
||||||
|
ctf_middle_thread_suspend((u32_t)(uintptr_t)thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_thread_resume(struct k_thread *thread)
|
||||||
|
{
|
||||||
|
ctf_middle_thread_resume((u32_t)(uintptr_t)thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_thread_ready(struct k_thread *thread)
|
||||||
|
{
|
||||||
|
ctf_middle_thread_ready((u32_t)(uintptr_t)thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_thread_pend(struct k_thread *thread)
|
||||||
|
{
|
||||||
|
ctf_middle_thread_pend((u32_t)(uintptr_t)thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_thread_info(struct k_thread *thread)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_THREAD_STACK_INFO)
|
||||||
|
ctf_middle_thread_info(
|
||||||
|
(u32_t)(uintptr_t)thread,
|
||||||
|
thread->stack_info.size,
|
||||||
|
thread->stack_info.start
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_isr_enter(void)
|
||||||
|
{
|
||||||
|
ctf_middle_isr_enter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_isr_exit(void)
|
||||||
|
{
|
||||||
|
ctf_middle_isr_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_isr_exit_to_scheduler(void)
|
||||||
|
{
|
||||||
|
ctf_middle_isr_exit_to_scheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_idle(void)
|
||||||
|
{
|
||||||
|
ctf_middle_idle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_void(unsigned int id)
|
||||||
|
{
|
||||||
|
ctf_middle_void(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_trace_end_call(unsigned int id)
|
||||||
|
{
|
||||||
|
ctf_middle_end_call(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void z_sys_trace_thread_switched_out(void)
|
||||||
|
{
|
||||||
|
sys_trace_thread_switched_out();
|
||||||
|
}
|
||||||
|
void z_sys_trace_thread_switched_in(void)
|
||||||
|
{
|
||||||
|
sys_trace_thread_switched_in();
|
||||||
|
}
|
||||||
|
void z_sys_trace_isr_enter(void)
|
||||||
|
{
|
||||||
|
sys_trace_isr_enter();
|
||||||
|
}
|
||||||
|
void z_sys_trace_isr_exit(void)
|
||||||
|
{
|
||||||
|
sys_trace_isr_exit();
|
||||||
|
}
|
||||||
|
void z_sys_trace_isr_exit_to_scheduler(void)
|
||||||
|
{
|
||||||
|
sys_trace_isr_exit_to_scheduler();
|
||||||
|
}
|
||||||
|
void z_sys_trace_idle(void)
|
||||||
|
{
|
||||||
|
sys_trace_idle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ctf_top_init(struct device *arg)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(arg);
|
||||||
|
|
||||||
|
ctf_bottom_configure();
|
||||||
|
ctf_bottom_start();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(ctf_top_init, PRE_KERNEL_1, 0);
|
11
subsys/debug/tracing/ctf/ctf_top.h
Normal file
11
subsys/debug/tracing/ctf/ctf_top.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Oticon A/S
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SUBSYS_DEBUG_TRACING_CTF_TOP_H
|
||||||
|
#define SUBSYS_DEBUG_TRACING_CTF_TOP_H
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SUBSYS_DEBUG_TRACING_CTF_TOP_H */
|
150
subsys/debug/tracing/ctf/tsdl/metadata
Normal file
150
subsys/debug/tracing/ctf/tsdl/metadata
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/* CTF 1.8 */
|
||||||
|
typealias integer { size = 8; align = 8; signed = true; } := int8_t;
|
||||||
|
typealias integer { size = 8; align = 8; signed = false; } := uint8_t;
|
||||||
|
typealias integer { size = 16; align = 8; signed = false; } := uint16_t;
|
||||||
|
typealias integer { size = 32; align = 8; signed = false; } := uint32_t;
|
||||||
|
typealias integer { size = 64; align = 8; signed = false; } := uint64_t;
|
||||||
|
typealias integer { size = 8; align = 8; signed = false; encoding = ASCII; } := ctf_bounded_string_t;
|
||||||
|
typealias enum : uint32_t {
|
||||||
|
MUTEX_INIT = 33,
|
||||||
|
MUTEX_UNLOCK = 34,
|
||||||
|
MUTEX_LOCK = 35,
|
||||||
|
SEMA_INIT = 36,
|
||||||
|
SEMA_GIVE = 37,
|
||||||
|
SEMA_TAKE = 38
|
||||||
|
} := call_id;
|
||||||
|
|
||||||
|
struct event_header {
|
||||||
|
uint32_t timestamp;
|
||||||
|
uint8_t id;
|
||||||
|
};
|
||||||
|
|
||||||
|
trace {
|
||||||
|
major = 1;
|
||||||
|
minor = 8;
|
||||||
|
byte_order = le;
|
||||||
|
};
|
||||||
|
|
||||||
|
stream {
|
||||||
|
event.header := struct event_header;
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = thread_switched_out;
|
||||||
|
id = 0x10;
|
||||||
|
fields := struct {
|
||||||
|
uint32_t thread_id;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = thread_switched_in;
|
||||||
|
id = 0x11;
|
||||||
|
fields := struct {
|
||||||
|
uint32_t thread_id;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = thread_priority_set;
|
||||||
|
id = 0x12;
|
||||||
|
fields := struct {
|
||||||
|
uint32_t thread_id;
|
||||||
|
int8_t prio;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = thread_create;
|
||||||
|
id = 0x13;
|
||||||
|
fields := struct {
|
||||||
|
uint32_t thread_id;
|
||||||
|
ctf_bounded_string_t name[20];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = thread_abort;
|
||||||
|
id = 0x14;
|
||||||
|
fields := struct {
|
||||||
|
uint32_t thread_id;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = thread_suspend;
|
||||||
|
id = 0x15;
|
||||||
|
fields := struct {
|
||||||
|
uint32_t thread_id;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = thread_resume;
|
||||||
|
id = 0x16;
|
||||||
|
fields := struct {
|
||||||
|
uint32_t thread_id;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
event {
|
||||||
|
name = thread_ready;
|
||||||
|
id = 0x17;
|
||||||
|
fields := struct {
|
||||||
|
uint32_t thread_id;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = thread_pending;
|
||||||
|
id = 0x18;
|
||||||
|
fields := struct {
|
||||||
|
uint32_t thread_id;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = thread_info;
|
||||||
|
id = 0x19;
|
||||||
|
fields := struct {
|
||||||
|
uint32_t thread_id;
|
||||||
|
uint32_t stack_base;
|
||||||
|
uint32_t stack_size;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = isr_enter;
|
||||||
|
id = 0x20;
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = isr_exit;
|
||||||
|
id = 0x21;
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = isr_exit_to_scheduler;
|
||||||
|
id = 0x22;
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = idle;
|
||||||
|
id = 0x30;
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = start_call;
|
||||||
|
id = 0x41;
|
||||||
|
fields := struct {
|
||||||
|
call_id id;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
event {
|
||||||
|
name = end_call;
|
||||||
|
id = 0x42;
|
||||||
|
fields := struct {
|
||||||
|
call_id id;
|
||||||
|
};
|
||||||
|
};
|
39
subsys/debug/tracing/include/tracing_ctf.h
Normal file
39
subsys/debug/tracing/include/tracing_ctf.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Oticon A/S
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TRACE_CTF_H
|
||||||
|
#define _TRACE_CTF_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <kernel_structs.h>
|
||||||
|
#include <init.h>
|
||||||
|
|
||||||
|
void sys_trace_thread_switched_out(void);
|
||||||
|
void sys_trace_thread_switched_in(void);
|
||||||
|
void sys_trace_thread_priority_set(struct k_thread *thread);
|
||||||
|
void sys_trace_thread_create(struct k_thread *thread);
|
||||||
|
void sys_trace_thread_abort(struct k_thread *thread);
|
||||||
|
void sys_trace_thread_suspend(struct k_thread *thread);
|
||||||
|
void sys_trace_thread_resume(struct k_thread *thread);
|
||||||
|
void sys_trace_thread_ready(struct k_thread *thread);
|
||||||
|
void sys_trace_thread_pend(struct k_thread *thread);
|
||||||
|
void sys_trace_thread_info(struct k_thread *thread);
|
||||||
|
void sys_trace_isr_enter(void);
|
||||||
|
void sys_trace_isr_exit(void);
|
||||||
|
void sys_trace_isr_exit_to_scheduler(void);
|
||||||
|
void sys_trace_idle(void);
|
||||||
|
void sys_trace_void(unsigned int id);
|
||||||
|
void sys_trace_end_call(unsigned int id);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _TRACE_CTF_H */
|
Loading…
Add table
Add a link
Reference in a new issue