diff --git a/companion/src/simulation/wasmsimulatorinterface.cpp b/companion/src/simulation/wasmsimulatorinterface.cpp index d9081741e50..44746a2cfe5 100644 --- a/companion/src/simulation/wasmsimulatorinterface.cpp +++ b/companion/src/simulation/wasmsimulatorinterface.cpp @@ -444,9 +444,11 @@ void WasmSimulatorInterface::init() m_stopRequested = false; + for (auto & value : m_analogValues) + value.store(0, std::memory_order_relaxed); + // Call simuInit QMutexLocker lckr(&m_mutex); - memset(m_analogValues, 0, sizeof(m_analogValues)); wasm_runtime_call_wasm(m_execEnv, m_fnInit, 0, nullptr); // Query LCD dimensions @@ -584,13 +586,16 @@ void WasmSimulatorInterface::stop() return; m_stopRequested = true; - deinitAudio(); { QMutexLocker lckr(&m_mutex); wasm_runtime_call_wasm(m_execEnv, m_fnStop, 0, nullptr); } + // Close audio only once simuStop() has joined the firmware threads, so the + // audio task cannot be inside SDL_QueueAudio() while the device closes. + deinitAudio(); + // Fully destroy the WASM module so the next init()/start() gets a clean // instance. WASI threads created by the firmware's RTOS layer cannot be // reliably restarted within the same module instance. @@ -614,16 +619,15 @@ void WasmSimulatorInterface::setVolumeGain(const int value) void WasmSimulatorInterface::setAnalogValue(uint8_t index, int16_t value) { - QMutexLocker lckr(&m_mutex); if (index < MAX_ANALOGS) - m_analogValues[index] = value; + m_analogValues[index].store(value, std::memory_order_relaxed); } +// Called from firmware threads; must not take m_mutex (see header). int16_t WasmSimulatorInterface::getAnalogValue(uint8_t index) { - QMutexLocker lckr(&m_mutex); if (index < MAX_ANALOGS) - return m_analogValues[index]; + return m_analogValues[index].load(std::memory_order_relaxed); return 0; } diff --git a/companion/src/simulation/wasmsimulatorinterface.h b/companion/src/simulation/wasmsimulatorinterface.h index 6daebe8918f..1d8596f6606 100644 --- a/companion/src/simulation/wasmsimulatorinterface.h +++ b/companion/src/simulation/wasmsimulatorinterface.h @@ -126,7 +126,9 @@ class WasmSimulatorInterface : public SimulatorInterface // Host-side analog values (polled by WASM via simuGetAnalog) static constexpr int MAX_ANALOGS = 32; - int16_t m_analogValues[MAX_ANALOGS] = {}; + // Read by firmware threads through host_simuGetAnalog, so kept out of + // m_mutex: stop() holds that across simuStop(), which joins those threads. + std::atomic m_analogValues[MAX_ANALOGS] = {}; // Cached output values for change detection TxOutputs m_lastOutputs;