소스 검색

Merge pull request #10611 from liamwhite/audio-deadlock

audio_renderer: resolve adsp thread deadlock shutdown
bunnei 3 년 전
부모
커밋
db7b106f1d

+ 4 - 4
src/audio_core/renderer/adsp/audio_renderer.cpp

@@ -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
                     {
                     {

+ 2 - 2
src/audio_core/renderer/adsp/audio_renderer.h

@@ -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

+ 3 - 2
src/audio_core/sink/sink_stream.cpp

@@ -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; });
     }
     }
 }
 }
 
 

+ 3 - 2
src/audio_core/sink/sink_stream.h

@@ -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;
 };
 };