ESPHome 2026.4.0-dev
Loading...
Searching...
No Matches
task_log_buffer_zephyr.cpp
Go to the documentation of this file.
1#ifdef USE_ZEPHYR
2
4
5namespace esphome::logger {
6
7__thread bool non_main_task_recursion_guard_; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
8
9#ifdef USE_ESPHOME_TASK_LOG_BUFFER
10
11static inline uint32_t total_size_in_32bit_words(uint16_t text_length) {
12 // Calculate total size in 32-bit words needed (header + text length + null terminator + 3(4 bytes alignment)
13 return (sizeof(TaskLogBuffer::LogMessage) + text_length + 1 + 3) / sizeof(uint32_t);
14}
15
16static inline uint32_t get_wlen(const mpsc_pbuf_generic *item) {
17 return total_size_in_32bit_words(reinterpret_cast<const TaskLogBuffer::LogMessage *>(item)->text_length);
18}
19
21 // Storage is a member array (embedded in Logger), no heap allocation needed
22 this->mpsc_config_.buf = this->buf_storage_;
23 this->mpsc_config_.size = BUF_WORD_COUNT;
24 this->mpsc_config_.flags = MPSC_PBUF_MODE_OVERWRITE;
25 this->mpsc_config_.get_wlen = get_wlen;
26
27 mpsc_pbuf_init(&this->log_buffer_, &this->mpsc_config_);
28}
29
30bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name,
31 const char *format, va_list args) {
32 // First, calculate the exact length needed using a null buffer (no actual writing)
33 va_list args_copy;
34 va_copy(args_copy, args);
35 int ret = vsnprintf(nullptr, 0, format, args_copy);
36 va_end(args_copy);
37
38 if (ret <= 0) {
39 return false; // Formatting error or empty message
40 }
41
42 // Calculate actual text length (capped to maximum size)
43 static constexpr size_t MAX_TEXT_SIZE = 255;
44 size_t text_length = (static_cast<size_t>(ret) > MAX_TEXT_SIZE) ? MAX_TEXT_SIZE : ret;
45 size_t total_size = total_size_in_32bit_words(text_length);
46 auto *msg = reinterpret_cast<LogMessage *>(mpsc_pbuf_alloc(&this->log_buffer_, total_size, K_NO_WAIT));
47 if (msg == nullptr) {
48 return false;
49 }
50 msg->level = level;
51 msg->tag = tag;
52 msg->line = line;
53 strncpy(msg->thread_name, thread_name, sizeof(msg->thread_name) - 1);
54 msg->thread_name[sizeof(msg->thread_name) - 1] = '\0'; // Ensure null termination
55
56 // Format the message text directly into the acquired memory
57 // We add 1 to text_length to ensure space for null terminator during formatting
58 char *text_area = msg->text_data();
59 ret = vsnprintf(text_area, text_length + 1, format, args);
60
61 // Handle unexpected formatting error (ret < 0 is encoding error; ret == 0 is valid empty output)
62 if (ret < 0) {
63 // this should not happen, vsnprintf was called already once
64 // fill with '\n' to not call mpsc_pbuf_free from producer
65 // it will be trimmed anyway
66 for (size_t i = 0; i < text_length; ++i) {
67 text_area[i] = '\n';
68 }
69 text_area[text_length] = 0;
70 // do not return false to free the buffer from main thread
71 }
72
73 msg->text_length = text_length;
74
75 mpsc_pbuf_commit(&this->log_buffer_, reinterpret_cast<mpsc_pbuf_generic *>(msg));
76 return true;
77}
78
79bool TaskLogBuffer::borrow_message_main_loop(LogMessage *&message, uint16_t &text_length) {
80 if (this->current_token_) {
81 return false;
82 }
83
84 this->current_token_ = mpsc_pbuf_claim(&this->log_buffer_);
85
86 if (this->current_token_ == nullptr) {
87 return false;
88 }
89
90 // we claimed buffer already, const_cast is safe here
91 message = const_cast<LogMessage *>(reinterpret_cast<const LogMessage *>(this->current_token_));
92
93 text_length = message->text_length;
94 // Remove trailing newlines
95 while (text_length > 0 && message->text_data()[text_length - 1] == '\n') {
96 text_length--;
97 }
98
99 return true;
100}
101
103 if (this->current_token_ == nullptr) {
104 return;
105 }
106 mpsc_pbuf_free(&this->log_buffer_, this->current_token_);
107 this->current_token_ = nullptr;
108}
109#endif // USE_ESPHOME_TASK_LOG_BUFFER
110
111} // namespace esphome::logger
112
113#endif // USE_ZEPHYR
static constexpr size_t BUF_WORD_COUNT
bool borrow_message_main_loop(LogMessage *&message, uint16_t &text_length)
bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args)
uint32_t buf_storage_[BUF_WORD_COUNT]
const char * message
Definition component.cpp:35
__thread bool non_main_task_recursion_guard_
const char int line
Definition log.h:74
const char * tag
Definition log.h:74
const char int const __FlashStringHelper * format
Definition log.h:74
const char int const __FlashStringHelper va_list args
Definition log.h:74
va_end(args)
static void uint32_t