From 81ce6db3137316b07b005ca2f52a6d39e1c2981b Mon Sep 17 00:00:00 2001 From: Krzysztof Chruscinski Date: Mon, 7 Feb 2022 14:36:36 +0100 Subject: [PATCH] logging: Add common api for getting memory usage Logging v2 did not support getting memory usage data. Adding this support by creating common api for getting current and maximum usage. Tracking of maximum usage is optional and can be enabled using CONFIG_LOG_MEM_UTILIZATION. Updated shell command to use common API. Signed-off-by: Krzysztof Chruscinski --- include/logging/log_ctrl.h | 26 +++++++++++++++++++++++ include/logging/log_msg.h | 7 ++++++- subsys/logging/Kconfig.misc | 9 ++++++++ subsys/logging/log_cmds.c | 32 +++++++++++++++------------- subsys/logging/log_core.c | 42 +++++++++++++++++++++++++++++++++++-- subsys/logging/log_msg.c | 5 +++++ 6 files changed, 103 insertions(+), 18 deletions(-) diff --git a/include/logging/log_ctrl.h b/include/logging/log_ctrl.h index 9afa0723232..ef0169741cd 100644 --- a/include/logging/log_ctrl.h +++ b/include/logging/log_ctrl.h @@ -220,6 +220,32 @@ static inline bool log_data_pending(void) */ int log_set_tag(const char *tag); +/** + * @brief Get current memory usage. + * + * @param[out] buf_size Capacity of the buffer used for storing log messages. + * @param[out] usage Number of bytes currently containing pending log messages. + * + * @retval -EINVAL if logging mode does not use the buffer. + * @retval 0 successfully collected usage data. + */ +int log_mem_get_usage(uint32_t *buf_size, uint32_t *usage); + +/** + * @brief Get maximum memory usage. + * + * Requires CONFIG_LOG_MEM_UTILIZATION option. + * + * @param[out] max Maximum number of bytes used for pending log messages. + * + * @retval -EINVAL if logging mode does not use the buffer. + * @retval -ENOTSUP if instrumentation is not enabled. + * not been enabled. + * + * @retval 0 successfully collected usage data. + */ +int log_mem_get_max_usage(uint32_t *max); + #if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_MINIMAL) #define LOG_CORE_INIT() log_core_init() #define LOG_INIT() log_init() diff --git a/include/logging/log_msg.h b/include/logging/log_msg.h index 570a8347ede..eab86cc6a4b 100644 --- a/include/logging/log_msg.h +++ b/include/logging/log_msg.h @@ -482,7 +482,12 @@ uint32_t log_msg_mem_get_used(void); */ uint32_t log_msg_mem_get_max_used(void); - +/** + * @brief Get slab size + * + * @return Size of a slab used in slab pool for log messages. + */ +size_t log_msg_get_slab_size(void); /** * @} */ diff --git a/subsys/logging/Kconfig.misc b/subsys/logging/Kconfig.misc index 804ef88a74a..6c2ccdb4c9c 100644 --- a/subsys/logging/Kconfig.misc +++ b/subsys/logging/Kconfig.misc @@ -53,4 +53,13 @@ config LOG2_FMT_SECTION removing strings from final binary and should be used for dictionary logging. +config LOG_MEM_UTILIZATION + bool "Enable tracking maximum memory utilization" + depends on LOG_MODE_DEFERRED + default y if LOG_CMDS + select MEM_SLAB_TRACE_MAX_UTILIZATION if LOG1 + help + When enabled, maximum usage of memory used for log messages in deferred + mode is tracked. It can be used to trim LOG_BUFFER_SIZE. + endmenu diff --git a/subsys/logging/log_cmds.c b/subsys/logging/log_cmds.c index 9619c09f28f..e47aa84e4a3 100644 --- a/subsys/logging/log_cmds.c +++ b/subsys/logging/log_cmds.c @@ -404,26 +404,28 @@ static int cmd_log_strdup_utilization(const struct shell *shell, return 0; } -static int cmd_log_memory_slabs(const struct shell *sh, size_t argc, char **argv) +static int cmd_log_mem(const struct shell *sh, size_t argc, char **argv) { - uint32_t slabs_free; + uint32_t size; uint32_t used; uint32_t max; + int err; - slabs_free = log_msg_mem_get_free(); - used = log_msg_mem_get_used(); - - shell_print(sh, "Blocks used:\t%d", used); - shell_print(sh, "Blocks free:\t%d", slabs_free); - if (IS_ENABLED(CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION)) { - max = log_msg_mem_get_max_used(); - shell_print(sh, "Blocks max:\t%d", max); - } else { - shell_print( - sh, - "Enable CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION to get max memory utilization"); + err = log_mem_get_usage(&size, &used); + if (err < 0) { + shell_error(sh, "Failed to get usage (mode does not support it?)"); } + shell_print(sh, "Log message buffer utilization report:"); + shell_print(sh, "\tCapacity: %u bytes", size); + shell_print(sh, "\tCurrently in use: %u bytes", used); + err = log_mem_get_max_usage(&max); + if (err < 0) { + shell_print(sh, "Enable CONFIG_LOG_MEM_UTILIZATION to get maximum usage"); + } + + shell_print(sh, "\tMaximum usage: %u bytes", max); + return 0; } @@ -479,7 +481,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE( "Get utilization of string duplicates pool", cmd_log_strdup_utilization, 1, 0), SHELL_COND_CMD(CONFIG_LOG_MODE_DEFERRED, mem, NULL, "Logger memory usage", - cmd_log_memory_slabs), + cmd_log_mem), SHELL_SUBCMD_SET_END); SHELL_CMD_REGISTER(log, &sub_log_stat, "Commands for controlling logger", diff --git a/subsys/logging/log_core.c b/subsys/logging/log_core.c index 391b9bf87d4..4af16c9e4d1 100644 --- a/subsys/logging/log_core.c +++ b/subsys/logging/log_core.c @@ -105,8 +105,10 @@ static const struct mpsc_pbuf_buffer_config mpsc_config = { .size = ARRAY_SIZE(buf32), .notify_drop = notify_drop, .get_wlen = log_msg2_generic_get_wlen, - .flags = IS_ENABLED(CONFIG_LOG_MODE_OVERFLOW) ? - MPSC_PBUF_MODE_OVERWRITE : 0 + .flags = (IS_ENABLED(CONFIG_LOG_MODE_OVERFLOW) ? + MPSC_PBUF_MODE_OVERWRITE : 0) | + (IS_ENABLED(CONFIG_LOG_MEM_UTILIZATION) ? + MPSC_PBUF_MAX_UTILIZATION : 0) }; /* Check that default tag can fit in tag buffer. */ @@ -1259,6 +1261,42 @@ int log_set_tag(const char *str) return 0; } +int log_mem_get_usage(uint32_t *buf_size, uint32_t *usage) +{ + __ASSERT_NO_MSG(buf_size != NULL); + __ASSERT_NO_MSG(usage != NULL); + + if (!IS_ENABLED(CONFIG_LOG_MODE_DEFERRED)) { + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_LOG1)) { + *buf_size = CONFIG_LOG_BUFFER_SIZE; + *usage = log_msg_mem_get_used() * log_msg_get_slab_size(); + return 0; + } + + mpsc_pbuf_get_utilization(&log_buffer, buf_size, usage); + + return 0; +} + +int log_mem_get_max_usage(uint32_t *max) +{ + __ASSERT_NO_MSG(max != NULL); + + if (!IS_ENABLED(CONFIG_LOG_MODE_DEFERRED)) { + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_LOG1)) { + *max = log_msg_mem_get_max_used() * log_msg_get_slab_size(); + return 0; + } + + return mpsc_pbuf_get_max_utilization(&log_buffer, max); +} + static void log_process_thread_timer_expiry_fn(struct k_timer *timer) { k_sem_give(&log_process_thread_sem); diff --git a/subsys/logging/log_msg.c b/subsys/logging/log_msg.c index 522f47abd35..7ebf4f7f692 100644 --- a/subsys/logging/log_msg.c +++ b/subsys/logging/log_msg.c @@ -498,3 +498,8 @@ uint32_t log_msg_mem_get_max_used(void) { return k_mem_slab_max_used_get(&log_msg_pool); } + +size_t log_msg_get_slab_size(void) +{ + return MSG_SIZE; +}