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:
Ben Vanik
2015-09-06 09:30:54 -07:00
parent 33270cd2a0
commit 3c96b6fa0a
50 changed files with 271 additions and 219 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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