Files
PX4-Autopilot/platforms
Julian Oes 27a21488b2 fix(lockstep_scheduler): fix signal-loss race and ABBA deadlock
Two related thread-safety fixes for the cond_timedwait + set_absolute_time
dance, both surfaced under TSan with multi-instance Mavlink and a fast
sim clock advance:

1. Signal loss between releasing _timed_waits_mutex and entering
   pthread_cond_wait. set_absolute_time could have already broadcast
   to a waiter that hadn't actually started waiting yet, and the
   broadcast would be missed -> wait blocks forever.

   Fix: cond_timedwait uses pthread_cond_timedwait with a short
   wall-clock timeout (10 ms) and re-checks the timeout flag. Lost
   signals turn into a maximum of one loop iteration of latency.

2. ABBA between (passed_lock -> _timed_waits_mutex) used by
   cond_timedwait to mark `done`, and (passed_lock under
   _timed_waits_mutex) used by set_absolute_time to broadcast. TSan
   flagged the inversion immediately.

   Fix: split set_absolute_time into three phases. Phase 1 marks
   timed_outs and stages waiters onto a per-call signal_next list,
   under _timed_waits_mutex only. Phase 2 broadcasts to each waiter,
   outside _timed_waits_mutex but under a new _signaling_mutex held
   for the duration. Phase 3 clears _setting_time under the
   _timed_waits_mutex again.

   The waiter's "dance" (when it sees _setting_time still true on
   exit) acquires _signaling_mutex first, then _timed_waits_mutex,
   guaranteeing it cannot return — and let its stack-local
   passed_lock/passed_cond go out of scope — until set_absolute_time
   has finished signaling.

The TimedWait::timeout flag also becomes std::atomic<bool> since it
is now read by cond_timedwait without holding _timed_waits_mutex.
2026-07-17 10:51:42 -05:00
..