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:
@@ -19,7 +19,7 @@ Device::Device(const std::string& mount_path) : mount_path_(mount_path) {}
|
||||
Device::~Device() = default;
|
||||
|
||||
void Device::Dump(StringBuffer* string_buffer) {
|
||||
std::lock_guard<xe::recursive_mutex> lock(mutex_);
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
root_entry_->Dump(string_buffer, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ class Device {
|
||||
virtual bool Initialize() = 0;
|
||||
void Dump(StringBuffer* string_buffer);
|
||||
|
||||
xe::recursive_mutex& mutex() { return mutex_; }
|
||||
const std::string& mount_path() const { return mount_path_; }
|
||||
|
||||
virtual bool is_read_only() const { return true; }
|
||||
@@ -41,7 +40,7 @@ class Device {
|
||||
virtual uint32_t bytes_per_sector() const = 0;
|
||||
|
||||
protected:
|
||||
xe::recursive_mutex mutex_;
|
||||
xe::global_critical_region global_critical_region_;
|
||||
std::string mount_path_;
|
||||
std::unique_ptr<Entry> root_entry_;
|
||||
};
|
||||
|
||||
@@ -47,7 +47,7 @@ void Entry::Dump(xe::StringBuffer* string_buffer, int indent) {
|
||||
bool Entry::is_read_only() const { return device_->is_read_only(); }
|
||||
|
||||
Entry* Entry::GetChild(std::string name) {
|
||||
std::lock_guard<xe::recursive_mutex> lock(device_->mutex());
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
// TODO(benvanik): a faster search
|
||||
for (auto& child : children_) {
|
||||
if (strcasecmp(child->name().c_str(), name.c_str()) == 0) {
|
||||
@@ -59,7 +59,7 @@ Entry* Entry::GetChild(std::string name) {
|
||||
|
||||
Entry* Entry::IterateChildren(const xe::filesystem::WildcardEngine& engine,
|
||||
size_t* current_index) {
|
||||
std::lock_guard<xe::recursive_mutex> lock(device_->mutex());
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
while (*current_index < children_.size()) {
|
||||
auto& child = children_[*current_index];
|
||||
*current_index = *current_index + 1;
|
||||
@@ -71,10 +71,10 @@ Entry* Entry::IterateChildren(const xe::filesystem::WildcardEngine& engine,
|
||||
}
|
||||
|
||||
Entry* Entry::CreateEntry(std::string name, uint32_t attributes) {
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
if (is_read_only()) {
|
||||
return nullptr;
|
||||
}
|
||||
std::lock_guard<xe::recursive_mutex> lock(device_->mutex());
|
||||
if (GetChild(name)) {
|
||||
// Already exists.
|
||||
return nullptr;
|
||||
@@ -90,10 +90,10 @@ Entry* Entry::CreateEntry(std::string name, uint32_t attributes) {
|
||||
}
|
||||
|
||||
bool Entry::Delete(Entry* entry) {
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
if (is_read_only()) {
|
||||
return false;
|
||||
}
|
||||
std::lock_guard<xe::recursive_mutex> lock(device_->mutex());
|
||||
if (entry->parent() != this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "xenia/base/filesystem.h"
|
||||
#include "xenia/base/mapped_memory.h"
|
||||
#include "xenia/base/mutex.h"
|
||||
#include "xenia/base/string_buffer.h"
|
||||
#include "xenia/kernel/xobject.h"
|
||||
#include "xenia/xbox.h"
|
||||
@@ -125,6 +126,7 @@ class Entry {
|
||||
}
|
||||
virtual bool DeleteEntryInternal(Entry* entry) { return false; }
|
||||
|
||||
xe::global_critical_region global_critical_region_;
|
||||
Device* device_;
|
||||
Entry* parent_;
|
||||
std::string path_;
|
||||
|
||||
@@ -27,20 +27,20 @@ VirtualFileSystem::~VirtualFileSystem() {
|
||||
}
|
||||
|
||||
bool VirtualFileSystem::RegisterDevice(std::unique_ptr<Device> device) {
|
||||
std::lock_guard<xe::mutex> lock(mutex_);
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
devices_.emplace_back(std::move(device));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VirtualFileSystem::RegisterSymbolicLink(std::string path,
|
||||
std::string target) {
|
||||
std::lock_guard<xe::mutex> lock(mutex_);
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
symlinks_.insert({path, target});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VirtualFileSystem::UnregisterSymbolicLink(std::string path) {
|
||||
std::lock_guard<xe::mutex> lock(mutex_);
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
auto it = symlinks_.find(path);
|
||||
if (it == symlinks_.end()) {
|
||||
return false;
|
||||
@@ -50,7 +50,7 @@ bool VirtualFileSystem::UnregisterSymbolicLink(std::string path) {
|
||||
}
|
||||
|
||||
Entry* VirtualFileSystem::ResolvePath(std::string path) {
|
||||
std::lock_guard<xe::mutex> lock(mutex_);
|
||||
auto global_lock = global_critical_region_.Acquire();
|
||||
|
||||
// Resolve relative paths
|
||||
std::string normalized_path(xe::filesystem::CanonicalizePath(path));
|
||||
|
||||
@@ -46,7 +46,7 @@ class VirtualFileSystem {
|
||||
FileAction* out_action);
|
||||
|
||||
private:
|
||||
xe::mutex mutex_;
|
||||
xe::global_critical_region global_critical_region_;
|
||||
std::vector<std::unique_ptr<Device>> devices_;
|
||||
std::unordered_map<std::string, std::string> symlinks_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user