diff options
| author | 2021-11-28 13:05:18 -0800 | |
|---|---|---|
| committer | 2021-12-06 16:39:18 -0800 | |
| commit | efb5de1c5f1c26de7d8346caf4bf09cc48f9906a (patch) | |
| tree | a387df1711a62876ba27827a56d452b95ed5e222 /src | |
| parent | hle: kernel: k_thread: Skip reschedule on DisableDispatch with SC. (diff) | |
| download | yuzu-efb5de1c5f1c26de7d8346caf4bf09cc48f9906a.tar.gz yuzu-efb5de1c5f1c26de7d8346caf4bf09cc48f9906a.tar.xz yuzu-efb5de1c5f1c26de7d8346caf4bf09cc48f9906a.zip | |
hle: kernel: service_thread: Use std::jthread.
- Fixes a potential deadlock on service thread shutdown.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/service_thread.cpp | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index 6721b6276..00657bc4c 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp | |||
| @@ -25,24 +25,27 @@ public: | |||
| 25 | void QueueSyncRequest(KSession& session, std::shared_ptr<HLERequestContext>&& context); | 25 | void QueueSyncRequest(KSession& session, std::shared_ptr<HLERequestContext>&& context); |
| 26 | 26 | ||
| 27 | private: | 27 | private: |
| 28 | std::vector<std::thread> threads; | 28 | std::vector<std::jthread> threads; |
| 29 | std::queue<std::function<void()>> requests; | 29 | std::queue<std::function<void()>> requests; |
| 30 | std::mutex queue_mutex; | 30 | std::mutex queue_mutex; |
| 31 | std::condition_variable condition; | 31 | std::condition_variable_any condition; |
| 32 | const std::string service_name; | 32 | const std::string service_name; |
| 33 | bool stop{}; | ||
| 34 | }; | 33 | }; |
| 35 | 34 | ||
| 36 | ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name) | 35 | ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std::string& name) |
| 37 | : service_name{name} { | 36 | : service_name{name} { |
| 38 | for (std::size_t i = 0; i < num_threads; ++i) | 37 | for (std::size_t i = 0; i < num_threads; ++i) { |
| 39 | threads.emplace_back([this, &kernel] { | 38 | threads.emplace_back([this, &kernel](std::stop_token stop_token) { |
| 40 | Common::SetCurrentThreadName(std::string{"yuzu:HleService:" + service_name}.c_str()); | 39 | Common::SetCurrentThreadName(std::string{"yuzu:HleService:" + service_name}.c_str()); |
| 41 | 40 | ||
| 42 | // Wait for first request before trying to acquire a render context | 41 | // Wait for first request before trying to acquire a render context |
| 43 | { | 42 | { |
| 44 | std::unique_lock lock{queue_mutex}; | 43 | std::unique_lock lock{queue_mutex}; |
| 45 | condition.wait(lock, [this] { return stop || !requests.empty(); }); | 44 | condition.wait(lock, stop_token, [this] { return !requests.empty(); }); |
| 45 | } | ||
| 46 | |||
| 47 | if (stop_token.stop_requested()) { | ||
| 48 | return; | ||
| 46 | } | 49 | } |
| 47 | 50 | ||
| 48 | kernel.RegisterHostThread(); | 51 | kernel.RegisterHostThread(); |
| @@ -52,10 +55,16 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std | |||
| 52 | 55 | ||
| 53 | { | 56 | { |
| 54 | std::unique_lock lock{queue_mutex}; | 57 | std::unique_lock lock{queue_mutex}; |
| 55 | condition.wait(lock, [this] { return stop || !requests.empty(); }); | 58 | condition.wait(lock, stop_token, [this] { return !requests.empty(); }); |
| 56 | if (stop || requests.empty()) { | 59 | |
| 60 | if (stop_token.stop_requested()) { | ||
| 57 | return; | 61 | return; |
| 58 | } | 62 | } |
| 63 | |||
| 64 | if (requests.empty()) { | ||
| 65 | continue; | ||
| 66 | } | ||
| 67 | |||
| 59 | task = std::move(requests.front()); | 68 | task = std::move(requests.front()); |
| 60 | requests.pop(); | 69 | requests.pop(); |
| 61 | } | 70 | } |
| @@ -63,6 +72,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel, std::size_t num_threads, const std | |||
| 63 | task(); | 72 | task(); |
| 64 | } | 73 | } |
| 65 | }); | 74 | }); |
| 75 | } | ||
| 66 | } | 76 | } |
| 67 | 77 | ||
| 68 | void ServiceThread::Impl::QueueSyncRequest(KSession& session, | 78 | void ServiceThread::Impl::QueueSyncRequest(KSession& session, |
| @@ -87,16 +97,7 @@ void ServiceThread::Impl::QueueSyncRequest(KSession& session, | |||
| 87 | condition.notify_one(); | 97 | condition.notify_one(); |
| 88 | } | 98 | } |
| 89 | 99 | ||
| 90 | ServiceThread::Impl::~Impl() { | 100 | ServiceThread::Impl::~Impl() = default; |
| 91 | { | ||
| 92 | std::unique_lock lock{queue_mutex}; | ||
| 93 | stop = true; | ||
| 94 | } | ||
| 95 | condition.notify_all(); | ||
| 96 | for (std::thread& thread : threads) { | ||
| 97 | thread.join(); | ||
| 98 | } | ||
| 99 | } | ||
| 100 | 101 | ||
| 101 | ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name) | 102 | ServiceThread::ServiceThread(KernelCore& kernel, std::size_t num_threads, const std::string& name) |
| 102 | : impl{std::make_unique<Impl>(kernel, num_threads, name)} {} | 103 | : impl{std::make_unique<Impl>(kernel, num_threads, name)} {} |