Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix esp32 select race conditions. (#780)
- Fixes race condition that caused ESP32's select to not wake up even though an executable was posted. - Fixes another race condition where variables are not locked when accessing from ISR (relevant on ESP32 only). - Optimizes an unnecessary round of select wakeup. Note: review is in #774 which was irreversibly closed due to an incorrect sequence of operations I did on github. === * Fixes race condition in ESP32 select-wakeup implementation. A correct implementation of a selectable fd driver has to check in vfs_select_start() whether the fd is readable. This check was missing from the prior implementation. We had an application level check of the queue being non-empty, but there is a window of time between the application doing this check, and the select() implementation of the esp32 getting to calling vfs_select_start(). The wakeup implementation was only effective if it came after vfs_select_start, by the design of esp's select mechanism, since the wakeup semaphore only comes in vfs_select_start. Since the esp32's select() is very slow, this was actually a pretty big gap. The OpenMRN Device::select implementation does not suffer from this race condition, because the event group bits can be set at any time, even if Device::select is still in the setup phase. Added a comment to this effect. * Fixes another (smaller) race condition in ESP32's select wakeup. The wakeup_from_isr routine consults the pendingWakeup_ and inSelect_ variables. These variables need to be locked, because multi-core ESP32's could run an isr on one core and othercode on a different core. Moves the atomic lock from esp_wakeup_from_isr into OSSelectWakeup::wakeup_from_isr. * Optimizes unnecessary select iterations. When the application already knows about the executables in the queue, we don't need select to terminate with EINTR. We either ran the executable and the queue is empty (in which case we want select to sleep), or we know the queue is not empty and thus will run select with a timeout of 0.
- Loading branch information