diff options
| author | Jules Blok <jules.blok@gmail.com> | 2015-06-10 00:00:12 +0200 |
|---|---|---|
| committer | Jules Blok <jules.blok@gmail.com> | 2015-06-10 00:00:12 +0200 |
| commit | 7dfced21a2e5aac7195e0e1ad76468e30306766b (patch) | |
| tree | bd671b639d3d911460b767caabad8fc8a759a6bf /Source/UnitTests/Core/PageFaultTest.cpp | |
| parent | c25be031fc1031d795157d8344b87b7841145197 (diff) | |
| parent | 7b0a65e295c784f9d573f2ef52d4e2a7b9bb2889 (diff) | |
Merge branch 'master' into stable
Diffstat (limited to 'Source/UnitTests/Core/PageFaultTest.cpp')
| -rw-r--r-- | Source/UnitTests/Core/PageFaultTest.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/Source/UnitTests/Core/PageFaultTest.cpp b/Source/UnitTests/Core/PageFaultTest.cpp new file mode 100644 index 0000000000..002b5ec866 --- /dev/null +++ b/Source/UnitTests/Core/PageFaultTest.cpp @@ -0,0 +1,81 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include <chrono> + +#include "Common/CommonTypes.h" +#include "Common/Timer.h" +#include "Core/MemTools.h" +#include "Core/PowerPC/JitCommon/JitBase.h" + +// include order is important +#include <gtest/gtest.h> // NOLINT + +#if _M_X86_64 +enum +{ +#ifdef _WIN32 + PAGE_GRAN = 0x10000 +#else + PAGE_GRAN = 0x1000 +#endif +}; + +class PageFaultFakeJit : public JitBase +{ +public: + // CPUCoreBase methods + void Init() override {} + void Shutdown() override {} + void ClearCache() override {} + void Run() override {} + void SingleStep() override {} + const char *GetName() override { return nullptr; } + + // JitBase methods + JitBaseBlockCache *GetBlockCache() override { return nullptr; } + void Jit(u32 em_address) override {} + const CommonAsmRoutinesBase *GetAsmRoutines() override { return nullptr; } + + virtual bool HandleFault(uintptr_t access_address, SContext* ctx) override + { + m_pre_unprotect_time = std::chrono::high_resolution_clock::now(); + UnWriteProtectMemory(m_data, PAGE_GRAN, /*allowExecute*/ false); + m_post_unprotect_time = std::chrono::high_resolution_clock::now(); + return true; + } + + void* m_data; + std::chrono::time_point<std::chrono::high_resolution_clock> + m_pre_unprotect_time, m_post_unprotect_time; +}; + + +TEST(PageFault, PageFault) +{ + EMM::InstallExceptionHandler(); + void* data = AllocateMemoryPages(PAGE_GRAN); + EXPECT_NE(data, nullptr); + WriteProtectMemory(data, PAGE_GRAN, false); + + PageFaultFakeJit pfjit; + jit = &pfjit; + pfjit.m_data = data; + + auto start = std::chrono::high_resolution_clock::now(); + *(volatile int*) data = 5; + auto end = std::chrono::high_resolution_clock::now(); + + #define AS_NS(diff) ((unsigned long long)std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count()) + + EMM::UninstallExceptionHandler(); + jit = nullptr; + + printf("page fault timing:\n"); + printf("start->HandleFault %llu ns\n", AS_NS(pfjit.m_pre_unprotect_time - start)); + printf("UnWriteProtectMemory %llu ns\n", AS_NS(pfjit.m_post_unprotect_time - pfjit.m_pre_unprotect_time)); + printf("HandleFault->end %llu ns\n", AS_NS(end - pfjit.m_post_unprotect_time)); + printf("total %llu ns\n", AS_NS(end - start)); +} +#endif |
