logging: Add a log flush operation

Ensure all pending log messages are processed by the log processing
thread when log_flush is called, blocking the caller until done.

Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
This commit is contained in:
Tom Burdick 2024-11-13 11:41:48 -06:00 committed by Benjamin Cabé
parent 44d5d8aef2
commit 5de7e415a0
4 changed files with 38 additions and 68 deletions

View file

@ -95,6 +95,17 @@ __syscall void log_panic(void);
*/ */
__syscall bool log_process(void); __syscall bool log_process(void);
/**
* @brief Process all pending log messages
*/
#ifdef CONFIG_LOG_MODE_DEFERRED
void log_flush(void);
#else
static inline void log_flush(void)
{
}
#endif
/** /**
* @brief Return number of buffered log messages. * @brief Return number of buffered log messages.
* *

View file

@ -203,60 +203,17 @@ out:
#include <zephyr/logging/log_ctrl.h> #include <zephyr/logging/log_ctrl.h>
static void llext_log_flush(void)
{
#ifdef CONFIG_LOG_MODE_DEFERRED
extern struct k_thread logging_thread;
int cur_prio = k_thread_priority_get(k_current_get());
int log_prio = k_thread_priority_get(&logging_thread);
int target_prio;
bool adjust_cur, adjust_log;
/*
* Our goal is to raise the logger thread priority above current, but if
* current has the highest possble priority, both need to be adjusted,
* particularly if the logger thread has the lowest possible priority
*/
if (log_prio < cur_prio) {
adjust_cur = false;
adjust_log = false;
target_prio = 0;
} else if (cur_prio == K_HIGHEST_THREAD_PRIO) {
adjust_cur = true;
adjust_log = true;
target_prio = cur_prio;
k_thread_priority_set(k_current_get(), cur_prio + 1);
} else {
adjust_cur = false;
adjust_log = true;
target_prio = cur_prio - 1;
}
/* adjust logging thread priority if needed */
if (adjust_log) {
k_thread_priority_set(&logging_thread, target_prio);
}
log_thread_trigger();
k_yield();
if (adjust_log) {
k_thread_priority_set(&logging_thread, log_prio);
}
if (adjust_cur) {
k_thread_priority_set(&logging_thread, cur_prio);
}
#endif
}
int llext_unload(struct llext **ext) int llext_unload(struct llext **ext)
{ {
__ASSERT(*ext, "Expected non-null extension"); __ASSERT(*ext, "Expected non-null extension");
struct llext *tmp = *ext; struct llext *tmp = *ext;
k_mutex_lock(&llext_lock, K_FOREVER); /* Flush pending log messages, as the deferred formatting may be referencing
* strings/args in the extension we are about to unload
*/
log_flush();
llext_log_flush(); k_mutex_lock(&llext_lock, K_FOREVER);
__ASSERT(tmp->use_count, "A valid LLEXT cannot have a zero use-count!"); __ASSERT(tmp->use_count, "A valid LLEXT cannot have a zero use-count!");

View file

@ -992,4 +992,19 @@ static int enable_logger(void)
return 0; return 0;
} }
#ifdef CONFIG_LOG_MODE_DEFERRED
void log_flush(void)
{
if (IS_ENABLED(CONFIG_LOG_PROCESS_THREAD)) {
while (log_data_pending()) {
k_sleep(K_MSEC(10));
}
k_sleep(K_MSEC(10));
} else {
while (LOG_PROCESS()) {
}
}
}
#endif
SYS_INIT(enable_logger, POST_KERNEL, CONFIG_LOG_CORE_INIT_PRIORITY); SYS_INIT(enable_logger, POST_KERNEL, CONFIG_LOG_CORE_INIT_PRIORITY);

View file

@ -934,19 +934,6 @@ static void __ztest_init_unit_test_result_for_suite(struct ztest_suite_node *sui
} }
} }
static void flush_log(void)
{
if (IS_ENABLED(CONFIG_LOG_PROCESS_THREAD)) {
while (log_data_pending()) {
k_sleep(K_MSEC(10));
}
k_sleep(K_MSEC(10));
} else {
while (LOG_PROCESS()) {
}
}
}
/* Show one line summary for a test suite. /* Show one line summary for a test suite.
*/ */
static void __ztest_show_suite_summary_oneline(struct ztest_suite_node *suite) static void __ztest_show_suite_summary_oneline(struct ztest_suite_node *suite)
@ -994,7 +981,7 @@ static void __ztest_show_suite_summary_oneline(struct ztest_suite_node *suite)
TC_RESULT_TO_STR(suite_result), passrate_major, passrate_minor, TC_RESULT_TO_STR(suite_result), passrate_major, passrate_minor,
suite->name, distinct_pass, distinct_fail, distinct_skip, distinct_total, suite->name, distinct_pass, distinct_fail, distinct_skip, distinct_total,
suite_duration_worst_ms / 1000, suite_duration_worst_ms % 1000); suite_duration_worst_ms / 1000, suite_duration_worst_ms % 1000);
flush_log(); log_flush();
} }
static void __ztest_show_suite_summary_verbose(struct ztest_suite_node *suite) static void __ztest_show_suite_summary_verbose(struct ztest_suite_node *suite)
@ -1035,12 +1022,12 @@ static void __ztest_show_suite_summary_verbose(struct ztest_suite_node *suite)
if (flush_frequency % 3 == 0) { if (flush_frequency % 3 == 0) {
/** Reduce the flush frequency a bit to speed up the output */ /** Reduce the flush frequency a bit to speed up the output */
flush_log(); log_flush();
} }
flush_frequency++; flush_frequency++;
} }
TC_SUMMARY_PRINT("\n"); TC_SUMMARY_PRINT("\n");
flush_log(); log_flush();
} }
static void __ztest_show_suite_summary(void) static void __ztest_show_suite_summary(void)
@ -1051,9 +1038,9 @@ static void __ztest_show_suite_summary(void)
/* Flush the log a lot to ensure that no summary content /* Flush the log a lot to ensure that no summary content
* is dropped if it goes through the logging subsystem. * is dropped if it goes through the logging subsystem.
*/ */
flush_log(); log_flush();
TC_SUMMARY_PRINT("\n------ TESTSUITE SUMMARY START ------\n\n"); TC_SUMMARY_PRINT("\n------ TESTSUITE SUMMARY START ------\n\n");
flush_log(); log_flush();
for (struct ztest_suite_node *ptr = _ztest_suite_node_list_start; for (struct ztest_suite_node *ptr = _ztest_suite_node_list_start;
ptr < _ztest_suite_node_list_end; ++ptr) { ptr < _ztest_suite_node_list_end; ++ptr) {
@ -1061,7 +1048,7 @@ static void __ztest_show_suite_summary(void)
__ztest_show_suite_summary_verbose(ptr); __ztest_show_suite_summary_verbose(ptr);
} }
TC_SUMMARY_PRINT("------ TESTSUITE SUMMARY END ------\n\n"); TC_SUMMARY_PRINT("------ TESTSUITE SUMMARY END ------\n\n");
flush_log(); log_flush();
} }
static int __ztest_run_test_suite(struct ztest_suite_node *ptr, const void *state, bool shuffle, static int __ztest_run_test_suite(struct ztest_suite_node *ptr, const void *state, bool shuffle,
@ -1474,7 +1461,7 @@ int main(void)
#ifndef CONFIG_ZTEST_SHELL #ifndef CONFIG_ZTEST_SHELL
test_main(); test_main();
end_report(); end_report();
flush_log(); log_flush();
LOG_PANIC(); LOG_PANIC();
if (IS_ENABLED(CONFIG_ZTEST_RETEST_IF_PASSED)) { if (IS_ENABLED(CONFIG_ZTEST_RETEST_IF_PASSED)) {
static __noinit struct { static __noinit struct {