DANGER DANGER. Switching to global critical region.
This changes almost all locks held by guest threads to use a single global critical region. This emulates the behavior on the PPC of disabling interrupts (by calls like KeRaiseIrqlToDpcLevel or masking interrupts), and prevents deadlocks from occuring when threads are suspended or otherwise blocked. This has performance implications and a pass is needed to ensure the locking is as granular as possible. It could also break everything because it's fundamentally unsound. We'll see.
This commit is contained in:
@@ -124,10 +124,10 @@ void AudioSystem::WorkerThreadMain() {
|
||||
if (result.first == xe::threading::WaitResult::kSuccess) {
|
||||
size_t index = result.second;
|
||||
do {
|
||||
lock_.lock();
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
uint32_t client_callback = clients_[index].callback;
|
||||
uint32_t client_callback_arg = clients_[index].wrapped_callback_arg;
|
||||
lock_.unlock();
|
||||
global_lock.unlock();
|
||||
|
||||
if (client_callback) {
|
||||
SCOPE_profile_cpu_i("apu", "xe::apu::AudioSystem->client_callback");
|
||||
@@ -169,7 +169,7 @@ void AudioSystem::Shutdown() {
|
||||
X_STATUS AudioSystem::RegisterClient(uint32_t callback, uint32_t callback_arg,
|
||||
size_t* out_index) {
|
||||
assert_true(unused_clients_.size());
|
||||
std::lock_guard<xe::mutex> lock(lock_);
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
|
||||
auto index = unused_clients_.front();
|
||||
|
||||
@@ -201,7 +201,7 @@ X_STATUS AudioSystem::RegisterClient(uint32_t callback, uint32_t callback_arg,
|
||||
void AudioSystem::SubmitFrame(size_t index, uint32_t samples_ptr) {
|
||||
SCOPE_profile_cpu_f("apu");
|
||||
|
||||
std::lock_guard<xe::mutex> lock(lock_);
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
assert_true(index < kMaximumClientCount);
|
||||
assert_true(clients_[index].driver != NULL);
|
||||
(clients_[index].driver)->SubmitFrame(samples_ptr);
|
||||
@@ -210,7 +210,7 @@ void AudioSystem::SubmitFrame(size_t index, uint32_t samples_ptr) {
|
||||
void AudioSystem::UnregisterClient(size_t index) {
|
||||
SCOPE_profile_cpu_f("apu");
|
||||
|
||||
std::lock_guard<xe::mutex> lock(lock_);
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
assert_true(index < kMaximumClientCount);
|
||||
DestroyDriver(clients_[index].driver);
|
||||
clients_[index] = {0};
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#define XENIA_APU_AUDIO_SYSTEM_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
#include "xenia/base/mutex.h"
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/kernel/objects/xthread.h"
|
||||
@@ -67,10 +67,8 @@ class AudioSystem {
|
||||
std::atomic<bool> worker_running_ = {false};
|
||||
kernel::object_ref<kernel::XHostThread> worker_thread_;
|
||||
|
||||
xe::mutex lock_;
|
||||
|
||||
xe::global_critical_region global_critical_region_;
|
||||
static const size_t kMaximumClientCount = 8;
|
||||
|
||||
struct {
|
||||
AudioDriver* driver;
|
||||
uint32_t callback;
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#define XENIA_APU_XMA_CONTEXT_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
#include "xenia/base/mutex.h"
|
||||
#include "xenia/memory.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
#define XENIA_APU_XMA_DECODER_H_
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
#include "xenia/apu/xma_context.h"
|
||||
#include "xenia/base/mutex.h"
|
||||
#include "xenia/kernel/objects/xthread.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user