If source_id is -1, which is a valid value, it will be converted to unsigned since it's compared with an unsigned which means it will be huge and asserts will trigger. To avoid this, we typecast the unsigned part to signed. Resolves #40115 Signed-off-by: Emil Lindqvist <emil@lindq.gr>
203 lines
5.1 KiB
C
203 lines
5.1 KiB
C
/*
|
|
* Copyright (c) 2021 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include <logging/log_internal.h>
|
|
#include <logging/log_ctrl.h>
|
|
#include <syscall_handler.h>
|
|
|
|
/* Implementation of functions related to controlling logging sources and backends:
|
|
* - getting/setting source details like name, filtering
|
|
* - controlling backends filtering
|
|
*/
|
|
|
|
/** @brief Get compiled level of the log source.
|
|
*
|
|
* @param source_id Source ID.
|
|
* @return Level.
|
|
*/
|
|
static inline uint8_t log_compiled_level_get(uint32_t source_id)
|
|
{
|
|
return __log_const_start[source_id].level;
|
|
}
|
|
|
|
void z_log_runtime_filters_init(void)
|
|
{
|
|
/*
|
|
* Initialize aggregated runtime filter levels (no backends are
|
|
* attached yet, so leave backend slots in each dynamic filter set
|
|
* alone for now).
|
|
*
|
|
* Each log source's aggregated runtime level is set to match its
|
|
* compile-time level. When backends are attached later on in
|
|
* log_init(), they'll be initialized to the same value.
|
|
*/
|
|
for (int i = 0; i < z_log_sources_count(); i++) {
|
|
uint32_t *filters = z_log_dynamic_filters_get(i);
|
|
uint8_t level = log_compiled_level_get(i);
|
|
|
|
LOG_FILTER_SLOT_SET(filters,
|
|
LOG_FILTER_AGGR_SLOT_IDX,
|
|
level);
|
|
}
|
|
}
|
|
|
|
uint32_t log_src_cnt_get(uint32_t domain_id)
|
|
{
|
|
return z_log_sources_count();
|
|
}
|
|
|
|
/** @brief Get name of the log source.
|
|
*
|
|
* @param source_id Source ID.
|
|
* @return Name.
|
|
*/
|
|
static inline const char *log_name_get(uint32_t source_id)
|
|
{
|
|
return __log_const_start[source_id].name;
|
|
}
|
|
|
|
const char *log_source_name_get(uint32_t domain_id, uint32_t src_id)
|
|
{
|
|
return src_id < z_log_sources_count() ? log_name_get(src_id) : NULL;
|
|
}
|
|
|
|
static uint32_t max_filter_get(uint32_t filters)
|
|
{
|
|
uint32_t max_filter = LOG_LEVEL_NONE;
|
|
int first_slot = LOG_FILTER_FIRST_BACKEND_SLOT_IDX;
|
|
int i;
|
|
|
|
for (i = first_slot; i < LOG_FILTERS_NUM_OF_SLOTS; i++) {
|
|
uint32_t tmp_filter = LOG_FILTER_SLOT_GET(&filters, i);
|
|
|
|
if (tmp_filter > max_filter) {
|
|
max_filter = tmp_filter;
|
|
}
|
|
}
|
|
|
|
return max_filter;
|
|
}
|
|
|
|
uint32_t z_impl_log_filter_set(struct log_backend const *const backend,
|
|
uint32_t domain_id, int16_t source_id,
|
|
uint32_t level)
|
|
{
|
|
__ASSERT_NO_MSG(source_id < (int16_t)z_log_sources_count());
|
|
|
|
if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) {
|
|
uint32_t new_aggr_filter;
|
|
|
|
uint32_t *filters = z_log_dynamic_filters_get(source_id);
|
|
|
|
if (backend == NULL) {
|
|
struct log_backend const *iter_backend;
|
|
uint32_t max = 0U;
|
|
uint32_t current;
|
|
|
|
for (int i = 0; i < log_backend_count_get(); i++) {
|
|
iter_backend = log_backend_get(i);
|
|
current = log_filter_set(iter_backend,
|
|
domain_id,
|
|
source_id, level);
|
|
max = MAX(current, max);
|
|
}
|
|
|
|
level = max;
|
|
} else {
|
|
uint32_t max = log_filter_get(backend, domain_id,
|
|
source_id, false);
|
|
|
|
level = MIN(level, max);
|
|
|
|
LOG_FILTER_SLOT_SET(filters,
|
|
log_backend_id_get(backend),
|
|
level);
|
|
|
|
/* Once current backend filter is updated recalculate
|
|
* aggregated maximal level
|
|
*/
|
|
new_aggr_filter = max_filter_get(*filters);
|
|
|
|
LOG_FILTER_SLOT_SET(filters,
|
|
LOG_FILTER_AGGR_SLOT_IDX,
|
|
new_aggr_filter);
|
|
}
|
|
}
|
|
|
|
return level;
|
|
}
|
|
|
|
#ifdef CONFIG_USERSPACE
|
|
uint32_t z_vrfy_log_filter_set(struct log_backend const *const backend,
|
|
uint32_t domain_id,
|
|
int16_t src_id,
|
|
uint32_t level)
|
|
{
|
|
Z_OOPS(Z_SYSCALL_VERIFY_MSG(backend == NULL,
|
|
"Setting per-backend filters from user mode is not supported"));
|
|
Z_OOPS(Z_SYSCALL_VERIFY_MSG(domain_id == CONFIG_LOG_DOMAIN_ID,
|
|
"Invalid log domain_id"));
|
|
Z_OOPS(Z_SYSCALL_VERIFY_MSG(src_id < (int16_t)z_log_sources_count(),
|
|
"Invalid log source id"));
|
|
Z_OOPS(Z_SYSCALL_VERIFY_MSG(
|
|
(level <= LOG_LEVEL_DBG),
|
|
"Invalid log level"));
|
|
|
|
return z_impl_log_filter_set(NULL, domain_id, src_id, level);
|
|
}
|
|
#include <syscalls/log_filter_set_mrsh.c>
|
|
#endif
|
|
|
|
static void backend_filter_set(struct log_backend const *const backend,
|
|
uint32_t level)
|
|
{
|
|
if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) {
|
|
for (int i = 0; i < z_log_sources_count(); i++) {
|
|
log_filter_set(backend, CONFIG_LOG_DOMAIN_ID, i, level);
|
|
}
|
|
}
|
|
}
|
|
|
|
void log_backend_enable(struct log_backend const *const backend,
|
|
void *ctx,
|
|
uint32_t level)
|
|
{
|
|
/* As first slot in filtering mask is reserved, backend ID has offset.*/
|
|
uint32_t id = LOG_FILTER_FIRST_BACKEND_SLOT_IDX;
|
|
|
|
id += backend - log_backend_get(0);
|
|
|
|
log_backend_id_set(backend, id);
|
|
backend_filter_set(backend, level);
|
|
log_backend_activate(backend, ctx);
|
|
|
|
z_log_notify_backend_enabled();
|
|
}
|
|
|
|
void log_backend_disable(struct log_backend const *const backend)
|
|
{
|
|
log_backend_deactivate(backend);
|
|
backend_filter_set(backend, LOG_LEVEL_NONE);
|
|
}
|
|
|
|
uint32_t log_filter_get(struct log_backend const *const backend,
|
|
uint32_t domain_id, int16_t source_id, bool runtime)
|
|
{
|
|
__ASSERT_NO_MSG(source_id < (int16_t)z_log_sources_count());
|
|
|
|
if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && runtime) {
|
|
if (source_id < 0) {
|
|
return LOG_LEVEL_DBG;
|
|
}
|
|
|
|
uint32_t *filters = z_log_dynamic_filters_get(source_id);
|
|
|
|
return LOG_FILTER_SLOT_GET(filters,
|
|
log_backend_id_get(backend));
|
|
}
|
|
|
|
return log_compiled_level_get(source_id);
|
|
}
|