From 16bbb8ef34331d82c382c431898db4804c841dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Leksell?= Date: Fri, 26 Mar 2021 08:31:23 +0100 Subject: [PATCH] Tracing: Trace hook support macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds generic trace hook macros for inserting trace hook for function entry, exit, blocking, and object initialization with a variable number of arguments (objects, return values, etc.). Utilizing macro concatenation these macros produce trace hooks of a similar format to the old trace system with SYS_TRACING_OBJ_FUNC(k_thread, switched_in) being turned into sys_trace_k_thread_switched_in() by the preprocessor. Although these macros still rely on the manual definition of each unique trace hook in tracing.h, the benefit of not directly calling those is that we can enable/disable trace hooks based on object type (k_thread, k_sem, etc.) through the preprocessor while providing the ability of adding type specific runtime trace processing similar to SYS_TRACING_OBJ_INIT. Signed-off-by: Torbjörn Leksell Signed-off-by: Anas Nashif --- include/kernel.h | 1 + include/tracing/tracing_macros.h | 321 +++++++++++++++++++++++++++++++ subsys/tracing/Kconfig | 100 +++++++++- 3 files changed, 421 insertions(+), 1 deletion(-) create mode 100644 include/tracing/tracing_macros.h diff --git a/include/kernel.h b/include/kernel.h index 5f1d2d37343..5fa7bde848e 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS #include diff --git a/include/tracing/tracing_macros.h b/include/tracing/tracing_macros.h new file mode 100644 index 00000000000..8ad92d1b163 --- /dev/null +++ b/include/tracing/tracing_macros.h @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_TRACING_TRACING_MACROS_H_ +#define ZEPHYR_INCLUDE_TRACING_TRACING_MACROS_H_ + +#ifndef CONFIG_TRACING + +#define SYS_PORT_TRACING_FUNC(type, func, ...) do { } while (false) +#define SYS_PORT_TRACING_FUNC_ENTER(type, func, ...) do { } while (false) +#define SYS_PORT_TRACING_FUNC_BLOCKING(type, func, ...) do { } while (false) +#define SYS_PORT_TRACING_FUNC_EXIT(type, func, ...) do { } while (false) +#define SYS_PORT_TRACING_OBJ_INIT(obj_type, obj, ...) do { } while (false) +#define SYS_PORT_TRACING_OBJ_FUNC(obj_type, func, obj, ...) do { } while (false) +#define SYS_PORT_TRACING_OBJ_FUNC_ENTER(obj_type, func, obj, ...) do { } while (false) +#define SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(obj_type, func, obj, ...) do { } while (false) +#define SYS_PORT_TRACING_OBJ_FUNC_EXIT(obj_type, func, obj, ...) do { } while (false) + +#else + +/* Helper macros used by the extended tracing system + */ +#define _SYS_PORT_TRACING_TYPE_MASK(type) \ + sys_port_trace_type_mask_ ## type +#define _SYS_PORT_TRACING_FUNC(name, func) \ + sys_port_trace_ ## name ## _ ## func +#define _SYS_PORT_TRACING_FUNC_ENTER(name, func) \ + sys_port_trace_ ## name ## _ ## func ## _enter +#define _SYS_PORT_TRACING_FUNC_BLOCKING(name, func) \ + sys_port_trace_ ## name ## _ ## func ## _blocking +#define _SYS_PORT_TRACING_FUNC_EXIT(name, func) \ + sys_port_trace_ ## name ## _ ## func ## _exit +#define _SYS_PORT_TRACING_OBJ_INIT(name) \ + sys_port_trace_ ## name ## _init +#define _SYS_PORT_TRACING_OBJ_FUNC(name, func) \ + sys_port_trace_ ## name ## _ ## func +#define _SYS_PORT_TRACING_OBJ_FUNC_ENTER(name, func) \ + sys_port_trace_ ## name ## _ ## func ## _enter +#define _SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(name, func) \ + sys_port_trace_ ## name ## _ ## func ## _blocking +#define _SYS_PORT_TRACING_OBJ_FUNC_EXIT(name, func) \ + sys_port_trace_ ## name ## _ ## func ## _exit + + +/* Object trace macros part of the system for checking if certain + * objects should be traced or not depending on the tracing configuration. + */ +#if defined(CONFIG_TRACING_THREAD) + #define sys_port_trace_type_mask_k_thread(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_thread(trace_call) +#endif + +#if defined(CONFIG_TRACING_WORK) + #define sys_port_trace_type_mask_k_work(trace_call) trace_call + #define sys_port_trace_type_mask_k_work_queue(trace_call) trace_call + #define sys_port_trace_type_mask_k_work_delayable(trace_call) trace_call + #define sys_port_trace_type_mask_k_work_poll(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_work(trace_call) + #define sys_port_trace_type_mask_k_work_queue(trace_call) + #define sys_port_trace_type_mask_k_work_delayable(trace_call) + #define sys_port_trace_type_mask_k_work_poll(trace_call) +#endif + +#if defined(CONFIG_TRACING_SEMAPHORE) + #define sys_port_trace_type_mask_k_sem(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_sem(trace_call) +#endif + +#if defined(CONFIG_TRACING_MUTEX) + #define sys_port_trace_type_mask_k_mutex(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_mutex(trace_call) +#endif + +#if defined(CONFIG_TRACING_CONDVAR) + #define sys_port_trace_type_mask_k_condvar(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_condvar(trace_call) +#endif + +#if defined(CONFIG_TRACING_QUEUE) + #define sys_port_trace_type_mask_k_queue(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_queue(trace_call) +#endif + +#if defined(CONFIG_TRACING_FIFO) + #define sys_port_trace_type_mask_k_fifo(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_fifo(trace_call) +#endif + +#if defined(CONFIG_TRACING_LIFO) + #define sys_port_trace_type_mask_k_lifo(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_lifo(trace_call) +#endif + +#if defined(CONFIG_TRACING_STACK) + #define sys_port_trace_type_mask_k_stack(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_stack(trace_call) +#endif + +#if defined(CONFIG_TRACING_MESSAGE_QUEUE) + #define sys_port_trace_type_mask_k_msgq(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_msgq(trace_call) +#endif + +#if defined(CONFIG_TRACING_MAILBOX) + #define sys_port_trace_type_mask_k_mbox(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_mbox(trace_call) +#endif + +#if defined(CONFIG_TRACING_PIPE) + #define sys_port_trace_type_mask_k_pipe(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_pipe(trace_call) +#endif + +#if defined(CONFIG_TRACING_HEAP) + #define sys_port_trace_type_mask_k_heap(trace_call) trace_call + #define sys_port_trace_type_mask_k_heap_sys(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_heap(trace_call) + #define sys_port_trace_type_mask_k_heap_sys(trace_call) +#endif + +#if defined(CONFIG_TRACING_MEMORY_SLAB) + #define sys_port_trace_type_mask_k_mem_slab(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_mem_slab(trace_call) +#endif + +#if defined(CONFIG_TRACING_TIMER) + #define sys_port_trace_type_mask_k_timer(trace_call) trace_call +#else + #define sys_port_trace_type_mask_k_timer(trace_call) +#endif + + + + +/** + * @def SYS_PORT_TRACING_OBJ_MASK + * + * @brief Checks if an object type should be traced or not. + * + * @param type Tracing event type/object + * @param trace_call Tracing call + */ +#define SYS_PORT_TRACING_TYPE_MASK(type, trace_call) \ + _SYS_PORT_TRACING_TYPE_MASK(type)(trace_call) + + + + +/** + * @def SYS_PORT_TRACING_FUNC + * + * @brief Tracing macro for function calls which are not directly + * associated with a specific type of object. + * + * @param type Type of tracing event or object type + * @param func Name of the function responsible for the call. This does not need to exactly + * match the name of the function but should rather match what the user called in case of + * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. + * @param ... Additional parameters relevant to the tracing call + */ +#define SYS_PORT_TRACING_FUNC(type, func, ...) \ + do { \ + _SYS_PORT_TRACING_FUNC(type, func)(__VA_ARGS__); \ + } while (false) + +/** + * @def SYS_PORT_TRACING_FUNC_ENTER + * + * @brief Tracing macro for the entry into a function that might or might not return + * a value. + * + * @param type Type of tracing event or object type + * @param func Name of the function responsible for the call. This does not need to exactly + * match the name of the function but should rather match what the user called in case of + * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. + * @param ... Additional parameters relevant to the tracing call + */ +#define SYS_PORT_TRACING_FUNC_ENTER(type, func, ...) \ + do { \ + _SYS_PORT_TRACING_FUNC_ENTER(type, func)(__VA_ARGS__); \ + } while (false) + +/** + * @def SYS_PORT_TRACING_FUNC_BLOCKING + * + * @brief Tracing macro for when a function blocks during its execution. + * + * @param type Type of tracing event or object type + * @param func Name of the function responsible for the call. This does not need to exactly + * match the name of the function but should rather match what the user called in case of + * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. + * @param ... Additional parameters relevant to the tracing call + */ +#define SYS_PORT_TRACING_FUNC_BLOCKING(type, func, ...) \ + do { \ + _SYS_PORT_TRACING_FUNC_BLOCKING(type, func)(__VA_ARGS__); \ + } while (false) + +/** + * @def SYS_PORT_TRACING_FUNC_EXIT + * + * @brief Tracing macro for when a function ends its execution. Potential return values + * can be given as additional arguments. + * + * @param type Type of tracing event or object type + * @param func Name of the function responsible for the call. This does not need to exactly + * match the name of the function but should rather match what the user called in case of + * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. + * @param ... Additional parameters relevant to the tracing call + */ +#define SYS_PORT_TRACING_FUNC_EXIT(type, func, ...) \ + do { \ + _SYS_PORT_TRACING_FUNC_EXIT(type, func)(__VA_ARGS__); \ + } while (false) + +/** + * @def SYS_PORT_TRACING_OBJ_INIT + * + * @brief Tracing macro for the initialization of an object. + * + * @param obj_type The type of object associated with the call (k_thread, k_sem, k_mutex etc.) + * @param obj Object + */ +#define SYS_PORT_TRACING_OBJ_INIT(obj_type, obj, ...) \ + do { \ + SYS_PORT_TRACING_TYPE_MASK(obj_type, \ + _SYS_PORT_TRACING_OBJ_INIT(obj_type)(obj, ##__VA_ARGS__)); \ + } while (false) + +/** + * @def SYS_PORT_TRACING_OBJ_FUNC + * + * @brief Tracing macro for simple object function calls often without returns or branching. + * + * @param obj_type The type of object associated with the call (k_thread, k_sem, k_mutex etc.) + * @param func Name of the function responsible for the call. This does not need to exactly + * match the name of the function but should rather match what the user called in case of + * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. + * @param obj Object + * @param ... Additional parameters relevant to the tracing call + */ +#define SYS_PORT_TRACING_OBJ_FUNC(obj_type, func, obj, ...) \ + do { \ + SYS_PORT_TRACING_TYPE_MASK(obj_type, \ + _SYS_PORT_TRACING_OBJ_FUNC(obj_type, func)(obj, ##__VA_ARGS__)); \ + } while (false) + +/** + * @def SYS_PORT_TRACING_OBJ_FUNC_ENTER + * + * @brief Tracing macro for the entry into a function that might or might not return + * a value. + * + * @param obj_type The type of object associated with the call (k_thread, k_sem, k_mutex etc.) + * @param func Name of the function responsible for the call. This does not need to exactly + * match the name of the function but should rather match what the user called in case of + * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. + * @param obj Object + * @param ... Additional parameters relevant to the tracing call + */ +#define SYS_PORT_TRACING_OBJ_FUNC_ENTER(obj_type, func, obj, ...) \ + do { \ + SYS_PORT_TRACING_TYPE_MASK(obj_type, \ + _SYS_PORT_TRACING_OBJ_FUNC_ENTER(obj_type, func)(obj, ##__VA_ARGS__)); \ + } while (false) + +/** + * @def SYS_PORT_TRACING_OBJ_FUNC_BLOCKING + * + * @brief Tracing macro for when a function blocks during its execution. + * + * @param obj_type The type of object associated with the call (k_thread, k_sem, k_mutex etc.) + * @param func Name of the function responsible for the call. This does not need to exactly + * match the name of the function but should rather match what the user called in case of + * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. + * @param obj Object + * @param ... Additional parameters relevant to the tracing call + */ +#define SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(obj_type, func, obj, timeout, ...) \ + do { \ + SYS_PORT_TRACING_TYPE_MASK(obj_type, \ + _SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(obj_type, func) \ + (obj, timeout, ##__VA_ARGS__)); \ + } while (false) + +/** + * @def SYS_PORT_TRACING_OBJ_FUNC_EXIT + * + * @brief Tracing macro for when a function ends its execution. Potential return values + * can be given as additional arguments. + * + * @param obj_type The type of object associated with the call (k_thread, k_sem, k_mutex etc.) + * @param func Name of the function responsible for the call. This does not need to exactly + * match the name of the function but should rather match what the user called in case of + * system calls etc. That is, we can often omit the z_vrfy/z_impl part of the name. + * @param obj Object + * @param ... Additional parameters relevant to the tracing call + */ +#define SYS_PORT_TRACING_OBJ_FUNC_EXIT(obj_type, func, obj, ...) \ + do { \ + SYS_PORT_TRACING_TYPE_MASK(obj_type, \ + _SYS_PORT_TRACING_OBJ_FUNC_EXIT(obj_type, func)(obj, ##__VA_ARGS__)); \ + } while (false) +#endif /* CONFIG_TRACING */ +#endif diff --git a/subsys/tracing/Kconfig b/subsys/tracing/Kconfig index e8c80d5c582..35ea2f367b6 100644 --- a/subsys/tracing/Kconfig +++ b/subsys/tracing/Kconfig @@ -189,13 +189,111 @@ config TRACING_CMD_BUFFER_SIZE help Size of tracing command buffer. -config TRACING_ISR +menu "Tracing Configuration" + config SYSCALL_TRACING + bool "Enable tracing Syscalls" + default y + help + Enable tracing Syscalls. + + config TRACING_THREAD + bool "Enable tracing Threads" + default y + help + Enable tracing Threads. + + config TRACING_WORK + bool "Enable tracing Work" + default y + help + Enable tracing Work and Work queue events + + config TRACING_ISR bool "Enable tracing ISRs" default y help Enable tracing ISRs. This requires the backend to be very low-latency. + config TRACING_SEMAPHORE + bool "Enable tracing Semaphores" + default y + help + Enable tracing Semaphores. + + config TRACING_MUTEX + bool "Enable tracing Mutexes" + default y + help + Enable tracing Mutexes. + + config TRACING_CONDVAR + bool "Enable tracing Condition Variables" + default y + help + Enable tracing Condition Variables + + config TRACING_QUEUE + bool "Enable tracing Queues" + default y + help + Enable tracing Queues. + + config TRACING_FIFO + bool "Enable tracing FIFO queues" + default y + help + Enable tracing FIFO queues. + + config TRACING_LIFO + bool "Enable tracing LIFO queues" + default y + help + Enable tracing LIFO queues. + + config TRACING_STACK + bool "Enable tracing Memory Stacks" + default y + help + Enable tracing Memory Stacks. + + config TRACING_MESSAGE_QUEUE + bool "Enable tracing Message Queues" + default y + help + Enable tracing Message Queues. + + config TRACING_MAILBOX + bool "Enable tracing Mailboxes" + default y + help + Enable tracing Mailboxes. + + config TRACING_PIPE + bool "Enable tracing Pipes" + default y + help + Enable tracing Pipes. + + config TRACING_HEAP + bool "Enable tracing Memory Heaps" + default y + help + Enable tracing Memory Heaps. + + config TRACING_MEMORY_SLAB + bool "Enable tracing Memory Slabs" + default y + help + Enable tracing Memory Slabs. + + config TRACING_TIMER + bool "Enable tracing Timers" + default y + help + Enable tracing Timers. +endmenu + endif source "subsys/tracing/sysview/Kconfig"