mirror of
https://github.com/esphome/esphome.git
synced 2026-07-10 08:55:36 +00:00
fix
This commit is contained in:
@@ -173,20 +173,9 @@ Logger::Logger(uint32_t baud_rate, size_t tx_buffer_size) : baud_rate_(baud_rate
|
||||
}
|
||||
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
||||
void Logger::init_log_buffer(size_t total_buffer_size) {
|
||||
#ifdef USE_HOST
|
||||
// Host uses slot count instead of byte size
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed
|
||||
this->log_buffer_ = new logger::TaskLogBufferHost(total_buffer_size);
|
||||
#elif defined(USE_ESP32)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed
|
||||
this->log_buffer_ = new logger::TaskLogBuffer(total_buffer_size);
|
||||
#elif defined(USE_LIBRETINY)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed
|
||||
this->log_buffer_ = new logger::TaskLogBufferLibreTiny(total_buffer_size);
|
||||
#elif defined(USE_ZEPHYR)
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed
|
||||
this->log_buffer_ = new logger::TaskLogBufferZephyr(total_buffer_size);
|
||||
#endif
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY) || (defined(USE_ZEPHYR) && !defined(USE_LOGGER_USB_CDC))
|
||||
// Start with loop disabled when using task buffer (unless using USB CDC on ESP32)
|
||||
@@ -210,7 +199,7 @@ void Logger::process_messages_() {
|
||||
// Process any buffered messages when available
|
||||
if (this->log_buffer_->has_messages()) {
|
||||
#ifdef USE_HOST
|
||||
logger::TaskLogBufferHost::LogMessage *message;
|
||||
logger::TaskLogBuffer::LogMessage *message;
|
||||
while (this->log_buffer_->get_message_main_loop(&message)) {
|
||||
const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr;
|
||||
LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_};
|
||||
@@ -220,13 +209,7 @@ void Logger::process_messages_() {
|
||||
this->write_log_buffer_to_console_(buf);
|
||||
}
|
||||
#elif defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
|
||||
#ifdef USE_ESP32
|
||||
logger::TaskLogBuffer::LogMessage *message;
|
||||
#elif defined(USE_LIBRETINY)
|
||||
logger::TaskLogBufferLibreTiny::LogMessage *message;
|
||||
#else
|
||||
logger::TaskLogBufferZephyr::LogMessage *message;
|
||||
#endif
|
||||
const char *text;
|
||||
while (this->log_buffer_->borrow_message_main_loop(&message, &text)) {
|
||||
const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr;
|
||||
|
||||
@@ -346,15 +346,7 @@ class Logger : public Component {
|
||||
std::vector<LoggerLevelListener *> level_listeners_; // Log level change listeners
|
||||
#endif
|
||||
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
||||
#ifdef USE_HOST
|
||||
logger::TaskLogBufferHost *log_buffer_{nullptr}; // Allocated once, never freed
|
||||
#elif defined(USE_ESP32)
|
||||
logger::TaskLogBuffer *log_buffer_{nullptr}; // Allocated once, never freed
|
||||
#elif defined(USE_LIBRETINY)
|
||||
logger::TaskLogBufferLibreTiny *log_buffer_{nullptr}; // Allocated once, never freed
|
||||
#elif defined(USE_ZEPHYR)
|
||||
logger::TaskLogBufferZephyr *log_buffer_{nullptr}; // Allocated once, never freed
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Group smaller types together at the end
|
||||
|
||||
@@ -10,16 +10,16 @@
|
||||
|
||||
namespace esphome::logger {
|
||||
|
||||
TaskLogBufferHost::TaskLogBufferHost(size_t slot_count) : slot_count_(slot_count) {
|
||||
TaskLogBuffer::TaskLogBuffer(size_t slot_count) : slot_count_(slot_count) {
|
||||
// Allocate message slots
|
||||
this->slots_ = std::make_unique<LogMessage[]>(slot_count);
|
||||
}
|
||||
|
||||
TaskLogBufferHost::~TaskLogBufferHost() {
|
||||
TaskLogBuffer::~TaskLogBuffer() {
|
||||
// unique_ptr handles cleanup automatically
|
||||
}
|
||||
|
||||
int TaskLogBufferHost::acquire_write_slot_() {
|
||||
int TaskLogBuffer::acquire_write_slot_() {
|
||||
// Try to reserve a slot using compare-and-swap
|
||||
size_t current_reserve = this->reserve_index_.load(std::memory_order_relaxed);
|
||||
|
||||
@@ -43,7 +43,7 @@ int TaskLogBufferHost::acquire_write_slot_() {
|
||||
}
|
||||
}
|
||||
|
||||
void TaskLogBufferHost::commit_write_slot_(int slot_index) {
|
||||
void TaskLogBuffer::commit_write_slot_(int slot_index) {
|
||||
// Mark the slot as ready for reading
|
||||
this->slots_[slot_index].ready.store(true, std::memory_order_release);
|
||||
|
||||
@@ -70,8 +70,8 @@ void TaskLogBufferHost::commit_write_slot_(int slot_index) {
|
||||
}
|
||||
}
|
||||
|
||||
bool TaskLogBufferHost::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name,
|
||||
const char *format, va_list args) {
|
||||
bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name,
|
||||
const char *format, va_list args) {
|
||||
// Acquire a slot
|
||||
int slot_index = this->acquire_write_slot_();
|
||||
if (slot_index < 0) {
|
||||
@@ -115,7 +115,7 @@ bool TaskLogBufferHost::send_message_thread_safe(uint8_t level, const char *tag,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TaskLogBufferHost::get_message_main_loop(LogMessage **message) {
|
||||
bool TaskLogBuffer::get_message_main_loop(LogMessage **message) {
|
||||
if (message == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -138,7 +138,7 @@ bool TaskLogBufferHost::get_message_main_loop(LogMessage **message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void TaskLogBufferHost::release_message_main_loop() {
|
||||
void TaskLogBuffer::release_message_main_loop() {
|
||||
size_t current_read = this->read_index_.load(std::memory_order_relaxed);
|
||||
|
||||
// Clear the ready flag
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace esphome::logger {
|
||||
* - Atomic CAS for slot reservation allows multiple producers without locks
|
||||
* - Single consumer (main loop) processes messages in order
|
||||
*/
|
||||
class TaskLogBufferHost {
|
||||
class TaskLogBuffer {
|
||||
public:
|
||||
// Default number of message slots - host has plenty of memory
|
||||
static constexpr size_t DEFAULT_SLOT_COUNT = 64;
|
||||
@@ -74,8 +74,8 @@ class TaskLogBufferHost {
|
||||
};
|
||||
|
||||
/// Constructor that takes the number of message slots
|
||||
explicit TaskLogBufferHost(size_t slot_count);
|
||||
~TaskLogBufferHost();
|
||||
explicit TaskLogBuffer(size_t slot_count);
|
||||
~TaskLogBuffer();
|
||||
|
||||
// NOT thread-safe - get next message from buffer, only call from main loop
|
||||
// Returns true if a message was retrieved, false if buffer is empty
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace esphome::logger {
|
||||
|
||||
TaskLogBufferLibreTiny::TaskLogBufferLibreTiny(size_t total_buffer_size) {
|
||||
TaskLogBuffer::TaskLogBuffer(size_t total_buffer_size) {
|
||||
this->size_ = total_buffer_size;
|
||||
// Allocate memory for the circular buffer using ESPHome's RAM allocator
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
@@ -17,7 +17,7 @@ TaskLogBufferLibreTiny::TaskLogBufferLibreTiny(size_t total_buffer_size) {
|
||||
this->mutex_ = xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
TaskLogBufferLibreTiny::~TaskLogBufferLibreTiny() {
|
||||
TaskLogBuffer::~TaskLogBuffer() {
|
||||
if (this->mutex_ != nullptr) {
|
||||
vSemaphoreDelete(this->mutex_);
|
||||
this->mutex_ = nullptr;
|
||||
@@ -29,7 +29,7 @@ TaskLogBufferLibreTiny::~TaskLogBufferLibreTiny() {
|
||||
}
|
||||
}
|
||||
|
||||
size_t TaskLogBufferLibreTiny::available_contiguous_space() const {
|
||||
size_t TaskLogBuffer::available_contiguous_space() const {
|
||||
if (this->head_ >= this->tail_) {
|
||||
// head is ahead of or equal to tail
|
||||
// Available space is from head to end, plus from start to tail
|
||||
@@ -47,7 +47,7 @@ size_t TaskLogBufferLibreTiny::available_contiguous_space() const {
|
||||
}
|
||||
}
|
||||
|
||||
bool TaskLogBufferLibreTiny::borrow_message_main_loop(LogMessage **message, const char **text) {
|
||||
bool TaskLogBuffer::borrow_message_main_loop(LogMessage **message, const char **text) {
|
||||
if (message == nullptr || text == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ bool TaskLogBufferLibreTiny::borrow_message_main_loop(LogMessage **message, cons
|
||||
return true;
|
||||
}
|
||||
|
||||
void TaskLogBufferLibreTiny::release_message_main_loop() {
|
||||
void TaskLogBuffer::release_message_main_loop() {
|
||||
// Advance tail past the current message
|
||||
this->tail_ += this->current_message_size_;
|
||||
|
||||
@@ -100,8 +100,8 @@ void TaskLogBufferLibreTiny::release_message_main_loop() {
|
||||
xSemaphoreGive(this->mutex_);
|
||||
}
|
||||
|
||||
bool TaskLogBufferLibreTiny::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line,
|
||||
const char *thread_name, const char *format, va_list args) {
|
||||
bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name,
|
||||
const char *format, va_list args) {
|
||||
// First, calculate the exact length needed using a null buffer (no actual writing)
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace esphome::logger {
|
||||
* - Volatile counter enables fast has_messages() without lock overhead
|
||||
* - If message doesn't fit at end, padding is added and message wraps to start
|
||||
*/
|
||||
class TaskLogBufferLibreTiny {
|
||||
class TaskLogBuffer {
|
||||
public:
|
||||
// Structure for a log message header (text data follows immediately after)
|
||||
struct LogMessage {
|
||||
@@ -60,8 +60,8 @@ class TaskLogBufferLibreTiny {
|
||||
static constexpr uint8_t PADDING_MARKER_LEVEL = 0xFF;
|
||||
|
||||
// Constructor that takes a total buffer size
|
||||
explicit TaskLogBufferLibreTiny(size_t total_buffer_size);
|
||||
~TaskLogBufferLibreTiny();
|
||||
explicit TaskLogBuffer(size_t total_buffer_size);
|
||||
~TaskLogBuffer();
|
||||
|
||||
// NOT thread-safe - borrow a message from the buffer, only call from main loop
|
||||
bool borrow_message_main_loop(LogMessage **message, const char **text);
|
||||
|
||||
@@ -9,12 +9,12 @@ namespace esphome::logger {
|
||||
__thread bool non_main_task_recursion_guard_; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
static inline uint32_t get_wlen(const mpsc_pbuf_generic *item) {
|
||||
auto *msg = reinterpret_cast<const TaskLogBufferZephyr::LogMessage *>(item);
|
||||
auto *msg = reinterpret_cast<const TaskLogBuffer::LogMessage *>(item);
|
||||
// Calculate total size in 32-bit words needed (header + text length + null terminator + 3(4 bytes alignment)
|
||||
return (sizeof(TaskLogBufferZephyr::LogMessage) + msg->text_length + 1 + 3) / sizeof(uint32_t);
|
||||
return (sizeof(TaskLogBuffer::LogMessage) + msg->text_length + 1 + 3) / sizeof(uint32_t);
|
||||
}
|
||||
|
||||
TaskLogBufferZephyr::TaskLogBufferZephyr(size_t total_buffer_size) {
|
||||
TaskLogBuffer::TaskLogBuffer(size_t total_buffer_size) {
|
||||
// alignment to 4 bytes
|
||||
total_buffer_size = (total_buffer_size + 3) / sizeof(uint32_t);
|
||||
this->mpsc_config_.buf = new uint32_t[total_buffer_size];
|
||||
@@ -25,10 +25,10 @@ TaskLogBufferZephyr::TaskLogBufferZephyr(size_t total_buffer_size) {
|
||||
mpsc_pbuf_init(&this->log_buffer_, &this->mpsc_config_);
|
||||
}
|
||||
|
||||
TaskLogBufferZephyr::~TaskLogBufferZephyr() { delete[] this->mpsc_config_.buf; }
|
||||
TaskLogBuffer::~TaskLogBuffer() { delete[] this->mpsc_config_.buf; }
|
||||
|
||||
bool TaskLogBufferZephyr::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line,
|
||||
const char *thread_name, const char *format, va_list args) {
|
||||
bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name,
|
||||
const char *format, va_list args) {
|
||||
// First, calculate the exact length needed using a null buffer (no actual writing)
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
@@ -76,7 +76,7 @@ bool TaskLogBufferZephyr::send_message_thread_safe(uint8_t level, const char *ta
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TaskLogBufferZephyr::borrow_message_main_loop(LogMessage **message, const char **text) {
|
||||
bool TaskLogBuffer::borrow_message_main_loop(LogMessage **message, const char **text) {
|
||||
if (this->current_token_) {
|
||||
return false;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ bool TaskLogBufferZephyr::borrow_message_main_loop(LogMessage **message, const c
|
||||
return true;
|
||||
}
|
||||
|
||||
void TaskLogBufferZephyr::release_message_main_loop() {
|
||||
void TaskLogBuffer::release_message_main_loop() {
|
||||
if (this->current_token_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ static constexpr size_t MAX_POINTER_REPRESENTATION = 2 + sizeof(void *) * 2 + 1;
|
||||
|
||||
extern __thread bool non_main_task_recursion_guard_; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
class TaskLogBufferZephyr {
|
||||
class TaskLogBuffer {
|
||||
public:
|
||||
// Structure for a log message header (text data follows immediately after)
|
||||
struct LogMessage {
|
||||
@@ -36,8 +36,8 @@ class TaskLogBufferZephyr {
|
||||
inline const char *text_data() const { return reinterpret_cast<const char *>(this) + sizeof(LogMessage); }
|
||||
};
|
||||
// Constructor that takes a total buffer size
|
||||
explicit TaskLogBufferZephyr(size_t total_buffer_size);
|
||||
~TaskLogBufferZephyr();
|
||||
explicit TaskLogBuffer(size_t total_buffer_size);
|
||||
~TaskLogBuffer();
|
||||
|
||||
// Check if there are messages ready to be processed using an atomic counter for performance
|
||||
inline bool HOT has_messages() { return mpsc_pbuf_is_pending(&this->log_buffer_); }
|
||||
|
||||
Reference in New Issue
Block a user