mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
graphics: pause memory-tracking spin loops
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
#include "common/virtualMemory.h"
|
||||
#include "graphics/host_gpu/pageManager.h"
|
||||
|
||||
#include <barrier>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
|
||||
@@ -167,6 +170,7 @@ struct ProtectionCall {
|
||||
uint64_t size;
|
||||
};
|
||||
std::vector<ProtectionCall> g_protection_ranges;
|
||||
std::mutex g_protection_log_mutex;
|
||||
|
||||
bool ProtectAddressSpace(uint64_t vaddr, uint64_t size,
|
||||
Common::VirtualMemory::Mode mode) {
|
||||
@@ -177,8 +181,11 @@ bool ProtectAddressSpace(uint64_t vaddr, uint64_t size,
|
||||
protection = PAGE_READWRITE;
|
||||
}
|
||||
DWORD old_protection = 0;
|
||||
g_protection_calls++;
|
||||
g_protection_ranges.push_back({vaddr, size});
|
||||
{
|
||||
std::lock_guard lock(g_protection_log_mutex);
|
||||
g_protection_calls++;
|
||||
g_protection_ranges.push_back({vaddr, size});
|
||||
}
|
||||
return VirtualProtect(reinterpret_cast<void *>(vaddr), size, protection,
|
||||
&old_protection) != 0;
|
||||
}
|
||||
@@ -547,6 +554,34 @@ void TestReadWriteWatcherInteractions() {
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
void TestConcurrentSharedWatchers() {
|
||||
constexpr size_t worker_count = 8;
|
||||
PageManager manager;
|
||||
auto *memory = Allocate(TRACKER_PAGE_SIZE);
|
||||
const auto address = reinterpret_cast<uint64_t>(memory);
|
||||
bool watched = false;
|
||||
std::barrier phase(worker_count, [&]() noexcept {
|
||||
watched = !watched;
|
||||
Check(Protection(memory) == (watched ? PAGE_READONLY : PAGE_READWRITE),
|
||||
"concurrent watchers lost protection or failed to restore writes");
|
||||
});
|
||||
std::vector<std::jthread> workers;
|
||||
for (size_t i = 0; i < worker_count; i++) {
|
||||
workers.emplace_back([&] {
|
||||
for (size_t round = 0; round < 100; round++) {
|
||||
manager.UpdatePageWatchers<true>(address, TRACKER_PAGE_SIZE);
|
||||
phase.arrive_and_wait();
|
||||
manager.UpdatePageWatchers<false>(address, TRACKER_PAGE_SIZE);
|
||||
phase.arrive_and_wait();
|
||||
}
|
||||
});
|
||||
}
|
||||
for (auto &worker : workers) {
|
||||
worker.join();
|
||||
}
|
||||
Check(VirtualFree(memory, 0, MEM_RELEASE) != 0, "VirtualFree failed");
|
||||
}
|
||||
|
||||
[[noreturn]] void RunDeathCase(const char *name) {
|
||||
PageManager manager;
|
||||
const auto page_size = manager.GetPageSize();
|
||||
@@ -669,6 +704,7 @@ int main(int argc, char **argv) {
|
||||
TestRegionMaskWatcherRanges();
|
||||
TestRegionEndpointBatching();
|
||||
TestReadWriteWatcherInteractions();
|
||||
TestConcurrentSharedWatchers();
|
||||
TestFatalPaths();
|
||||
std::puts("PageManagerTests: all cases passed");
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user