Skip to content

Commit 139407f

Browse files
gromeronashif
authored andcommitted
instrumentation: Add instrumentation subsystem
This commit adds the instrumentation subsystem. Signed-off-by: Gustavo Romero <[email protected]> Signed-off-by: Kevin Townsend <[email protected]> Signed-off-by: Maciej Sobkowski <[email protected]>
1 parent 217bb19 commit 139407f

File tree

14 files changed

+1536
-0
lines changed

14 files changed

+1536
-0
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
/*
2+
* Copyright 2023 Linaro
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_INCLUDE_INSTRUMENTATION_INSTRUMENTATION_H_
8+
#define ZEPHYR_INCLUDE_INSTRUMENTATION_INSTRUMENTATION_H_
9+
10+
#include <zephyr/kernel.h>
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
#if !defined(__no_instrumentation__)
17+
#error "No toolchain support for __no_instrumentation__"
18+
#endif
19+
20+
/**
21+
* @brief Instrumentation event record types.
22+
*/
23+
enum instr_event_types {
24+
INSTR_EVENT_ENTRY = 0, /**< Callee entry event record, followed by instr_event. */
25+
INSTR_EVENT_EXIT, /**< Callee exit event record, followed by instr_event. */
26+
INSTR_EVENT_PROFILE, /**< Profile events */
27+
INSTR_EVENT_SCHED_IN, /**< Thread switched in scheduler event */
28+
INSTR_EVENT_SCHED_OUT, /**< Thread switched out scheduler event */
29+
INSTR_EVENT_NUM, /**< Add more events above this one */
30+
INSTR_EVENT_INVALID /**< Invalid or no event generated after promotion */
31+
} __packed;
32+
33+
/**
34+
* @brief Header for the event records.
35+
*/
36+
struct instr_header {
37+
/** Event type */
38+
enum instr_event_types type;
39+
} __packed;
40+
41+
/**
42+
* @brief Context-specific data of an event.
43+
*/
44+
struct instr_event_context {
45+
/** Arch-specific mode indicator (thread mode, interrupt mode, etc.). */
46+
uint8_t mode: 3;
47+
/** CPU number. */
48+
uint8_t cpu: 5;
49+
/** Thread ID (correlate values with thread lookup table). */
50+
void *thread_id;
51+
#ifdef CONFIG_THREAD_NAME
52+
/** Thread name (that can be compacted with the correlate lookup table). */
53+
char thread_name[CONFIG_THREAD_MAX_NAME_LEN];
54+
#endif
55+
} __packed;
56+
57+
/**
58+
* @brief Event records and associated payloads. Payloads are determined based
59+
* on the code and additional fields in the header.
60+
*/
61+
struct instr_record {
62+
struct instr_header header;
63+
void *callee;
64+
void *caller;
65+
uint64_t timestamp;
66+
union {
67+
struct instr_event_context context; /* Context data */
68+
/* Add more payloads here */
69+
};
70+
} __packed;
71+
72+
/**
73+
* @brief Checks if tracing feature is available.
74+
*
75+
*/
76+
bool instr_tracing_supported(void);
77+
78+
/**
79+
* @brief Checks if profiling feature is available.
80+
*
81+
*/
82+
bool instr_profiling_supported(void);
83+
84+
/**
85+
* @brief Checks if subsystem is ready to be initialized. Must called be before
86+
* instr_init().
87+
*/
88+
bool instr_fundamentals_initialized(void);
89+
90+
/**
91+
* @brief Performs initialisation required by the system.
92+
*/
93+
int instr_init(void);
94+
95+
/**
96+
* @brief Tells if instrumentation subsystem is properly initialized.
97+
*/
98+
bool instr_initialized(void);
99+
100+
/**
101+
* @brief Tells if instrumentation is enabled, i.e. can be turned on.
102+
*/
103+
bool instr_enabled(void);
104+
105+
/**
106+
* @brief Enables instrumentation.
107+
*/
108+
int instr_enable(void);
109+
110+
/**
111+
* @brief Disables instrumentation.
112+
*/
113+
int instr_disable(void);
114+
115+
/**
116+
* @brief Turns on instrumentation (start recording events).
117+
*/
118+
int instr_turn_on(void);
119+
120+
/**
121+
* @brief Turns off instrumentation (stop recording events).
122+
*/
123+
int instr_turn_off(void);
124+
125+
/**
126+
* @brief Tells if instrumentation is turned on.
127+
*/
128+
bool instr_turned_on(void);
129+
130+
/**
131+
* @brief Tells if instrumentation can collect traces.
132+
*/
133+
bool instr_trace_enabled(void);
134+
135+
/**
136+
* @brief Tells if instrumentation can collect profile info.
137+
*/
138+
bool instr_profile_enabled(void);
139+
140+
/**
141+
* @brief Dumps the buffered contents via UART (tracing).
142+
*/
143+
void instr_dump_buffer_uart(void);
144+
145+
/**
146+
* @brief Dumps the delta accumulator array via UART (profiling).
147+
*/
148+
void instr_dump_deltas_uart(void);
149+
150+
/**
151+
* @brief Shared callback handler to process entry/exit events.
152+
*
153+
* @param opcode The type of event to process.
154+
* @param func Address of the function being called.
155+
* @param caller Address of the function caller.
156+
*/
157+
void instr_event_handler(enum instr_event_types opcode, void *func, void *caller);
158+
159+
/**
160+
* @brief Given a function address, set it as the trigger function, i.e. when
161+
* the function is called it will turn on the instrumentation.
162+
*
163+
* @param callee The function address
164+
*/
165+
void instr_set_trigger_func(void *callee);
166+
167+
/**
168+
* @brief Given a function address, set it as the stopper function, i.e. when
169+
* the function exits it will turn off the instrumentation.
170+
*
171+
* @param callee The function address
172+
*/
173+
void instr_set_stop_func(void *callee);
174+
175+
/**
176+
* @brief Get the trigger function address.
177+
*
178+
*/
179+
void *instr_get_trigger_func(void);
180+
181+
/**
182+
* @brief Get the stopper function address.
183+
*
184+
*/
185+
void *instr_get_stop_func(void);
186+
187+
#ifdef __cplusplus
188+
}
189+
#endif
190+
191+
#endif /* ZEPHYR_INCLUDE_INSTRUMENTATION_INSTRUMENTATION_H_ */

subsys/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ add_subdirectory(debug)
1717
add_subdirectory(fb)
1818
add_subdirectory(fs)
1919
add_subdirectory(gnss)
20+
add_subdirectory(instrumentation)
2021
add_subdirectory(ipc)
2122
add_subdirectory(logging)
2223
add_subdirectory(mem_mgmt)

subsys/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ source "subsys/fb/Kconfig"
2525
source "subsys/fs/Kconfig"
2626
source "subsys/gnss/Kconfig"
2727
source "subsys/input/Kconfig"
28+
source "subsys/instrumentation/Kconfig"
2829
source "subsys/ipc/Kconfig"
2930
source "subsys/jwt/Kconfig"
3031
source "subsys/llext/Kconfig"
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright 2023 Linaro
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
zephyr_sources_ifdef(CONFIG_INSTRUMENTATION
5+
common/instr_common.c
6+
timestamp/timestamp.c
7+
transport/uart.c
8+
)
9+
10+
zephyr_sources_ifdef(CONFIG_INSTRUMENTATION_MODE_CALLGRAPH ringbuffer/ringbuffer.c)
11+
12+
if(CONFIG_INSTRUMENTATION)
13+
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
14+
zephyr_sources(handlers/instr_handlers_gcc.c)
15+
else()
16+
message(WARNING "CONFIG_INSTRUMENTATION unsupported by this compiler: ${CMAKE_C_COMPILER_ID}.")
17+
endif()
18+
19+
configure_file(${CMAKE_CURRENT_LIST_DIR}/ctf/metadata.template ${CMAKE_BINARY_DIR}/ctf_metadata @ONLY)
20+
endif()
21+
22+
zephyr_compile_definitions_ifdef(CONFIG_INSTRUMENTATION INSTR_TRIGGER_FUNCTION=${CONFIG_INSTRUMENTATION_TRIGGER_FUNCTION})
23+
zephyr_compile_definitions_ifdef(CONFIG_INSTRUMENTATION INSTR_STOPPER_FUNCTION=${CONFIG_INSTRUMENTATION_STOPPER_FUNCTION})
24+
zephyr_include_directories_ifdef(CONFIG_INSTRUMENTATION include)

subsys/instrumentation/Kconfig

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Copyright 2023 Linaro
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# Instrumentation configuration options
5+
6+
config INSTRUMENTATION
7+
bool "Compiler Instrumentation Support"
8+
select REBOOT
9+
select RETAINED_MEM
10+
select RETAINED_MEM_ZEPHYR_RAM
11+
select RETAINED_MEM_MUTEX_FORCE_DISABLE
12+
select RETENTION
13+
select RETENTION_MUTEX_FORCE_DISABLE
14+
select UART_INTERRUPT_DRIVEN
15+
help
16+
Enable compiler-managed runtime system instrumentation. This requires
17+
a compiler that supports function instrumentation, and a backend for
18+
capturing and processing those instrumentation events from the target,
19+
like a serial port.
20+
21+
if INSTRUMENTATION
22+
23+
config INSTRUMENTATION_MODE_CALLGRAPH
24+
bool "Call graph mode (Tracing)"
25+
default y
26+
select THREAD_NAME
27+
select TRACING
28+
select TIMING_FUNCTIONS
29+
help
30+
Enables reconstruction of function call graphs and the observation
31+
of context switches (threads), within the limits of the trace buffer
32+
size.
33+
34+
config INSTRUMENTATION_MODE_CALLGRAPH_TRACE_BUFFER_SIZE
35+
int "Size of the trace buffer (bytes)"
36+
depends on INSTRUMENTATION_MODE_CALLGRAPH
37+
default 12000
38+
# Lower limit (in bytes) must match the biggest record item size. For
39+
# details about the sizes, please see instrumentation.h for the record
40+
# struct sizes.
41+
range 20 4294967296
42+
help
43+
Size of the trace buffer. The trace buffer is used to buffer the
44+
tracing events and has two working modes: it can be configure either
45+
as a simple buffer or as a ring buffer (overwriting mode).
46+
47+
config INSTRUMENTATION_MODE_CALLGRAPH_BUFFER_OVERWRITE
48+
bool "Trace buffer overwriting mode"
49+
depends on INSTRUMENTATION_MODE_CALLGRAPH
50+
default y
51+
help
52+
If the trace buffer is set as overwriting it works as a ring buffer.
53+
In this working mode if the buffer gets full old records will be
54+
overwritten by the newer records. This mode allows recording the most
55+
recent tracing events at the expense of losing the old ones. If this
56+
mode is not selected, then once the buffer is full tracing stops.
57+
58+
config INSTRUMENTATION_MODE_STATISTICAL
59+
bool "Statistical mode (Profiling)"
60+
select TIMING_FUNCTIONS
61+
default y
62+
help
63+
Enables statistical profiling of the runtime system, tracking total
64+
execution time of the number of functions equal to
65+
INSTRUMENTATION_MODE_STATISTICAL_MAX_NUM_FUNC.
66+
67+
config INSTRUMENTATION_MODE_STATISTICAL_MAX_NUM_FUNC
68+
int "Maximum number of functions to collect statistics from"
69+
depends on INSTRUMENTATION_MODE_STATISTICAL
70+
default 256
71+
range 1 4096
72+
help
73+
Maximum number of functions to collect statistics from. Set the
74+
maximum number of functions to collect the total execution time for
75+
each function called in the region defined by 'trigger' and 'stopper'
76+
instrumentation points.
77+
78+
config INSTRUMENTATION_MODE_STATISTICAL_MAX_CALL_DEPTH
79+
int "Maximum call depth"
80+
depends on INSTRUMENTATION_MODE_STATISTICAL
81+
default 65535
82+
range 1 65535
83+
help
84+
The maximum number of times a function can be recursively called
85+
before profile data (delta time) stops being collected.
86+
87+
config INSTRUMENTATION_TRIGGER_FUNCTION
88+
string "Default trigger function used to turn on instrumentation"
89+
default "main"
90+
help
91+
Sets the trigger function. Instrumentation (tracing and profiling) is
92+
only turned on when the trigger function is called. The trigger
93+
function can be changed at runtime via the 'zaru' CLI tool.
94+
95+
config INSTRUMENTATION_STOPPER_FUNCTION
96+
string "Default stopper function used to turn off instrumentation"
97+
default "main"
98+
help
99+
Sets the stopper function. Instrumentation (tracing and profiling) is
100+
only turned off when the trigger function returns. The stopper
101+
function can be changed at runtime via the 'zaru' CLI tool.
102+
103+
config INSTRUMENTATION_EXCLUDE_FUNCTION_LIST
104+
string "Exclude function list"
105+
depends on INSTRUMENTATION_MODE_CALLGRAPH || INSTRUMENTATION_MODE_STATISTICAL
106+
help
107+
Set the list of function names to be excluded from instrumentation.
108+
The function name to be matched is its user-visible name. The match is
109+
done on substrings: if the function name in the list is a substring of
110+
a function name, it is considered to be a match. The function names in
111+
the list are separate by a comma, for instance: sym0, sym1, ...
112+
113+
config INSTRUMENTATION_EXCLUDE_FILE_LIST
114+
string "Exclude file list"
115+
depends on INSTRUMENTATION_MODE_CALLGRAPH || INSTRUMENTATION_MODE_STATISTICAL
116+
help
117+
Set the list of files that are excluded from instrumentation. The
118+
match is done on substrings: if the file parameter is a substring of
119+
the file name, it is considered to be a match. The files in the list
120+
are separate by a comma, for instance: file0, file1, ...
121+
122+
endif

0 commit comments

Comments
 (0)