yuzu-emu
/
yuzu
Archived
1
0
Fork 0

Merge pull request #10611 from liamwhite/audio-deadlock

audio_renderer: resolve adsp thread deadlock shutdown
This commit is contained in:
bunnei 2023-06-05 17:15:19 -07:00 committed by GitHub
commit db7b106f1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 12 additions and 10 deletions

View File

@ -105,7 +105,7 @@ void AudioRenderer::Start(AudioRenderer_Mailbox* mailbox_) {
} }
mailbox = mailbox_; mailbox = mailbox_;
thread = std::thread(&AudioRenderer::ThreadFunc, this); thread = std::jthread([this](std::stop_token stop_token) { ThreadFunc(stop_token); });
running = true; running = true;
} }
@ -131,7 +131,7 @@ void AudioRenderer::CreateSinkStreams() {
} }
} }
void AudioRenderer::ThreadFunc() { void AudioRenderer::ThreadFunc(std::stop_token stop_token) {
static constexpr char name[]{"AudioRenderer"}; static constexpr char name[]{"AudioRenderer"};
MicroProfileOnThreadCreate(name); MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name); Common::SetCurrentThreadName(name);
@ -146,7 +146,7 @@ void AudioRenderer::ThreadFunc() {
constexpr u64 max_process_time{2'304'000ULL}; constexpr u64 max_process_time{2'304'000ULL};
while (true) { while (!stop_token.stop_requested()) {
auto message{mailbox->ADSPWaitMessage()}; auto message{mailbox->ADSPWaitMessage()};
switch (message) { switch (message) {
case RenderMessage::AudioRenderer_Shutdown: case RenderMessage::AudioRenderer_Shutdown:
@ -194,7 +194,7 @@ void AudioRenderer::ThreadFunc() {
max_time = std::min(command_buffer.time_limit, max_time); max_time = std::min(command_buffer.time_limit, max_time);
command_list_processor.SetProcessTimeMax(max_time); command_list_processor.SetProcessTimeMax(max_time);
streams[index]->WaitFreeSpace(); streams[index]->WaitFreeSpace(stop_token);
// Process the command list // Process the command list
{ {

View File

@ -177,7 +177,7 @@ private:
/** /**
* Main AudioRenderer thread, responsible for processing the command lists. * Main AudioRenderer thread, responsible for processing the command lists.
*/ */
void ThreadFunc(); void ThreadFunc(std::stop_token stop_token);
/** /**
* Creates the streams which will receive the processed samples. * Creates the streams which will receive the processed samples.
@ -187,7 +187,7 @@ private:
/// Core system /// Core system
Core::System& system; Core::System& system;
/// Main thread /// Main thread
std::thread thread{}; std::jthread thread{};
/// The current state /// The current state
std::atomic<bool> running{}; std::atomic<bool> running{};
/// The active mailbox /// The active mailbox

View File

@ -269,12 +269,13 @@ u64 SinkStream::GetExpectedPlayedSampleCount() {
return std::min<u64>(exp_played_sample_count, max_played_sample_count) + TargetSampleCount * 3; return std::min<u64>(exp_played_sample_count, max_played_sample_count) + TargetSampleCount * 3;
} }
void SinkStream::WaitFreeSpace() { void SinkStream::WaitFreeSpace(std::stop_token stop_token) {
std::unique_lock lk{release_mutex}; std::unique_lock lk{release_mutex};
release_cv.wait_for(lk, std::chrono::milliseconds(5), release_cv.wait_for(lk, std::chrono::milliseconds(5),
[this]() { return queued_buffers < max_queue_size; }); [this]() { return queued_buffers < max_queue_size; });
if (queued_buffers > max_queue_size + 3) { if (queued_buffers > max_queue_size + 3) {
release_cv.wait(lk, [this]() { return queued_buffers < max_queue_size; }); Common::CondvarWait(release_cv, lk, stop_token,
[this] { return queued_buffers < max_queue_size; });
} }
} }

View File

@ -13,6 +13,7 @@
#include "audio_core/common/common.h" #include "audio_core/common/common.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/polyfill_thread.h"
#include "common/reader_writer_queue.h" #include "common/reader_writer_queue.h"
#include "common/ring_buffer.h" #include "common/ring_buffer.h"
#include "common/thread.h" #include "common/thread.h"
@ -210,7 +211,7 @@ public:
/** /**
* Waits for free space in the sample ring buffer * Waits for free space in the sample ring buffer
*/ */
void WaitFreeSpace(); void WaitFreeSpace(std::stop_token stop_token);
protected: protected:
/// Core system /// Core system
@ -252,7 +253,7 @@ private:
/// Set via IAudioDevice service calls /// Set via IAudioDevice service calls
f32 device_volume{1.0f}; f32 device_volume{1.0f};
/// Signalled when ring buffer entries are consumed /// Signalled when ring buffer entries are consumed
std::condition_variable release_cv; std::condition_variable_any release_cv;
std::mutex release_mutex; std::mutex release_mutex;
}; };