fix(firmware): event_log bounded mutex wait, skip on contention
Mutex take in event_log_write and event_log_read_recent switched from portMAX_DELAY to pdMS_TO_TICKS(50) with skip-on-timeout. Prevents the high-priority WiFi event task from stalling on NVS writes; diag loss under contention is preferable to dropped WiFi events.
This commit is contained in:
@@ -102,7 +102,11 @@ void event_log_init() {
|
|||||||
void event_log_write(EventLogTag tag, uint16_t data0, uint16_t data1) {
|
void event_log_write(EventLogTag tag, uint16_t data0, uint16_t data1) {
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
if (!s_ok) return;
|
if (!s_ok) return;
|
||||||
if (s_mutex) xSemaphoreTake(s_mutex, portMAX_DELAY);
|
// Bounded wait: skip on contention rather than stall the calling task.
|
||||||
|
// This matters because event_log_write runs from the WiFi event task
|
||||||
|
// (priority 23); blocking it on a 10-100ms NVS write can overflow the
|
||||||
|
// event queue. Diagnostic loss is preferable to dropped WiFi events.
|
||||||
|
if (s_mutex && xSemaphoreTake(s_mutex, pdMS_TO_TICKS(50)) != pdTRUE) return;
|
||||||
EventLogEntry e = {};
|
EventLogEntry e = {};
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
e.ts_unix = (now > NTP_SYNC_THRESHOLD) ? (uint32_t)now : 0;
|
e.ts_unix = (now > NTP_SYNC_THRESHOLD) ? (uint32_t)now : 0;
|
||||||
@@ -132,7 +136,9 @@ void event_log_write(EventLogTag tag, uint16_t data0, uint16_t data1) {
|
|||||||
size_t event_log_read_recent(EventLogEntry* out, size_t max_entries) {
|
size_t event_log_read_recent(EventLogEntry* out, size_t max_entries) {
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
if (!s_ok) return 0;
|
if (!s_ok) return 0;
|
||||||
if (s_mutex) xSemaphoreTake(s_mutex, portMAX_DELAY);
|
// Bounded wait to match event_log_write. Reads are slower (32 NVS gets),
|
||||||
|
// but returning 0 entries under contention beats blocking the caller.
|
||||||
|
if (s_mutex && xSemaphoreTake(s_mutex, pdMS_TO_TICKS(50)) != pdTRUE) return 0;
|
||||||
#endif
|
#endif
|
||||||
uint32_t head = g_head;
|
uint32_t head = g_head;
|
||||||
uint32_t cnt = g_cnt;
|
uint32_t cnt = g_cnt;
|
||||||
|
|||||||
@@ -35,6 +35,12 @@ static_assert(sizeof(EventLogEntry) == 32, "EventLogEntry must be 32 bytes");
|
|||||||
// NVS-backed 32-slot ring buffer. Safe to call before NTP sync.
|
// NVS-backed 32-slot ring buffer. Safe to call before NTP sync.
|
||||||
// Call exactly once from application setup, before any task writes events.
|
// Call exactly once from application setup, before any task writes events.
|
||||||
void event_log_init();
|
void event_log_init();
|
||||||
|
|
||||||
|
// Safe to call from any FreeRTOS task after event_log_init().
|
||||||
|
// Bounded mutex wait (~50ms) — will silently skip on contention rather than
|
||||||
|
// block the calling task. Acceptable for diagnostic logging.
|
||||||
void event_log_write(EventLogTag tag, uint16_t data0 = 0, uint16_t data1 = 0);
|
void event_log_write(EventLogTag tag, uint16_t data0 = 0, uint16_t data1 = 0);
|
||||||
|
|
||||||
|
// Same bounded-wait contract as event_log_write: returns 0 on mutex timeout.
|
||||||
size_t event_log_read_recent(EventLogEntry* out, size_t max_entries);
|
size_t event_log_read_recent(EventLogEntry* out, size_t max_entries);
|
||||||
uint16_t event_log_path_hash(const char* path); // fnv1a16 — exposed for tests
|
uint16_t event_log_path_hash(const char* path); // fnv1a16 — exposed for tests
|
||||||
|
|||||||
Reference in New Issue
Block a user