|
| | TaskLogBuffer (size_t total_buffer_size) |
| |
| | ~TaskLogBuffer () |
| |
| bool | borrow_message_main_loop (LogMessage *&message, uint16_t &text_length) |
| |
| void | release_message_main_loop () |
| |
| bool | send_message_thread_safe (uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args) |
| |
| bool HOT | has_messages () const |
| |
| size_t | size () const |
| |
| | TaskLogBuffer (size_t slot_count) |
| | Constructor that takes the number of message slots.
|
| |
| | ~TaskLogBuffer () |
| |
| bool | borrow_message_main_loop (LogMessage *&message, uint16_t &text_length) |
| |
| void | release_message_main_loop () |
| |
| bool | send_message_thread_safe (uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args) |
| |
| bool HOT | has_messages () const |
| |
| size_t | size () const |
| |
| | TaskLogBuffer (size_t total_buffer_size) |
| |
| | ~TaskLogBuffer () |
| |
| bool | borrow_message_main_loop (LogMessage *&message, uint16_t &text_length) |
| |
| void | release_message_main_loop () |
| |
| bool | send_message_thread_safe (uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args) |
| |
| bool HOT | has_messages () const |
| |
| size_t | size () const |
| |
| | TaskLogBuffer (size_t total_buffer_size) |
| |
| | ~TaskLogBuffer () |
| |
| bool HOT | has_messages () |
| |
| size_t | size () const |
| |
| bool | borrow_message_main_loop (LogMessage *&message, uint16_t &text_length) |
| |
| void | release_message_main_loop () |
| |
| bool | send_message_thread_safe (uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args) |
| |
Task log buffer for ESP32 platform using FreeRTOS ring buffer.
Task log buffer for LibreTiny platform using mutex-protected circular buffer.
Lock-free task log buffer for host platform.
Threading Model: Multi-Producer Single-Consumer (MPSC)
This uses the FreeRTOS ring buffer (RINGBUF_TYPE_NOSPLIT) which provides built-in thread-safety for the MPSC pattern. The ring buffer ensures message integrity - each message is stored contiguously.
Design:
- Variable-size messages with header + text stored contiguously
- FreeRTOS ring buffer handles synchronization internally
- Atomic counter for fast has_messages() check without ring buffer lock
Threading Model: Multi-Producer Single-Consumer (MPSC)
This implements a lock-free ring buffer for log messages on the host platform. It uses atomic compare-and-swap (CAS) operations for thread-safe slot reservation without requiring mutexes in the hot path.
Design:
- Fixed number of pre-allocated message slots to avoid dynamic allocation
- Each slot contains a header and fixed-size text buffer
- Atomic CAS for slot reservation allows multiple producers without locks
- Single consumer (main loop) processes messages in order
Why This Is Critical: Without thread-safe logging, when a non-main task logs a message, it would directly call the logger which builds a protobuf message in a shared buffer. If this happens while the main loop is also using that buffer (e.g., sending API responses), the buffer gets corrupted, sending garbage to all connected API clients and breaking their connections. This buffer ensures log messages from other tasks are queued safely and processed only from the main loop.
Threading Model: Multi-Producer Single-Consumer (MPSC)
This uses a simple circular buffer protected by a FreeRTOS mutex. Unlike ESP32, LibreTiny lacks hardware atomic support (ARM968E-S has no LDREX/STREX), so we use a volatile counter for fast has_messages() checks instead of atomics.
Design:
- Variable-size messages with header + text stored contiguously (NOSPLIT style)
- FreeRTOS mutex protects all buffer operations
- Volatile counter enables fast has_messages() without lock overhead
- If message doesn't fit at end, padding is added and message wraps to start
Definition at line 18 of file task_log_buffer_zephyr.h.