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

@@ -13,7 +13,6 @@
#include <algorithm>
#include <cstring>
#include <mutex>
#include "xenia/base/clock.h"
#include "xenia/base/logging.h"
@@ -461,7 +460,7 @@ void BaseHeap::Dispose() {
}
void BaseHeap::DumpMap() {
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
XELOGE("------------------------------------------------------------------");
XELOGE("Heap: %.8X-%.8X", heap_base_, heap_base_ + heap_size_);
XELOGE("------------------------------------------------------------------");
@@ -535,7 +534,7 @@ bool BaseHeap::AllocFixed(uint32_t base_address, uint32_t size,
return false;
}
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
// - If we are reserving the entire range requested must not be already
// reserved.
@@ -620,7 +619,7 @@ bool BaseHeap::AllocRange(uint32_t low_address, uint32_t high_address,
return false;
}
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
// Find a free page range.
// The base page must match the requested alignment, so we first scan for
@@ -751,7 +750,7 @@ bool BaseHeap::Decommit(uint32_t address, uint32_t size) {
std::min(uint32_t(page_table_.size()) - 1, start_page_number);
end_page_number = std::min(uint32_t(page_table_.size()) - 1, end_page_number);
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
// Release from host.
// TODO(benvanik): find a way to actually decommit memory;
@@ -775,7 +774,7 @@ bool BaseHeap::Decommit(uint32_t address, uint32_t size) {
}
bool BaseHeap::Release(uint32_t base_address, uint32_t* out_region_size) {
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
// Given address must be a region base address.
uint32_t base_page_number = (base_address - heap_base_) / page_size_;
@@ -831,7 +830,7 @@ bool BaseHeap::Protect(uint32_t address, uint32_t size, uint32_t protect) {
std::min(uint32_t(page_table_.size()) - 1, start_page_number);
end_page_number = std::min(uint32_t(page_table_.size()) - 1, end_page_number);
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
// Ensure all pages are in the same reserved region and all are committed.
uint32_t first_base_address = UINT_MAX;
@@ -883,7 +882,7 @@ bool BaseHeap::QueryRegionInfo(uint32_t base_address,
return false;
}
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
auto start_page_entry = page_table_[start_page_number];
out_info->base_address = base_address;
@@ -934,7 +933,7 @@ bool BaseHeap::QuerySize(uint32_t address, uint32_t* out_size) {
*out_size = 0;
return false;
}
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
auto page_entry = page_table_[page_number];
*out_size = (page_entry.region_page_count * page_size_);
return true;
@@ -947,7 +946,7 @@ bool BaseHeap::QueryProtect(uint32_t address, uint32_t* out_protect) {
*out_protect = 0;
return false;
}
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
auto page_entry = page_table_[page_number];
*out_protect = page_entry.current_protect;
return true;
@@ -995,7 +994,7 @@ bool PhysicalHeap::Alloc(uint32_t size, uint32_t alignment,
size = xe::round_up(size, page_size_);
alignment = xe::round_up(alignment, page_size_);
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
// Allocate from parent heap (gets our physical address in 0-512mb).
uint32_t parent_low_address = GetPhysicalAddress(heap_base_);
@@ -1033,7 +1032,7 @@ bool PhysicalHeap::AllocFixed(uint32_t base_address, uint32_t size,
size = xe::round_up(size, page_size_);
alignment = xe::round_up(alignment, page_size_);
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
// Allocate from parent heap (gets our physical address in 0-512mb).
// NOTE: this can potentially overwrite heap contents if there are already
@@ -1074,7 +1073,7 @@ bool PhysicalHeap::AllocRange(uint32_t low_address, uint32_t high_address,
size = xe::round_up(size, page_size_);
alignment = xe::round_up(alignment, page_size_);
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
// Allocate from parent heap (gets our physical address in 0-512mb).
low_address = std::max(heap_base_, low_address);
@@ -1108,7 +1107,7 @@ bool PhysicalHeap::AllocRange(uint32_t low_address, uint32_t high_address,
}
bool PhysicalHeap::Decommit(uint32_t address, uint32_t size) {
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
uint32_t parent_address = GetPhysicalAddress(address);
if (!parent_heap_->Decommit(parent_address, size)) {
XELOGE("PhysicalHeap::Decommit failed due to parent heap failure");
@@ -1118,7 +1117,7 @@ bool PhysicalHeap::Decommit(uint32_t address, uint32_t size) {
}
bool PhysicalHeap::Release(uint32_t base_address, uint32_t* out_region_size) {
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
uint32_t parent_base_address = GetPhysicalAddress(base_address);
if (!parent_heap_->Release(parent_base_address, out_region_size)) {
XELOGE("PhysicalHeap::Release failed due to parent heap failure");
@@ -1128,7 +1127,7 @@ bool PhysicalHeap::Release(uint32_t base_address, uint32_t* out_region_size) {
}
bool PhysicalHeap::Protect(uint32_t address, uint32_t size, uint32_t protect) {
std::lock_guard<xe::recursive_mutex> lock(heap_mutex_);
auto global_lock = global_critical_region_.Acquire();
uint32_t parent_address = GetPhysicalAddress(address);
bool parent_result = parent_heap_->Protect(parent_address, size, protect);
if (!parent_result) {