logging: Add option to block in thread context
Added CONIFG_LOG_BLOCK_IN_THREAD option to block until buffer for log message is available. When log message is called in the thread and there is no buffer available in the pool, thread will block with configurable timeout (CONFIG_LOG_BLOCK_IN_THREAD_TIMEOUT_MS). If buffer cannot be allocated by that time, message will be dropped. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
95c2968d32
commit
cc5094b3bf
3 changed files with 56 additions and 1 deletions
|
@ -97,6 +97,11 @@ oldest one are discarded.
|
||||||
:option:`CONFIG_LOG_MODE_NO_OVERFLOW`: When logger cannot allocate new message
|
:option:`CONFIG_LOG_MODE_NO_OVERFLOW`: When logger cannot allocate new message
|
||||||
it is discarded.
|
it is discarded.
|
||||||
|
|
||||||
|
:option:`CONFIG_LOG_BLOCK_IN_THREAD`: If enabled and new log message cannot
|
||||||
|
be allocated thread context will block for up to
|
||||||
|
:option:`CONFIG_LOG_BLOCK_IN_THREAD_TIMEOUT_MS` or until log message is
|
||||||
|
allocated.
|
||||||
|
|
||||||
:option:`CONFIG_LOG_DEFAULT_LEVEL`: Default level, sets the logging level
|
:option:`CONFIG_LOG_DEFAULT_LEVEL`: Default level, sets the logging level
|
||||||
used by modules that are not setting their own logging level.
|
used by modules that are not setting their own logging level.
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,26 @@ config LOG_MODE_NO_OVERFLOW
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
config LOG_BLOCK_IN_THREAD
|
||||||
|
bool "On log full block in thread context"
|
||||||
|
help
|
||||||
|
When enabled logger will block (if in the thread context) when
|
||||||
|
internal logger buffer is full and new message cannot be allocated.
|
||||||
|
|
||||||
|
if LOG_BLOCK_IN_THREAD
|
||||||
|
|
||||||
|
config LOG_BLOCK_IN_THREAD_TIMEOUT_MS
|
||||||
|
int "Maximum time (in milliseconds) thread can be blocked"
|
||||||
|
default 1000
|
||||||
|
range -1 10000
|
||||||
|
help
|
||||||
|
If new buffer for a log message cannot be allocated in that time, log
|
||||||
|
message is dropped. Forever blocking (-1) is possible however may lead
|
||||||
|
to the logger deadlock if logging is enabled in threads used for
|
||||||
|
logging (e.g. logger or shell thread).
|
||||||
|
|
||||||
|
endif # LOG_BLOCK_IN_THREAD
|
||||||
|
|
||||||
config LOG_PROCESS_TRIGGER_THRESHOLD
|
config LOG_PROCESS_TRIGGER_THRESHOLD
|
||||||
int "Amount of buffered logs which triggers processing thread."
|
int "Amount of buffered logs which triggers processing thread."
|
||||||
default 10
|
default 10
|
||||||
|
|
|
@ -31,6 +31,12 @@ BUILD_ASSERT_MSG((sizeof(union log_msg_head_data) ==
|
||||||
#define CONFIG_LOG_BUFFER_SIZE 0
|
#define CONFIG_LOG_BUFFER_SIZE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Define needed when CONFIG_LOG_BLOCK_IN_THREAD is disabled to satisfy
|
||||||
|
* compiler. */
|
||||||
|
#ifndef CONFIG_LOG_BLOCK_IN_THREAD_TIMEOUT_MS
|
||||||
|
#define CONFIG_LOG_BLOCK_IN_THREAD_TIMEOUT_MS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MSG_SIZE sizeof(union log_msg_chunk)
|
#define MSG_SIZE sizeof(union log_msg_chunk)
|
||||||
#define NUM_OF_MSGS (CONFIG_LOG_BUFFER_SIZE / MSG_SIZE)
|
#define NUM_OF_MSGS (CONFIG_LOG_BUFFER_SIZE / MSG_SIZE)
|
||||||
|
|
||||||
|
@ -43,10 +49,34 @@ void log_msg_pool_init(void)
|
||||||
k_mem_slab_init(&log_msg_pool, log_msg_pool_buf, MSG_SIZE, NUM_OF_MSGS);
|
k_mem_slab_init(&log_msg_pool, log_msg_pool_buf, MSG_SIZE, NUM_OF_MSGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if interrupts were locked in the context of this call. */
|
||||||
|
static bool is_irq_locked(void)
|
||||||
|
{
|
||||||
|
unsigned int key = z_arch_irq_lock();
|
||||||
|
bool ret = z_arch_irq_unlocked(key);
|
||||||
|
|
||||||
|
z_arch_irq_unlock(key);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if context can be blocked and pend on available memory slab. Context
|
||||||
|
* can be blocked if in a thread and interrupts are not locked.
|
||||||
|
*/
|
||||||
|
static bool block_on_alloc(void)
|
||||||
|
{
|
||||||
|
if (!IS_ENABLED(CONFIG_LOG_BLOCK_IN_THREAD)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (!k_is_in_isr() && !is_irq_locked());
|
||||||
|
}
|
||||||
|
|
||||||
union log_msg_chunk *log_msg_chunk_alloc(void)
|
union log_msg_chunk *log_msg_chunk_alloc(void)
|
||||||
{
|
{
|
||||||
union log_msg_chunk *msg = NULL;
|
union log_msg_chunk *msg = NULL;
|
||||||
int err = k_mem_slab_alloc(&log_msg_pool, (void **)&msg, K_NO_WAIT);
|
int err = k_mem_slab_alloc(&log_msg_pool, (void **)&msg,
|
||||||
|
block_on_alloc() ?
|
||||||
|
CONFIG_LOG_BLOCK_IN_THREAD_TIMEOUT_MS : K_NO_WAIT);
|
||||||
|
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
msg = log_msg_no_space_handle();
|
msg = log_msg_no_space_handle();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue