fix: don't wait on a log lock holder that can't run

The log lock is a binary semaphore, so when the radio task preempted loop()
mid-log every log from async_tcp waited the full 20ms for a holder that
couldn't let go until the radio job ended.  Waiting now stops as soon as
the holder is preempted on another core.  The rule lives in
LogLockPolicy.h with unit tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-12 18:35:42 +02:00
parent e47381b19e
commit 9988a2bec8
3 changed files with 93 additions and 2 deletions

21
src/LogLockPolicy.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef LOG_LOCK_POLICY_H
#define LOG_LOCK_POLICY_H
#include <stdint.h>
// When a log call stops waiting for the log lock (src/LogLock.cpp). Kept free
// of FreeRTOS so it can be unit tested on the PC (pio test -e native).
// What the task holding the log lock is doing.
enum class LogHolder {
unknown, // Just took the lock and hasn't recorded itself yet.
running, // Running on a core, so it lets go within a line.
preemptedHere, // Waiting for this core, so blocking lets it finish.
preemptedElsewhere // Preempted on another core (the radio task during a
// whole transmission), so waiting gets nowhere.
};
// Whether to keep waiting after waitedMs. Never past maxMs.
inline bool keepWaitingForLogLock(LogHolder holder, uint32_t waitedMs, uint32_t maxMs) {
if(waitedMs >= maxMs) return false;
return holder != LogHolder::preemptedElsewhere;
}
#endif