summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/memory.cpp52
1 files changed, 40 insertions, 12 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index b7f21698f..54a848936 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -4,6 +4,7 @@
#include <algorithm>
#include <cstring>
+#include <mutex>
#include <optional>
#include <utility>
@@ -497,7 +498,21 @@ struct Memory::Impl {
return CopyBlock(*system.CurrentProcess(), dest_addr, src_addr, size);
}
+ struct PageEntry {
+ u8* const pointer;
+ const Common::PageType attribute;
+ };
+
+ PageEntry SafePageEntry(std::size_t base) const {
+ std::lock_guard lock{rasterizer_cache_guard};
+ return {
+ .pointer = current_page_table->pointers[base],
+ .attribute = current_page_table->attributes[base],
+ };
+ }
+
void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) {
+ std::lock_guard lock{rasterizer_cache_guard};
if (vaddr == 0) {
return;
}
@@ -630,16 +645,22 @@ struct Memory::Impl {
*/
template <typename T>
T Read(const VAddr vaddr) {
- const u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
- if (page_pointer != nullptr) {
- // NOTE: Avoid adding any extra logic to this fast-path block
+ // Avoid adding any extra logic to this fast-path block
+ if (const u8* const pointer = current_page_table->pointers[vaddr >> PAGE_BITS]) {
T value;
- std::memcpy(&value, &page_pointer[vaddr], sizeof(T));
+ std::memcpy(&value, &pointer[vaddr], sizeof(T));
return value;
}
- const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
- switch (type) {
+ // Otherwise, we need to grab the page with a lock, in case it is currently being modified
+ const auto entry = SafePageEntry(vaddr >> PAGE_BITS);
+ if (entry.pointer) {
+ T value;
+ std::memcpy(&value, &entry.pointer[vaddr], sizeof(T));
+ return value;
+ }
+
+ switch (entry.attribute) {
case Common::PageType::Unmapped:
LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr);
return 0;
@@ -670,15 +691,21 @@ struct Memory::Impl {
*/
template <typename T>
void Write(const VAddr vaddr, const T data) {
- u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
- if (page_pointer != nullptr) {
- // NOTE: Avoid adding any extra logic to this fast-path block
- std::memcpy(&page_pointer[vaddr], &data, sizeof(T));
+ // Avoid adding any extra logic to this fast-path block
+ if (u8* const pointer = current_page_table->pointers[vaddr >> PAGE_BITS]) {
+ std::memcpy(&pointer[vaddr], &data, sizeof(T));
return;
}
- const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
- switch (type) {
+ // Otherwise, we need to grab the page with a lock, in case it is currently being modified
+ const auto entry = SafePageEntry(vaddr >> PAGE_BITS);
+ if (entry.pointer) {
+ // Memory was mapped, we are done
+ std::memcpy(&entry.pointer[vaddr], &data, sizeof(T));
+ return;
+ }
+
+ switch (entry.attribute) {
case Common::PageType::Unmapped:
LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8,
static_cast<u32>(data), vaddr);
@@ -756,6 +783,7 @@ struct Memory::Impl {
return true;
}
+ mutable std::mutex rasterizer_cache_guard;
Common::PageTable* current_page_table = nullptr;
Core::System& system;
};