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 <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruscinski 2022-02-07 14:36:36 +01:00 committed by Anas Nashif
parent 9ea5c1e510
commit 81ce6db313
6 changed files with 103 additions and 18 deletions

View file

@ -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()

View file

@ -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);
/**
* @}
*/

View file

@ -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

View file

@ -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",

View file

@ -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);

View file

@ -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;
}