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:
2026-04-23 13:31:54 -07:00
parent 84d9ba349b
commit cfa0d2563f
2 changed files with 14 additions and 2 deletions

View File

@@ -102,7 +102,11 @@ void event_log_init() {
void event_log_write(EventLogTag tag, uint16_t data0, uint16_t data1) {
#ifdef ARDUINO
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 = {};
time_t now = time(nullptr);
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) {
#ifdef ARDUINO
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
uint32_t head = g_head;
uint32_t cnt = g_cnt;

View File

@@ -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.
// Call exactly once from application setup, before any task writes events.
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);
// 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);
uint16_t event_log_path_hash(const char* path); // fnv1a16 — exposed for tests