diff --git a/include/zephyr/logging/log_core.h b/include/zephyr/logging/log_core.h index b18fe00c09e..7321b569f34 100644 --- a/include/zephyr/logging/log_core.h +++ b/include/zephyr/logging/log_core.h @@ -378,6 +378,13 @@ static inline char z_log_minimal_level_to_char(int level) /** @brief Number of slots in one word. */ #define LOG_FILTERS_NUM_OF_SLOTS (32 / LOG_FILTER_SLOT_SIZE) +/** @brief Maximum number of backends supported when runtime filtering is enabled. */ +#define LOG_FILTERS_MAX_BACKENDS \ + (LOG_FILTERS_NUM_OF_SLOTS - (1 + IS_ENABLED(CONFIG_LOG_FRONTEND))) + +/** @brief Slot reserved for the frontend. Last slot is used. */ +#define LOG_FRONTEND_SLOT_ID (LOG_FILTERS_NUM_OF_SLOTS - 1) + /** @brief Slot mask. */ #define LOG_FILTER_SLOT_MASK (BIT(LOG_FILTER_SLOT_SIZE) - 1U) diff --git a/include/zephyr/logging/log_ctrl.h b/include/zephyr/logging/log_ctrl.h index 6b8a5ec0414..9e5e3e3c077 100644 --- a/include/zephyr/logging/log_ctrl.h +++ b/include/zephyr/logging/log_ctrl.h @@ -156,7 +156,7 @@ uint32_t log_filter_get(struct log_backend const *const backend, /** * @brief Set filter on given source for the provided backend. * - * @param backend Backend instance. NULL for all backends. + * @param backend Backend instance. NULL for all backends (and frontend). * @param domain_id ID of the domain. * @param source_id Source (module or instance) ID. * @param level Severity level. @@ -168,6 +168,26 @@ __syscall uint32_t log_filter_set(struct log_backend const *const backend, uint32_t domain_id, int16_t source_id, uint32_t level); +/** + * @brief Get source filter for the frontend. + * + * @param source_id Source (module or instance) ID. + * @param runtime True for runtime filter or false for compiled in. + * + * @return Severity level. + */ +uint32_t log_frontend_filter_get(int16_t source_id, bool runtime); + +/** + * @brief Set filter on given source for the frontend. + * + * @param source_id Source (module or instance) ID. + * @param level Severity level. + * + * @return Actual level set which may be limited by compiled level. + */ +__syscall uint32_t log_frontend_filter_set(int16_t source_id, uint32_t level); + /** * * @brief Enable backend with initial maximum filtering level. diff --git a/subsys/logging/log_core.c b/subsys/logging/log_core.c index 3539556ac25..3a2e397a603 100644 --- a/subsys/logging/log_core.c +++ b/subsys/logging/log_core.c @@ -241,6 +241,11 @@ void log_core_init(void) if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { log_frontend_init(); + + for (uint16_t s = 0; s < log_src_cnt_get(0); s++) { + log_frontend_filter_set(s, CONFIG_LOG_MAX_LEVEL); + } + if (IS_ENABLED(CONFIG_LOG_FRONTEND_ONLY)) { return; } @@ -292,7 +297,7 @@ static uint32_t z_log_init(bool blocking, bool can_sleep) return 0; } - __ASSERT_NO_MSG(log_backend_count_get() < LOG_FILTERS_NUM_OF_SLOTS); + __ASSERT_NO_MSG(log_backend_count_get() < LOG_FILTERS_MAX_BACKENDS); if (atomic_inc(&initialized) != 0) { return 0; diff --git a/subsys/logging/log_mgmt.c b/subsys/logging/log_mgmt.c index 6336e4a8385..190c452a2d6 100644 --- a/subsys/logging/log_mgmt.c +++ b/subsys/logging/log_mgmt.c @@ -412,9 +412,23 @@ static void set_runtime_filter(uint8_t backend_id, uint8_t domain_id, } } -uint32_t z_impl_log_filter_set(struct log_backend const *const backend, - uint32_t domain_id, int16_t source_id, - uint32_t level) +static uint32_t filter_get(uint8_t id, uint32_t domain_id, int16_t source_id, bool runtime) +{ + __ASSERT_NO_MSG(source_id < log_src_cnt_get(domain_id)); + + if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && runtime) { + if (source_id < 0) { + return LOG_LEVEL_DBG; + } + + return LOG_FILTER_SLOT_GET(get_dynamic_filter(domain_id, source_id), id); + } + + return log_compiled_level_get(domain_id, source_id); +} + + +uint32_t filter_set(int id, uint32_t domain_id, int16_t source_id, uint32_t level) { if (!IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) { return log_compiled_level_get(domain_id, source_id); @@ -423,12 +437,20 @@ uint32_t z_impl_log_filter_set(struct log_backend const *const backend, __ASSERT_NO_MSG(source_id < log_src_cnt_get(domain_id)); - if (backend == NULL) { + if (id < 0) { uint32_t max = 0U; + size_t backend_cnt; - STRUCT_SECTION_FOREACH(log_backend, iter_backend) { - uint32_t current = log_filter_set(iter_backend, - domain_id, source_id, level); + if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { + max = filter_set(LOG_FRONTEND_SLOT_ID, domain_id, source_id, level); + if (IS_ENABLED(CONFIG_LOG_FRONTEND_ONLY)) { + return max; + } + } + + STRUCT_SECTION_COUNT(log_backend, &backend_cnt); + for (size_t i = 0; i < backend_cnt; i++) { + uint32_t current = filter_set(i, domain_id, source_id, level); max = MAX(current, max); } @@ -436,13 +458,27 @@ uint32_t z_impl_log_filter_set(struct log_backend const *const backend, return max; } - level = MIN(level, MAX(log_filter_get(backend, domain_id, source_id, false), + level = MIN(level, MAX(filter_get(id, domain_id, source_id, false), CONFIG_LOG_OVERRIDE_LEVEL)); - set_runtime_filter(log_backend_id_get(backend), domain_id, source_id, level); + set_runtime_filter(id, domain_id, source_id, level); return level; } +uint32_t z_impl_log_filter_set(struct log_backend const *const backend, + uint32_t domain_id, int16_t source_id, + uint32_t level) +{ + int id = (backend == NULL) ? -1 : log_backend_id_get(backend); + + return filter_set(id, domain_id, source_id, level); +} + +uint32_t z_impl_log_frontend_filter_set(int16_t source_id, uint32_t level) +{ + return filter_set(LOG_FRONTEND_SLOT_ID, Z_LOG_LOCAL_DOMAIN_ID, source_id, level); +} + #ifdef CONFIG_USERSPACE uint32_t z_vrfy_log_filter_set(struct log_backend const *const backend, uint32_t domain_id, @@ -541,18 +577,18 @@ void log_backend_disable(struct log_backend const *const backend) 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 < log_src_cnt_get(domain_id)); + int id = (backend == NULL) ? -1 : log_backend_id_get(backend); - if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && runtime) { - if (source_id < 0) { - return LOG_LEVEL_DBG; - } + return filter_get(id, domain_id, source_id, runtime); +} - return LOG_FILTER_SLOT_GET(get_dynamic_filter(domain_id, source_id), - log_backend_id_get(backend)); +uint32_t log_frontend_filter_get(int16_t source_id, bool runtime) +{ + if (!IS_ENABLED(CONFIG_LOG_FRONTEND)) { + return LOG_LEVEL_NONE; } - return log_compiled_level_get(domain_id, source_id); + return filter_get(LOG_FRONTEND_SLOT_ID, Z_LOG_LOCAL_DOMAIN_ID, source_id, runtime); } void z_log_links_initiate(void) diff --git a/subsys/logging/log_msg.c b/subsys/logging/log_msg.c index da9dffdc62e..f69c96dd7b0 100644 --- a/subsys/logging/log_msg.c +++ b/subsys/logging/log_msg.c @@ -51,6 +51,27 @@ void z_log_msg_finalize(struct log_msg *msg, const void *source, z_log_msg_commit(msg); } +static bool frontend_runtime_filtering(const void *source, uint32_t level) +{ + if (!IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING)) { + return true; + } + + /* If only frontend is used and log got here it means that it was accepted. */ + if (IS_ENABLED(CONFIG_LOG_FRONTEND_ONLY)) { + return true; + } + + if (level == LOG_LEVEL_NONE) { + return true; + } + + struct log_source_dynamic_data *dynamic = (struct log_source_dynamic_data *)source; + uint32_t f_level = LOG_FILTER_SLOT_GET(&dynamic->filters, LOG_FRONTEND_SLOT_ID); + + return level <= f_level; +} + /** @brief Create a log message using simplified method. * * Simple log message has 0-2 32 bit word arguments so creating cbprintf package @@ -102,7 +123,7 @@ static void z_log_msg_simple_create(const void *source, uint32_t level, uint32_t void z_impl_z_log_msg_simple_create_0(const void *source, uint32_t level, const char *fmt) { - if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { + if (IS_ENABLED(CONFIG_LOG_FRONTEND) && frontend_runtime_filtering(source, level)) { if (IS_ENABLED(CONFIG_LOG_FRONTEND_OPT_API)) { log_frontend_simple_0(source, level, fmt); } else { @@ -141,7 +162,7 @@ void z_impl_z_log_msg_simple_create_0(const void *source, uint32_t level, const void z_impl_z_log_msg_simple_create_1(const void *source, uint32_t level, const char *fmt, uint32_t arg) { - if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { + if (IS_ENABLED(CONFIG_LOG_FRONTEND) && frontend_runtime_filtering(source, level)) { if (IS_ENABLED(CONFIG_LOG_FRONTEND_OPT_API)) { log_frontend_simple_1(source, level, fmt, arg); } else { @@ -181,7 +202,7 @@ void z_impl_z_log_msg_simple_create_1(const void *source, uint32_t level, void z_impl_z_log_msg_simple_create_2(const void *source, uint32_t level, const char *fmt, uint32_t arg0, uint32_t arg1) { - if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { + if (IS_ENABLED(CONFIG_LOG_FRONTEND) && frontend_runtime_filtering(source, level)) { if (IS_ENABLED(CONFIG_LOG_FRONTEND_OPT_API)) { log_frontend_simple_2(source, level, fmt, arg0, arg1); } else { @@ -223,7 +244,7 @@ void z_impl_z_log_msg_static_create(const void *source, const struct log_msg_desc desc, uint8_t *package, const void *data) { - if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { + if (IS_ENABLED(CONFIG_LOG_FRONTEND) && frontend_runtime_filtering(source, desc.level)) { log_frontend_msg(source, desc, package, data); } @@ -324,7 +345,7 @@ void z_log_msg_runtime_vcreate(uint8_t domain_id, const void *source, __ASSERT_NO_MSG(plen >= 0); } - if (IS_ENABLED(CONFIG_LOG_FRONTEND)) { + if (IS_ENABLED(CONFIG_LOG_FRONTEND) && frontend_runtime_filtering(source, desc.level)) { log_frontend_msg(source, desc, pkg, data); }