From a0c524774386c4543c710958bf1c607a91d6f28c Mon Sep 17 00:00:00 2001 From: Moncef Mechri Date: Sun, 9 Aug 2015 00:37:48 +0200 Subject: Initialize ALSA before starting the audio thread This fixes a race condition: Before this commit, there was a race condition when starting a game: Core::EmuThread(), after having started (but not necessarily completed) the initialization of the audio thread, calls Core::SetState() which calls CCPU::EnableStepping(), which in turns calls AudioCommon::ClearAudioBuffer(). This means that SoundStream::Clear() can be called before AlsaSound::AlsaInit() has completed. --- Source/Core/AudioCommon/AlsaSoundStream.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'Source/Core/AudioCommon/AlsaSoundStream.cpp') diff --git a/Source/Core/AudioCommon/AlsaSoundStream.cpp b/Source/Core/AudioCommon/AlsaSoundStream.cpp index 5902edba94..ae888564b3 100644 --- a/Source/Core/AudioCommon/AlsaSoundStream.cpp +++ b/Source/Core/AudioCommon/AlsaSoundStream.cpp @@ -26,6 +26,12 @@ AlsaSound::~AlsaSound() bool AlsaSound::Start() { m_thread_status.store(ALSAThreadStatus::RUNNING); + if (!AlsaInit()) + { + m_thread_status.store(ALSAThreadStatus::STOPPED); + return false; + } + thread = std::thread(&AlsaSound::SoundLoop, this); return true; } @@ -44,10 +50,6 @@ void AlsaSound::Update() // Called on audio thread. void AlsaSound::SoundLoop() { - if (!AlsaInit()) { - m_thread_status.store(ALSAThreadStatus::STOPPED); - return; - } Common::SetCurrentThreadName("Audio thread - alsa"); while (m_thread_status.load() == ALSAThreadStatus::RUNNING) { -- cgit v1.2.3 From 333f998123f617c6e643103184142d67c090c7fd Mon Sep 17 00:00:00 2001 From: Moncef Mechri Date: Tue, 7 Jul 2015 15:30:27 +0200 Subject: Don't busy wait in the audio thread (ALSA) When the emulation is paused and the ALSA backend is used, make the audio thread wait on a condition variable instead of busy-waiting. This commit fixes bug #7729 Since the ALSA API is not thread-safe, calls to snd_pcm_drop() and snd_pcm_prepare() in AlsaSound::Clear() are protected by the same mutex as the condition variable in AlsaSound::SoundLoop() to make sure that we do not call these functions while a call to snd_pcm_writei() is ongoing. --- Source/Core/AudioCommon/AlsaSoundStream.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'Source/Core/AudioCommon/AlsaSoundStream.cpp') diff --git a/Source/Core/AudioCommon/AlsaSoundStream.cpp b/Source/Core/AudioCommon/AlsaSoundStream.cpp index ae888564b3..3a1f460133 100644 --- a/Source/Core/AudioCommon/AlsaSoundStream.cpp +++ b/Source/Core/AudioCommon/AlsaSoundStream.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include + #include "AudioCommon/AlsaSoundStream.h" #include "Common/CommonTypes.h" #include "Common/Thread.h" @@ -39,6 +41,10 @@ bool AlsaSound::Start() void AlsaSound::Stop() { m_thread_status.store(ALSAThreadStatus::STOPPING); + + //Give the opportunity to the audio thread + //to realize we are stopping the emulation + cv.notify_one(); thread.join(); } @@ -53,8 +59,11 @@ void AlsaSound::SoundLoop() Common::SetCurrentThreadName("Audio thread - alsa"); while (m_thread_status.load() == ALSAThreadStatus::RUNNING) { + std::unique_lock lock(cv_m); + cv.wait(lock, [this]{return !m_muted || m_thread_status.load() != ALSAThreadStatus::RUNNING;}); + m_mixer->Mix(reinterpret_cast(mix_buffer), frames_to_deliver); - int rc = m_muted ? 1337 : snd_pcm_writei(handle, mix_buffer, frames_to_deliver); + int rc = snd_pcm_writei(handle, mix_buffer, frames_to_deliver); if (rc == -EPIPE) { // Underrun @@ -69,6 +78,24 @@ void AlsaSound::SoundLoop() m_thread_status.store(ALSAThreadStatus::STOPPED); } + +void AlsaSound::Clear(bool muted) +{ + m_muted = muted; + if (m_muted) + { + std::lock_guard lock(cv_m); + snd_pcm_drop(handle); + } + else + { + std::unique_lock lock(cv_m); + snd_pcm_prepare(handle); + lock.unlock(); + cv.notify_one(); + } +} + bool AlsaSound::AlsaInit() { unsigned int sample_rate = m_mixer->GetSampleRate(); -- cgit v1.2.3 From cc036ca86cdaf709e01221975da734cb64d54a94 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 26 Sep 2015 17:13:07 -0400 Subject: Common: Remove other Common prefixed headers from Common.h --- Source/Core/AudioCommon/AlsaSoundStream.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'Source/Core/AudioCommon/AlsaSoundStream.cpp') diff --git a/Source/Core/AudioCommon/AlsaSoundStream.cpp b/Source/Core/AudioCommon/AlsaSoundStream.cpp index 3a1f460133..a132cb5de3 100644 --- a/Source/Core/AudioCommon/AlsaSoundStream.cpp +++ b/Source/Core/AudioCommon/AlsaSoundStream.cpp @@ -7,6 +7,7 @@ #include "AudioCommon/AlsaSoundStream.h" #include "Common/CommonTypes.h" #include "Common/Thread.h" +#include "Common/Logging/Log.h" #define FRAME_COUNT_MIN 256 #define BUFFER_SIZE_MAX 8192 -- cgit v1.2.3