From efd8e246ccd4554a772d2eda5415d6b2ffda14b4 Mon Sep 17 00:00:00 2001 From: Yonattan Louise Date: Fri, 31 Jul 2015 15:58:09 -0500 Subject: [PATCH] Add profiler method. Add a standardized mechanism to add profiling points to the Kernel with a single interface for the user to collect the profiling data. Change-Id: I4fa34ac1b42f73a73ba1fd805e755ee2fd00dff7 Signed-off-by: Yonattan Louise --- arch/arc/defconfig | 2 + arch/arm/defconfig | 2 + arch/x86/defconfig | 2 + include/misc/profiler.h | 152 +++++++++++++++++++++++++++++++++++ kernel/Kconfig | 19 +++++ kernel/nanokernel/Makefile | 1 + kernel/nanokernel/profiler.c | 71 ++++++++++++++++ 7 files changed, 249 insertions(+) create mode 100644 include/misc/profiler.h create mode 100644 kernel/nanokernel/profiler.c diff --git a/arch/arc/defconfig b/arch/arc/defconfig index 5ee946950c5..fb33f26163d 100644 --- a/arch/arc/defconfig +++ b/arch/arc/defconfig @@ -14,6 +14,8 @@ CONFIG_SYS_CLOCK_EXISTS=y CONFIG_XIP=y # CONFIG_ENHANCED_SECURITY is not set # CONFIG_EVENT_LOGGER is not set +# CONFIG_KERNEL_PROFILER is not set +# CONFIG_PROFILER_BUFFER_SIZE is not set # # Nanokernel Options diff --git a/arch/arm/defconfig b/arch/arm/defconfig index 4de6240a08c..47d6bafd903 100644 --- a/arch/arm/defconfig +++ b/arch/arm/defconfig @@ -15,6 +15,8 @@ CONFIG_SYS_CLOCK_EXISTS=y CONFIG_XIP=y # CONFIG_ENHANCED_SECURITY is not set # CONFIG_EVENT_LOGGER is not set +# CONFIG_KERNEL_PROFILER is not set +# CONFIG_PROFILER_BUFFER_SIZE is not set # # Nanokernel Options diff --git a/arch/x86/defconfig b/arch/x86/defconfig index 9263b3131e0..e36f338aa86 100644 --- a/arch/x86/defconfig +++ b/arch/x86/defconfig @@ -17,6 +17,8 @@ CONFIG_SYS_CLOCK_EXISTS=y # CONFIG_XIP is not set CONFIG_ENHANCED_SECURITY=y # CONFIG_EVENT_LOGGER is not set +# CONFIG_KERNEL_PROFILER is not set +# CONFIG_PROFILER_BUFFER_SIZE is not set # # Security Options diff --git a/include/misc/profiler.h b/include/misc/profiler.h new file mode 100644 index 00000000000..bf70db1c9ea --- /dev/null +++ b/include/misc/profiler.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3) Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file + * @brief Profiler support. + */ + + +#include + +#ifndef __PROFILE_H__ +#define __PROFILE_H__ + +#ifdef CONFIG_KERNEL_PROFILER + +/** + * Global variable of the ring buffer that allows user to implement + * their own reading routine. + */ +struct event_logger sys_profiler_logger; + + +/** + * @brief Sends a profile event message to the profiler. + * + * @details Sends a profile message to the profiler logger + * and informs that there are messages available. + * + * @param event_id The identification of the profiler event. + * @param data Pointer to the data of the message. + * @param data_size Size of the data in 32-bit words. + * + * @return No return value. + */ +#define sys_profiler_put(event_id, data, data_size) \ + sys_event_logger_put(&sys_profiler_logger, event_id, data, data_size) + + +/** + * @brief Sends a profile event message to the profiler with the current + * timestamp. + * + * @details Sends a profile message to the profiler logger and informs that + * there messages available. The timestamp when the event occurred is stored + * as part of the event message. + * + * @param event_id The identification of the profiler event. + * + * @return No return value. + */ +void sys_profiler_put_timed(uint16_t event_id); + + +/** + * @brief Retrieves a profiler event message. + * + * @details Retrieves a profiler event message copying it to the provided + * buffer. If the buffer is smaller than the message size the function returns + * an error. The function retrieves messages in FIFO order. + * + * @param buffer Pointer to the buffer where the message will be copied. + * @param buffer_size Size of the buffer in 32-bit words. + * + * @return -EMSGSIZE if the buffer size is smaller than the message size, + * the amount of 32-bit words copied or zero if there are no profile event + * messages available. + */ +#define sys_profiler_get(buffer, buffer_size) \ + sys_event_logger_get(&sys_profiler_logger, buffer, buffer_size) + + +/** + * @brief Retrieves a profiler event message, wait if there is no message + * available. + * + * @details Retrieves a profiler event message copying it to the provided + * buffer. If the buffer is smaller than the message size the function returns + * an error. The function retrieves messages in FIFO order. If there is no + * profiler event message available the caller pends until a new message is + * logged. + * + * @param buffer Pointer to the buffer where the message will be copied. + * @param buffer_size Size of the buffer in 32-bit words. + * + * @return -EMSGSIZE if the buffer size is smaller than the message size, or + * the amount of 32-bit words copied. + */ +#define sys_profiler_get_wait(buffer, buffer_size) \ + sys_event_logger_get_wait(&sys_profiler_logger, buffer, buffer_size) + + +#ifdef CONFIG_NANO_TIMEOUTS + +/** + * @brief Retrieves a profiler event message, wait with a timeout if there is + * no profiling event messages available. + * + * @details Retrieves a profiler event message copying it to the provided + * buffer. If the buffer is smaller than the message size the function returns + * an error. The function retrieves messages in FIFO order. If there are no + * profiler event messages available the caller pends until a new message is + * logged or the timeout expires. + * + * @param buffer Pointer to the buffer where the message will be copied. + * @param buffer_size Size of the buffer in 32-bit words. + * @param timeout Timeout in ticks. + * + * @return -EMSGSIZE if the buffer size is smaller than the message size, the + * amount of 32-bit words copied or zero if the timeout expires and the was no + * message available. + */ +#define sys_profiler_get_wait_timeout(buffer, buffer_size, timeout) \ + sys_event_logger_get_wait_timeout(&sys_profiler_logger, buffer, \ + buffer_size, timeout) +#endif /* CONFIG_NANO_TIMEOUTS */ + +#else /* !CONFIG_KERNEL_PROFILER */ + +static inline void sys_profiler_put(uint16_t event_id, uint32_t *event_data, + uint8_t data_size) {}; +static inline void sys_profiler_put_timed(uint16_t event_id) {}; +#endif /* CONFIG_KERNEL_PROFILER */ + +#endif /* __PROFILE_H__ */ diff --git a/kernel/Kconfig b/kernel/Kconfig index 376ed634705..4d1c93becca 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -111,6 +111,25 @@ config EVENT_LOGGER Enable event logging feature. Allow the usage of a ring buffer to transmit event messages with a single interface to collect them. +config KERNEL_PROFILER + bool + prompt "Enable profiler features" + default n + select EVENT_LOGGER + help + This feature enables the usage of the profiling logger. Provides the + logging of sleep events (either entering or leaving low power conditions), + context switch events, interrupt events, boot events and a method to + collect these profile messages. + +config PROFILER_BUFFER_SIZE + int + prompt "Profiler buffer size" + default 128 + depends on KERNEL_PROFILER + help + Buffer size in 32-bit words. + menu "Security Options" depends on ENHANCED_SECURITY diff --git a/kernel/nanokernel/Makefile b/kernel/nanokernel/Makefile index 2e1576c981d..381fef716b4 100644 --- a/kernel/nanokernel/Makefile +++ b/kernel/nanokernel/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_INT_LATENCY_BENCHMARK) += int_latency_bench.o obj-$(CONFIG_ADVANCED_POWER_MANAGEMENT) += idle.o obj-$(CONFIG_NANO_TIMERS) += nano_timer.o obj-$(CONFIG_EVENT_LOGGER) += event_logger.o +obj-$(CONFIG_KERNEL_PROFILER) += profiler.o diff --git a/kernel/nanokernel/profiler.c b/kernel/nanokernel/profiler.c new file mode 100644 index 00000000000..40cba70d557 --- /dev/null +++ b/kernel/nanokernel/profiler.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1) Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2) Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3) Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * @file + * @brief Profiler support. + */ + + +#include +#include +#include + +uint32_t _sys_profiler_buffer[CONFIG_PROFILER_BUFFER_SIZE]; + +/** + * @brief Initialize the profiler system. + * + * @details Initialize the ring buffer and the sync semaphore. + * + * @return No return value. + */ +static int _sys_profiler_init(struct device *arg) +{ + ARG_UNUSED(arg); + + sys_event_logger_init(&sys_profiler_logger, _sys_profiler_buffer, + CONFIG_PROFILER_BUFFER_SIZE); + + return 0; +} +DECLARE_DEVICE_INIT_CONFIG(profiler_0, "", _sys_profiler_init, NULL); +nano_early_init(profiler_0, NULL); + + +void sys_profiler_put_timed(uint16_t event_id) +{ + uint32_t data[1]; + + data[0] = nano_tick_get_32(); + + sys_event_logger_put(&sys_profiler_logger, event_id, data, + ARRAY_SIZE(data)); +}