Browse Source

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>
pull/12974/head
François Delawarde 7 years ago committed by Anas Nashif
parent
commit
4fac841869
  1. 7
      boards/posix/native_posix/Kconfig.defconfig
  2. 236
      doc/subsystems/tracing/ctf.rst
  3. 9
      doc/subsystems/tracing/index.rst
  4. 6
      ext/debug/ctf/ctf_map.h
  5. 3
      include/tracing.h
  6. 15
      subsys/debug/Kconfig
  7. 2
      subsys/debug/tracing/CMakeLists.txt
  8. 4
      subsys/debug/tracing/ctf/CMakeLists.txt
  9. 2
      subsys/debug/tracing/ctf/bottoms/posix/CMakeLists.txt
  10. 59
      subsys/debug/tracing/ctf/bottoms/posix/ctf_bottom.c
  11. 76
      subsys/debug/tracing/ctf/bottoms/posix/ctf_bottom.h
  12. 217
      subsys/debug/tracing/ctf/ctf_middle.h
  13. 177
      subsys/debug/tracing/ctf/ctf_top.c
  14. 11
      subsys/debug/tracing/ctf/ctf_top.h
  15. 150
      subsys/debug/tracing/ctf/tsdl/metadata
  16. 39
      subsys/debug/tracing/include/tracing_ctf.h

7
boards/posix/native_posix/Kconfig.defconfig

@ -79,4 +79,11 @@ config SDL_DISPLAY @@ -79,4 +79,11 @@ config SDL_DISPLAY
endif # DISPLAY
if TRACING_CTF
config TRACING_CTF_BOTTOM_POSIX
default y
endif # TRACING_CTF
endif # BOARD_NATIVE_POSIX

236
doc/subsystems/tracing/ctf.rst

@ -0,0 +1,236 @@ @@ -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);``

9
doc/subsystems/tracing/index.rst

@ -27,4 +27,13 @@ it to *y*. For example, this can be added to the @@ -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/
Common Trace Format (CTF) Support
*********************************
Documentation on CTF support can be found in the following subsection:
.. toctree::
:maxdepth: 1
ctf.rst

6
ext/debug/ctf/ctf_map.h

@ -37,8 +37,8 @@ @@ -37,8 +37,8 @@
* [3] https://en.wikipedia.org/wiki/Map_(higher-order_function)
*/
#ifndef _CTF_MAP_H
#define _CTF_MAP_H
#ifndef EXT_DEBUG_CTF_CTF_MAP_H
#define EXT_DEBUG_CTF_CTF_MAP_H
#define EVAL0(...) __VA_ARGS__
#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
@ -78,4 +78,4 @@ @@ -78,4 +78,4 @@
*/
#define MAP_LIST(f, ...) EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
#endif /* _CTF_MAP_H */
#endif /* EXT_DEBUG_CTF_CTF_MAP_H */

3
include/tracing.h

@ -33,6 +33,9 @@ void z_sys_trace_thread_switched_out(void); @@ -33,6 +33,9 @@ void z_sys_trace_thread_switched_out(void);
#elif defined CONFIG_TRACING_CPU_STATS
#include "tracing_cpu_stats.h"
#elif defined CONFIG_TRACING_CTF
#include "tracing_ctf.h"
#else
/**

15
subsys/debug/Kconfig

@ -257,6 +257,21 @@ config TRACING_CPU_STATS_INTERVAL @@ -257,6 +257,21 @@ config TRACING_CPU_STATS_INTERVAL
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"

2
subsys/debug/tracing/CMakeLists.txt

@ -10,3 +10,5 @@ zephyr_sources_ifdef( @@ -10,3 +10,5 @@ zephyr_sources_ifdef(
CONFIG_TRACING_CPU_STATS
cpu_stats.c
)
add_subdirectory_ifdef(CONFIG_TRACING_CTF ctf)

4
subsys/debug/tracing/ctf/CMakeLists.txt

@ -0,0 +1,4 @@ @@ -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

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
zephyr_include_directories(.)
zephyr_sources(ctf_bottom.c)

59
subsys/debug/tracing/ctf/bottoms/posix/ctf_bottom.c

@ -0,0 +1,59 @@ @@ -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

@ -0,0 +1,76 @@ @@ -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

@ -0,0 +1,217 @@ @@ -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

@ -0,0 +1,177 @@ @@ -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

@ -0,0 +1,11 @@ @@ -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

@ -0,0 +1,150 @@ @@ -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

@ -0,0 +1,39 @@ @@ -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…
Cancel
Save