mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-08 14:02:58 +08:00
feature: capture multiple cpu pagefault handler
Recorded multiple page fault handlers by using vector in cpu_page_fault_manager_linux. Added a static handlerIndex in order to track the depth of handler logic to call appropriate previous handlers. Related-To: NEO-11563 Signed-off-by: Young Jin Yoon <young.jin.yoon@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
f005574f3e
commit
b1f73355ac
@@ -96,14 +96,16 @@ inline void PageFaultManager::migrateStorageToGpuDomain(void *ptr, PageFaultData
|
|||||||
pageFaultData.domain = AllocationDomain::gpu;
|
pageFaultData.domain = AllocationDomain::gpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PageFaultManager::verifyPageFault(void *ptr) {
|
bool PageFaultManager::verifyAndHandlePageFault(void *ptr, bool handlePageFault) {
|
||||||
std::unique_lock<SpinLock> lock{mtx};
|
std::unique_lock<SpinLock> lock{mtx};
|
||||||
for (auto &alloc : this->memoryData) {
|
for (auto &alloc : this->memoryData) {
|
||||||
auto allocPtr = alloc.first;
|
auto allocPtr = alloc.first;
|
||||||
auto &pageFaultData = alloc.second;
|
auto &pageFaultData = alloc.second;
|
||||||
if (ptr >= allocPtr && ptr < ptrOffset(allocPtr, pageFaultData.size)) {
|
if (ptr >= allocPtr && ptr < ptrOffset(allocPtr, pageFaultData.size)) {
|
||||||
this->setAubWritable(true, allocPtr, pageFaultData.unifiedMemoryManager);
|
if (handlePageFault) {
|
||||||
gpuDomainHandler(this, allocPtr, pageFaultData);
|
this->setAubWritable(true, allocPtr, pageFaultData.unifiedMemoryManager);
|
||||||
|
gpuDomainHandler(this, allocPtr, pageFaultData);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class PageFaultManager : public NonCopyableOrMovableClass {
|
|||||||
virtual void evictMemoryAfterImplCopy(GraphicsAllocation *allocation, Device *device) = 0;
|
virtual void evictMemoryAfterImplCopy(GraphicsAllocation *allocation, Device *device) = 0;
|
||||||
virtual void allowCPUMemoryEvictionImpl(bool evict, void *ptr, CommandStreamReceiver &csr, OSInterface *osInterface) = 0;
|
virtual void allowCPUMemoryEvictionImpl(bool evict, void *ptr, CommandStreamReceiver &csr, OSInterface *osInterface) = 0;
|
||||||
|
|
||||||
MOCKABLE_VIRTUAL bool verifyPageFault(void *ptr);
|
MOCKABLE_VIRTUAL bool verifyAndHandlePageFault(void *ptr, bool handlePageFault);
|
||||||
MOCKABLE_VIRTUAL void transferToGpu(void *ptr, void *cmdQ);
|
MOCKABLE_VIRTUAL void transferToGpu(void *ptr, void *cmdQ);
|
||||||
MOCKABLE_VIRTUAL void setAubWritable(bool writable, void *ptr, SVMAllocsManager *unifiedMemoryManager);
|
MOCKABLE_VIRTUAL void setAubWritable(bool writable, void *ptr, SVMAllocsManager *unifiedMemoryManager);
|
||||||
MOCKABLE_VIRTUAL void setCpuAllocEvictable(bool evictable, void *ptr, SVMAllocsManager *unifiedMemoryManager);
|
MOCKABLE_VIRTUAL void setCpuAllocEvictable(bool evictable, void *ptr, SVMAllocsManager *unifiedMemoryManager);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "shared/source/helpers/debug_helpers.h"
|
#include "shared/source/helpers/debug_helpers.h"
|
||||||
#include "shared/source/memory_manager/memory_operations_handler.h"
|
#include "shared/source/memory_manager/memory_operations_handler.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
namespace NEO {
|
namespace NEO {
|
||||||
@@ -35,8 +36,9 @@ PageFaultManagerLinux::PageFaultManagerLinux() {
|
|||||||
|
|
||||||
PageFaultManagerLinux::~PageFaultManagerLinux() {
|
PageFaultManagerLinux::~PageFaultManagerLinux() {
|
||||||
if (!previousHandlerRestored) {
|
if (!previousHandlerRestored) {
|
||||||
auto retVal = sigaction(SIGSEGV, &previousPageFaultHandler, nullptr);
|
auto retVal = sigaction(SIGSEGV, &previousPageFaultHandlers[0], nullptr);
|
||||||
UNRECOVERABLE_IF(retVal != 0);
|
UNRECOVERABLE_IF(retVal != 0);
|
||||||
|
previousPageFaultHandlers.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,8 +49,21 @@ bool PageFaultManagerLinux::checkFaultHandlerFromPageFaultManager() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PageFaultManagerLinux::registerFaultHandler() {
|
void PageFaultManagerLinux::registerFaultHandler() {
|
||||||
|
struct sigaction previousPageFaultHandler = {};
|
||||||
|
auto retVal = sigaction(SIGSEGV, nullptr, &previousPageFaultHandler);
|
||||||
|
UNRECOVERABLE_IF(retVal != 0);
|
||||||
|
|
||||||
|
auto compareHandler = [&ph = previousPageFaultHandler](const struct sigaction &h) -> bool {
|
||||||
|
return (h.sa_flags & SA_SIGINFO) ? (h.sa_sigaction == ph.sa_sigaction) : (h.sa_handler == ph.sa_handler);
|
||||||
|
};
|
||||||
|
if (std::find_if(previousPageFaultHandlers.begin(),
|
||||||
|
previousPageFaultHandlers.end(),
|
||||||
|
compareHandler) == previousPageFaultHandlers.end()) {
|
||||||
|
previousPageFaultHandlers.push_back(previousPageFaultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
pageFaultHandler = [&](int signal, siginfo_t *info, void *context) {
|
pageFaultHandler = [&](int signal, siginfo_t *info, void *context) {
|
||||||
if (!this->verifyPageFault(info->si_addr)) {
|
if (!this->verifyAndHandlePageFault(info->si_addr, this->handlerIndex == 0)) {
|
||||||
callPreviousHandler(signal, info, context);
|
callPreviousHandler(signal, info, context);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -57,7 +72,7 @@ void PageFaultManagerLinux::registerFaultHandler() {
|
|||||||
pageFaultManagerHandler.sa_flags = SA_SIGINFO;
|
pageFaultManagerHandler.sa_flags = SA_SIGINFO;
|
||||||
pageFaultManagerHandler.sa_sigaction = pageFaultHandlerWrapper;
|
pageFaultManagerHandler.sa_sigaction = pageFaultHandlerWrapper;
|
||||||
|
|
||||||
auto retVal = sigaction(SIGSEGV, &pageFaultManagerHandler, &previousPageFaultHandler);
|
retVal = sigaction(SIGSEGV, &pageFaultManagerHandler, &previousPageFaultHandler);
|
||||||
UNRECOVERABLE_IF(retVal != 0);
|
UNRECOVERABLE_IF(retVal != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +91,9 @@ void PageFaultManagerLinux::protectCPUMemoryAccess(void *ptr, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PageFaultManagerLinux::callPreviousHandler(int signal, siginfo_t *info, void *context) {
|
void PageFaultManagerLinux::callPreviousHandler(int signal, siginfo_t *info, void *context) {
|
||||||
|
handlerIndex++;
|
||||||
|
UNRECOVERABLE_IF(handlerIndex < 0 && handlerIndex >= static_cast<int>(previousPageFaultHandlers.size()));
|
||||||
|
auto previousPageFaultHandler = previousPageFaultHandlers[previousPageFaultHandlers.size() - handlerIndex];
|
||||||
if (previousPageFaultHandler.sa_flags & SA_SIGINFO) {
|
if (previousPageFaultHandler.sa_flags & SA_SIGINFO) {
|
||||||
previousPageFaultHandler.sa_sigaction(signal, info, context);
|
previousPageFaultHandler.sa_sigaction(signal, info, context);
|
||||||
} else {
|
} else {
|
||||||
@@ -83,12 +101,12 @@ void PageFaultManagerLinux::callPreviousHandler(int signal, siginfo_t *info, voi
|
|||||||
auto retVal = sigaction(SIGSEGV, &previousPageFaultHandler, nullptr);
|
auto retVal = sigaction(SIGSEGV, &previousPageFaultHandler, nullptr);
|
||||||
UNRECOVERABLE_IF(retVal != 0);
|
UNRECOVERABLE_IF(retVal != 0);
|
||||||
previousHandlerRestored = true;
|
previousHandlerRestored = true;
|
||||||
} else if (previousPageFaultHandler.sa_handler == SIG_IGN) {
|
previousPageFaultHandlers.clear();
|
||||||
return;
|
} else if (previousPageFaultHandler.sa_handler != SIG_IGN) {
|
||||||
} else {
|
|
||||||
previousPageFaultHandler.sa_handler(signal);
|
previousPageFaultHandler.sa_handler(signal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
handlerIndex--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageFaultManagerLinux::evictMemoryAfterImplCopy(GraphicsAllocation *allocation, Device *device) {
|
void PageFaultManagerLinux::evictMemoryAfterImplCopy(GraphicsAllocation *allocation, Device *device) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace NEO {
|
namespace NEO {
|
||||||
class PageFaultManagerLinux : public PageFaultManager {
|
class PageFaultManagerLinux : public PageFaultManager {
|
||||||
@@ -35,8 +36,9 @@ class PageFaultManagerLinux : public PageFaultManager {
|
|||||||
|
|
||||||
static std::function<void(int signal, siginfo_t *info, void *context)> pageFaultHandler;
|
static std::function<void(int signal, siginfo_t *info, void *context)> pageFaultHandler;
|
||||||
|
|
||||||
struct sigaction previousPageFaultHandler = {};
|
std::vector<struct sigaction> previousPageFaultHandlers;
|
||||||
|
|
||||||
bool evictMemoryAfterCopy = false;
|
bool evictMemoryAfterCopy = false;
|
||||||
|
int handlerIndex = 0;
|
||||||
};
|
};
|
||||||
} // namespace NEO
|
} // namespace NEO
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ bool PageFaultManagerWindows::checkFaultHandlerFromPageFaultManager() {
|
|||||||
void PageFaultManagerWindows::registerFaultHandler() {
|
void PageFaultManagerWindows::registerFaultHandler() {
|
||||||
pageFaultHandler = [this](struct _EXCEPTION_POINTERS *exceptionInfo) {
|
pageFaultHandler = [this](struct _EXCEPTION_POINTERS *exceptionInfo) {
|
||||||
if (static_cast<long>(exceptionInfo->ExceptionRecord->ExceptionCode) == EXCEPTION_ACCESS_VIOLATION) {
|
if (static_cast<long>(exceptionInfo->ExceptionRecord->ExceptionCode) == EXCEPTION_ACCESS_VIOLATION) {
|
||||||
if (this->verifyPageFault(reinterpret_cast<void *>(exceptionInfo->ExceptionRecord->ExceptionInformation[1]))) {
|
if (this->verifyAndHandlePageFault(reinterpret_cast<void *>(exceptionInfo->ExceptionRecord->ExceptionInformation[1]), true)) {
|
||||||
// this is our fault that we serviced, continue app execution
|
// this is our fault that we serviced, continue app execution
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ class MockPageFaultManager : public PageFaultManager {
|
|||||||
using PageFaultManager::selectGpuDomainHandler;
|
using PageFaultManager::selectGpuDomainHandler;
|
||||||
using PageFaultManager::transferAndUnprotectMemory;
|
using PageFaultManager::transferAndUnprotectMemory;
|
||||||
using PageFaultManager::unprotectAndTransferMemory;
|
using PageFaultManager::unprotectAndTransferMemory;
|
||||||
using PageFaultManager::verifyPageFault;
|
using PageFaultManager::verifyAndHandlePageFault;
|
||||||
|
|
||||||
bool checkFaultHandlerFromPageFaultManager() override {
|
bool checkFaultHandlerFromPageFaultManager() override {
|
||||||
checkFaultHandlerCalled++;
|
checkFaultHandlerCalled++;
|
||||||
return (registerFaultHandlerCalled != 0);
|
return isFaultHandlerFromPageFaultManager;
|
||||||
}
|
}
|
||||||
void registerFaultHandler() override {
|
void registerFaultHandler() override {
|
||||||
registerFaultHandlerCalled++;
|
registerFaultHandlerCalled++;
|
||||||
@@ -115,6 +115,7 @@ class MockPageFaultManager : public PageFaultManager {
|
|||||||
size_t protectedSize = 0;
|
size_t protectedSize = 0;
|
||||||
bool isAubWritable = true;
|
bool isAubWritable = true;
|
||||||
bool isCpuAllocEvictable = true;
|
bool isCpuAllocEvictable = true;
|
||||||
|
bool isFaultHandlerFromPageFaultManager = false;
|
||||||
aub_stream::EngineType engineType = aub_stream::EngineType::NUM_ENGINES;
|
aub_stream::EngineType engineType = aub_stream::EngineType::NUM_ENGINES;
|
||||||
EngineUsage engineUsage = EngineUsage::engineUsageCount;
|
EngineUsage engineUsage = EngineUsage::engineUsageCount;
|
||||||
};
|
};
|
||||||
@@ -130,8 +131,8 @@ class MockPageFaultManagerHandlerInvoke : public T {
|
|||||||
using T::registerFaultHandler;
|
using T::registerFaultHandler;
|
||||||
using T::T;
|
using T::T;
|
||||||
|
|
||||||
bool verifyPageFault(void *ptr) override {
|
bool verifyAndHandlePageFault(void *ptr, bool handlePageFault) override {
|
||||||
handlerInvoked = true;
|
handlerInvoked = handlePageFault;
|
||||||
if (allowCPUMemoryAccessOnPageFault) {
|
if (allowCPUMemoryAccessOnPageFault) {
|
||||||
this->allowCPUMemoryAccess(ptr, size);
|
this->allowCPUMemoryAccess(ptr, size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,6 +253,8 @@ TEST_F(PageFaultManagerTest, givenUnifiedMemoryAllocWhenMoveToGpuDomainThenTrans
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PageFaultManagerTest, givenUnifiedMemoryAllocWhenMoveToGpuDomainTwiceThenCheckFaultHandlerFromPageFaultManagerReturnsTrue) {
|
TEST_F(PageFaultManagerTest, givenUnifiedMemoryAllocWhenMoveToGpuDomainTwiceThenCheckFaultHandlerFromPageFaultManagerReturnsTrue) {
|
||||||
|
DebugManagerStateRestore restorer;
|
||||||
|
debugManager.flags.RegisterPageFaultHandlerOnMigration.set(true);
|
||||||
void *cmdQ = reinterpret_cast<void *>(0xFFFF);
|
void *cmdQ = reinterpret_cast<void *>(0xFFFF);
|
||||||
void *alloc1 = reinterpret_cast<void *>(0x1);
|
void *alloc1 = reinterpret_cast<void *>(0x1);
|
||||||
void *alloc2 = reinterpret_cast<void *>(0x2);
|
void *alloc2 = reinterpret_cast<void *>(0x2);
|
||||||
@@ -262,7 +264,7 @@ TEST_F(PageFaultManagerTest, givenUnifiedMemoryAllocWhenMoveToGpuDomainTwiceThen
|
|||||||
EXPECT_EQ(pageFaultManager->memoryData.size(), 2u);
|
EXPECT_EQ(pageFaultManager->memoryData.size(), 2u);
|
||||||
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
|
|
||||||
EXPECT_FALSE(pageFaultManager->checkFaultHandlerFromPageFaultManager());
|
pageFaultManager->isFaultHandlerFromPageFaultManager = false;
|
||||||
|
|
||||||
pageFaultManager->moveAllocationToGpuDomain(alloc1);
|
pageFaultManager->moveAllocationToGpuDomain(alloc1);
|
||||||
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 0);
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 0);
|
||||||
@@ -274,7 +276,9 @@ TEST_F(PageFaultManagerTest, givenUnifiedMemoryAllocWhenMoveToGpuDomainTwiceThen
|
|||||||
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
||||||
EXPECT_EQ(pageFaultManager->transferToGpuAddress, alloc1);
|
EXPECT_EQ(pageFaultManager->transferToGpuAddress, alloc1);
|
||||||
|
|
||||||
EXPECT_TRUE(pageFaultManager->checkFaultHandlerFromPageFaultManager());
|
EXPECT_FALSE(pageFaultManager->checkFaultHandlerFromPageFaultManager());
|
||||||
|
|
||||||
|
pageFaultManager->isFaultHandlerFromPageFaultManager = true;
|
||||||
|
|
||||||
pageFaultManager->moveAllocationToGpuDomain(alloc2);
|
pageFaultManager->moveAllocationToGpuDomain(alloc2);
|
||||||
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 0);
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 0);
|
||||||
@@ -289,6 +293,44 @@ TEST_F(PageFaultManagerTest, givenUnifiedMemoryAllocWhenMoveToGpuDomainTwiceThen
|
|||||||
EXPECT_TRUE(pageFaultManager->checkFaultHandlerFromPageFaultManager());
|
EXPECT_TRUE(pageFaultManager->checkFaultHandlerFromPageFaultManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PageFaultManagerTest, givenUnifiedMemoryAllocWhenMoveToGpuDomainTwiceThenRegisterFaultHandlerIsCalledTwice) {
|
||||||
|
DebugManagerStateRestore restorer;
|
||||||
|
debugManager.flags.RegisterPageFaultHandlerOnMigration.set(true);
|
||||||
|
|
||||||
|
void *cmdQ = reinterpret_cast<void *>(0xFFFF);
|
||||||
|
void *alloc1 = reinterpret_cast<void *>(0x1);
|
||||||
|
void *alloc2 = reinterpret_cast<void *>(0x2);
|
||||||
|
|
||||||
|
pageFaultManager->insertAllocation(alloc1, 10u, unifiedMemoryManager.get(), cmdQ, {});
|
||||||
|
pageFaultManager->insertAllocation(alloc2, 20u, unifiedMemoryManager.get(), cmdQ, {});
|
||||||
|
EXPECT_EQ(pageFaultManager->memoryData.size(), 2u);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
|
|
||||||
|
pageFaultManager->isFaultHandlerFromPageFaultManager = false;
|
||||||
|
|
||||||
|
pageFaultManager->moveAllocationToGpuDomain(alloc1);
|
||||||
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 1);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 1);
|
||||||
|
EXPECT_EQ(pageFaultManager->registerFaultHandlerCalled, 1);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectedMemoryAccessAddress, alloc1);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToGpuAddress, alloc1);
|
||||||
|
EXPECT_FALSE(pageFaultManager->checkFaultHandlerFromPageFaultManager());
|
||||||
|
|
||||||
|
pageFaultManager->moveAllocationToGpuDomain(alloc2);
|
||||||
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 2);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 2);
|
||||||
|
EXPECT_EQ(pageFaultManager->registerFaultHandlerCalled, 2);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectedMemoryAccessAddress, alloc2);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectedSize, 20u);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToGpuAddress, alloc2);
|
||||||
|
EXPECT_FALSE(pageFaultManager->checkFaultHandlerFromPageFaultManager());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(PageFaultManagerTest, givenRegisterPageFaultHandlerOnMigrationDisabledWhenMoveToGpuDomainThenDoNotRegisterHandler) {
|
TEST_F(PageFaultManagerTest, givenRegisterPageFaultHandlerOnMigrationDisabledWhenMoveToGpuDomainThenDoNotRegisterHandler) {
|
||||||
DebugManagerStateRestore restorer;
|
DebugManagerStateRestore restorer;
|
||||||
debugManager.flags.RegisterPageFaultHandlerOnMigration.set(false);
|
debugManager.flags.RegisterPageFaultHandlerOnMigration.set(false);
|
||||||
@@ -397,14 +439,17 @@ TEST_F(PageFaultManagerTest, whenMovingToGpuDomainUntrackedAllocThenNothingIsCal
|
|||||||
|
|
||||||
TEST_F(PageFaultManagerTest, givenHandlerRegisteredAndUntrackedPageFaultAddressWhenVerifyingThenFalseIsReturned) {
|
TEST_F(PageFaultManagerTest, givenHandlerRegisteredAndUntrackedPageFaultAddressWhenVerifyingThenFalseIsReturned) {
|
||||||
void *alloc1 = reinterpret_cast<void *>(0x1);
|
void *alloc1 = reinterpret_cast<void *>(0x1);
|
||||||
void *alloc2 = reinterpret_cast<void *>(0x100);
|
void *alloc2 = reinterpret_cast<void *>(0x10);
|
||||||
void *alloc3 = reinterpret_cast<void *>(0x10000);
|
void *alloc3 = reinterpret_cast<void *>(0x100);
|
||||||
|
void *alloc4 = reinterpret_cast<void *>(0x1000);
|
||||||
|
|
||||||
pageFaultManager->insertAllocation(alloc1, 10, unifiedMemoryManager.get(), nullptr, {});
|
pageFaultManager->insertAllocation(alloc2, 10, unifiedMemoryManager.get(), nullptr, {});
|
||||||
pageFaultManager->insertAllocation(alloc2, 20, unifiedMemoryManager.get(), nullptr, {});
|
pageFaultManager->insertAllocation(alloc3, 20, unifiedMemoryManager.get(), nullptr, {});
|
||||||
EXPECT_EQ(pageFaultManager->memoryData.size(), 2u);
|
EXPECT_EQ(pageFaultManager->memoryData.size(), 2u);
|
||||||
|
|
||||||
auto retVal = pageFaultManager->verifyPageFault(alloc3);
|
auto retVal = pageFaultManager->verifyAndHandlePageFault(alloc1, true);
|
||||||
|
EXPECT_FALSE(retVal);
|
||||||
|
retVal = pageFaultManager->verifyAndHandlePageFault(alloc4, true);
|
||||||
EXPECT_FALSE(retVal);
|
EXPECT_FALSE(retVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,7 +462,13 @@ TEST_F(PageFaultManagerTest, givenTrackedPageFaultAddressWhenVerifyingThenProper
|
|||||||
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
EXPECT_EQ(pageFaultManager->memoryData.size(), 2u);
|
EXPECT_EQ(pageFaultManager->memoryData.size(), 2u);
|
||||||
|
|
||||||
pageFaultManager->verifyPageFault(alloc1);
|
pageFaultManager->verifyAndHandlePageFault(alloc1, false);
|
||||||
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
||||||
|
|
||||||
|
pageFaultManager->verifyAndHandlePageFault(alloc1, true);
|
||||||
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
||||||
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 0);
|
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 0);
|
||||||
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
@@ -438,7 +489,7 @@ TEST_F(PageFaultManagerTest, givenInitialPlacementCpuWhenVerifyingPagefaultThenF
|
|||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 1u);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 1u);
|
||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs[0], alloc);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs[0], alloc);
|
||||||
|
|
||||||
pageFaultManager->verifyPageFault(alloc);
|
pageFaultManager->verifyAndHandlePageFault(alloc, true);
|
||||||
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
||||||
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 0);
|
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 0);
|
||||||
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
@@ -464,13 +515,13 @@ TEST_F(PageFaultManagerTest, givenAllocsMovedToGpuDomainWhenVerifyingPageFaultTh
|
|||||||
pageFaultManager->moveAllocationsWithinUMAllocsManagerToGpuDomain(unifiedMemoryManager.get());
|
pageFaultManager->moveAllocationsWithinUMAllocsManagerToGpuDomain(unifiedMemoryManager.get());
|
||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
||||||
|
|
||||||
pageFaultManager->verifyPageFault(alloc2);
|
pageFaultManager->verifyAndHandlePageFault(alloc2, true);
|
||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 1u);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 1u);
|
||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs[0], alloc2);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs[0], alloc2);
|
||||||
|
|
||||||
pageFaultManager->gpuDomainHandler = &MockPageFaultManager::unprotectAndTransferMemory;
|
pageFaultManager->gpuDomainHandler = &MockPageFaultManager::unprotectAndTransferMemory;
|
||||||
|
|
||||||
pageFaultManager->verifyPageFault(alloc1);
|
pageFaultManager->verifyAndHandlePageFault(alloc1, true);
|
||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 2u);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 2u);
|
||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs[1], alloc1);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs[1], alloc1);
|
||||||
}
|
}
|
||||||
@@ -489,13 +540,13 @@ TEST_F(PageFaultManagerTest, givenAllocsFromCpuDomainWhenVerifyingPageFaultThenD
|
|||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
||||||
|
|
||||||
pageFaultManager->memoryData.at(alloc2).domain = PageFaultManager::AllocationDomain::none;
|
pageFaultManager->memoryData.at(alloc2).domain = PageFaultManager::AllocationDomain::none;
|
||||||
pageFaultManager->verifyPageFault(alloc2);
|
pageFaultManager->verifyAndHandlePageFault(alloc2, true);
|
||||||
EXPECT_EQ(pageFaultManager->memoryData.at(alloc2).domain, PageFaultManager::AllocationDomain::cpu);
|
EXPECT_EQ(pageFaultManager->memoryData.at(alloc2).domain, PageFaultManager::AllocationDomain::cpu);
|
||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
||||||
|
|
||||||
pageFaultManager->gpuDomainHandler = &MockPageFaultManager::unprotectAndTransferMemory;
|
pageFaultManager->gpuDomainHandler = &MockPageFaultManager::unprotectAndTransferMemory;
|
||||||
pageFaultManager->memoryData.at(alloc1).domain = PageFaultManager::AllocationDomain::none;
|
pageFaultManager->memoryData.at(alloc1).domain = PageFaultManager::AllocationDomain::none;
|
||||||
pageFaultManager->verifyPageFault(alloc1);
|
pageFaultManager->verifyAndHandlePageFault(alloc1, true);
|
||||||
EXPECT_EQ(pageFaultManager->memoryData.at(alloc1).domain, PageFaultManager::AllocationDomain::cpu);
|
EXPECT_EQ(pageFaultManager->memoryData.at(alloc1).domain, PageFaultManager::AllocationDomain::cpu);
|
||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
||||||
}
|
}
|
||||||
@@ -514,7 +565,7 @@ TEST_F(PageFaultManagerTest, givenTbxWhenVerifyingPagefaultThenVerifyPagefaultUn
|
|||||||
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 1);
|
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 1);
|
||||||
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
||||||
|
|
||||||
pageFaultManager->verifyPageFault(alloc);
|
pageFaultManager->verifyAndHandlePageFault(alloc, true);
|
||||||
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
||||||
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 1);
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 1);
|
||||||
EXPECT_EQ(pageFaultManager->allowedMemoryAccessAddress, alloc);
|
EXPECT_EQ(pageFaultManager->allowedMemoryAccessAddress, alloc);
|
||||||
@@ -541,7 +592,7 @@ TEST_F(PageFaultManagerTest, whenVerifyingPagefaultWithPrintUsmSharedMigrationDe
|
|||||||
EXPECT_EQ(pageFaultManager->protectedMemoryAccessAddress, alloc);
|
EXPECT_EQ(pageFaultManager->protectedMemoryAccessAddress, alloc);
|
||||||
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
||||||
|
|
||||||
pageFaultManager->verifyPageFault(alloc);
|
pageFaultManager->verifyAndHandlePageFault(alloc, true);
|
||||||
|
|
||||||
std::string output = testing::internal::GetCapturedStdout(); // stop capturing
|
std::string output = testing::internal::GetCapturedStdout(); // stop capturing
|
||||||
|
|
||||||
@@ -580,7 +631,7 @@ TEST_F(PageFaultManagerTest, givenTbxWhenVerifyingPagefaultWithPrintUsmSharedMig
|
|||||||
EXPECT_EQ(pageFaultManager->protectedMemoryAccessAddress, alloc);
|
EXPECT_EQ(pageFaultManager->protectedMemoryAccessAddress, alloc);
|
||||||
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
||||||
|
|
||||||
pageFaultManager->verifyPageFault(alloc);
|
pageFaultManager->verifyAndHandlePageFault(alloc, true);
|
||||||
|
|
||||||
std::string output = testing::internal::GetCapturedStdout(); // stop capturing
|
std::string output = testing::internal::GetCapturedStdout(); // stop capturing
|
||||||
|
|
||||||
@@ -614,7 +665,7 @@ TEST_F(PageFaultManagerTest, givenTbxAndInitialPlacementGpuWhenVerifyingPagefaul
|
|||||||
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
||||||
EXPECT_EQ(pageFaultManager->memoryData.size(), 1u);
|
EXPECT_EQ(pageFaultManager->memoryData.size(), 1u);
|
||||||
|
|
||||||
pageFaultManager->verifyPageFault(alloc);
|
pageFaultManager->verifyAndHandlePageFault(alloc, true);
|
||||||
|
|
||||||
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
||||||
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
||||||
@@ -670,7 +721,7 @@ TEST_F(PageFaultManagerTest, givenAllocationMovedToGpuDomainWhenVerifyingPagefau
|
|||||||
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
||||||
|
|
||||||
pageFaultManager->verifyPageFault(alloc);
|
pageFaultManager->verifyAndHandlePageFault(alloc, true);
|
||||||
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
||||||
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 1);
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 1);
|
||||||
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
||||||
@@ -682,6 +733,35 @@ TEST_F(PageFaultManagerTest, givenAllocationMovedToGpuDomainWhenVerifyingPagefau
|
|||||||
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs[0], alloc);
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs[0], alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PageFaultManagerTest, givenAllocationMovedToGpuDomainWhenVerifyingPagefaultWithHandlePageFaultFalseThenAllocationIsNotMovedToCpuDomain) {
|
||||||
|
void *cmdQ = reinterpret_cast<void *>(0xFFFF);
|
||||||
|
void *alloc = reinterpret_cast<void *>(0x1);
|
||||||
|
|
||||||
|
memoryProperties.allocFlags.usmInitialPlacementGpu = 1;
|
||||||
|
pageFaultManager->insertAllocation(alloc, 10, unifiedMemoryManager.get(), cmdQ, memoryProperties);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->memoryData.size(), 1u);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 1);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectedMemoryAccessAddress, alloc);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
||||||
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 1u);
|
||||||
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs[0], alloc);
|
||||||
|
|
||||||
|
pageFaultManager->moveAllocationToGpuDomain(alloc);
|
||||||
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 1);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
||||||
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
||||||
|
|
||||||
|
pageFaultManager->verifyAndHandlePageFault(alloc, false);
|
||||||
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->protectMemoryCalled, 1);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 0);
|
||||||
|
EXPECT_EQ(pageFaultManager->transferToGpuCalled, 0);
|
||||||
|
EXPECT_EQ(unifiedMemoryManager->nonGpuDomainAllocs.size(), 0u);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(PageFaultManagerTest, givenUnifiedMemoryAllocWhenSetAubWritableIsCalledThenAllocIsAubWritable) {
|
TEST_F(PageFaultManagerTest, givenUnifiedMemoryAllocWhenSetAubWritableIsCalledThenAllocIsAubWritable) {
|
||||||
REQUIRE_SVM_OR_SKIP(executionEnvironment.rootDeviceEnvironments[0]->getHardwareInfo());
|
REQUIRE_SVM_OR_SKIP(executionEnvironment.rootDeviceEnvironments[0]->getHardwareInfo());
|
||||||
|
|
||||||
@@ -727,7 +807,7 @@ TEST_F(PageFaultManagerTest, givenUnifiedMemoryAllocWhenMigratedBetweenCpuAndGpu
|
|||||||
EXPECT_EQ(pageFaultManager->protectedMemoryAccessAddress, ptr);
|
EXPECT_EQ(pageFaultManager->protectedMemoryAccessAddress, ptr);
|
||||||
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
EXPECT_EQ(pageFaultManager->protectedSize, 10u);
|
||||||
|
|
||||||
pageFaultManager->verifyPageFault(ptr);
|
pageFaultManager->verifyAndHandlePageFault(ptr, true);
|
||||||
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 1);
|
EXPECT_EQ(pageFaultManager->transferToCpuCalled, 1);
|
||||||
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
EXPECT_EQ(pageFaultManager->allowMemoryAccessCalled, 1);
|
||||||
EXPECT_EQ(pageFaultManager->setCpuAllocEvictableCalled, 2);
|
EXPECT_EQ(pageFaultManager->setCpuAllocEvictableCalled, 2);
|
||||||
|
|||||||
@@ -125,10 +125,14 @@ class MockFailPageFaultManager : public PageFaultManagerLinux {
|
|||||||
using PageFaultManagerLinux::checkFaultHandlerFromPageFaultManager;
|
using PageFaultManagerLinux::checkFaultHandlerFromPageFaultManager;
|
||||||
using PageFaultManagerLinux::PageFaultManagerLinux;
|
using PageFaultManagerLinux::PageFaultManagerLinux;
|
||||||
using PageFaultManagerLinux::previousHandlerRestored;
|
using PageFaultManagerLinux::previousHandlerRestored;
|
||||||
|
using PageFaultManagerLinux::previousPageFaultHandlers;
|
||||||
using PageFaultManagerLinux::registerFaultHandler;
|
using PageFaultManagerLinux::registerFaultHandler;
|
||||||
|
|
||||||
bool verifyPageFault(void *ptr) override {
|
bool verifyAndHandlePageFault(void *ptr, bool handlePageFault) override {
|
||||||
verifyCalled = true;
|
verifyCalled = true;
|
||||||
|
if (handlePageFault) {
|
||||||
|
numPageFaultHandled++;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,22 +140,38 @@ class MockFailPageFaultManager : public PageFaultManagerLinux {
|
|||||||
mockCalled = true;
|
mockCalled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mockPageFaultHandler2(int signal, siginfo_t *info, void *context) {
|
||||||
|
mockCalled2 = true;
|
||||||
|
pageFaultHandlerWrapper(signal, info, context);
|
||||||
|
}
|
||||||
|
|
||||||
static void mockPageFaultSimpleHandler(int signal) {
|
static void mockPageFaultSimpleHandler(int signal) {
|
||||||
simpleMockCalled = true;
|
simpleMockCalled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mockPageFaultSimpleHandler2(int signal) {
|
||||||
|
simpleMockCalled2 = true;
|
||||||
|
}
|
||||||
|
|
||||||
~MockFailPageFaultManager() override {
|
~MockFailPageFaultManager() override {
|
||||||
mockCalled = false;
|
mockCalled = false;
|
||||||
|
mockCalled2 = false;
|
||||||
simpleMockCalled = false;
|
simpleMockCalled = false;
|
||||||
|
simpleMockCalled2 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mockCalled;
|
static bool mockCalled;
|
||||||
|
static bool mockCalled2;
|
||||||
static bool simpleMockCalled;
|
static bool simpleMockCalled;
|
||||||
|
static bool simpleMockCalled2;
|
||||||
bool verifyCalled = false;
|
bool verifyCalled = false;
|
||||||
|
int numPageFaultHandled = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool MockFailPageFaultManager::mockCalled = false;
|
bool MockFailPageFaultManager::mockCalled = false;
|
||||||
|
bool MockFailPageFaultManager::mockCalled2 = false;
|
||||||
bool MockFailPageFaultManager::simpleMockCalled = false;
|
bool MockFailPageFaultManager::simpleMockCalled = false;
|
||||||
|
bool MockFailPageFaultManager::simpleMockCalled2 = false;
|
||||||
|
|
||||||
TEST_F(PageFaultManagerLinuxTest, givenPageFaultThatNEOShouldNotHandleAndSigInfoFlagSetThenSaSigactionIsCalled) {
|
TEST_F(PageFaultManagerLinuxTest, givenPageFaultThatNEOShouldNotHandleAndSigInfoFlagSetThenSaSigactionIsCalled) {
|
||||||
struct sigaction previousHandler = {};
|
struct sigaction previousHandler = {};
|
||||||
@@ -184,6 +204,7 @@ TEST_F(PageFaultManagerLinuxTest, givenPageFaultThatNEOShouldNotHandleThenSaHand
|
|||||||
auto mockPageFaultManager = std::make_unique<MockFailPageFaultManager>();
|
auto mockPageFaultManager = std::make_unique<MockFailPageFaultManager>();
|
||||||
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled);
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_EQ(1ul, mockPageFaultManager->previousPageFaultHandlers.size());
|
||||||
|
|
||||||
std::raise(SIGSEGV);
|
std::raise(SIGSEGV);
|
||||||
EXPECT_TRUE(mockPageFaultManager->verifyCalled);
|
EXPECT_TRUE(mockPageFaultManager->verifyCalled);
|
||||||
@@ -243,3 +264,170 @@ TEST_F(PageFaultManagerLinuxTest, givenDefaultSaHandlerWhenOverwritingNewHandler
|
|||||||
mockPageFaultManager.reset();
|
mockPageFaultManager.reset();
|
||||||
sigaction(SIGSEGV, &originalHandler, nullptr);
|
sigaction(SIGSEGV, &originalHandler, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PageFaultManagerLinuxTest, givenPageFaultThatNEOShouldNotHandleWhenRegisterSimpleHandlerTwiceThenSimpleHandlerIsRegisteredOnce) {
|
||||||
|
struct sigaction previousHandler = {};
|
||||||
|
struct sigaction previousHandler2 = {};
|
||||||
|
struct sigaction mockHandler = {};
|
||||||
|
struct sigaction mockHandler2 = {};
|
||||||
|
mockHandler.sa_handler = MockFailPageFaultManager::mockPageFaultSimpleHandler;
|
||||||
|
auto retVal = sigaction(SIGSEGV, &mockHandler, &previousHandler);
|
||||||
|
EXPECT_EQ(retVal, 0);
|
||||||
|
|
||||||
|
auto mockPageFaultManager = std::make_unique<MockFailPageFaultManager>();
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_EQ(1ul, mockPageFaultManager->previousPageFaultHandlers.size());
|
||||||
|
|
||||||
|
std::raise(SIGSEGV);
|
||||||
|
EXPECT_TRUE(mockPageFaultManager->verifyCalled);
|
||||||
|
EXPECT_EQ(1, mockPageFaultManager->numPageFaultHandled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_TRUE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
|
||||||
|
MockFailPageFaultManager::simpleMockCalled = false;
|
||||||
|
|
||||||
|
mockHandler2.sa_handler = MockFailPageFaultManager::mockPageFaultSimpleHandler;
|
||||||
|
retVal = sigaction(SIGSEGV, &mockHandler2, &previousHandler2);
|
||||||
|
EXPECT_EQ(retVal, 0);
|
||||||
|
mockPageFaultManager->registerFaultHandler();
|
||||||
|
|
||||||
|
std::raise(SIGSEGV);
|
||||||
|
EXPECT_TRUE(mockPageFaultManager->verifyCalled);
|
||||||
|
EXPECT_EQ(2, mockPageFaultManager->numPageFaultHandled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_TRUE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_EQ(1ul, mockPageFaultManager->previousPageFaultHandlers.size());
|
||||||
|
|
||||||
|
mockPageFaultManager.reset();
|
||||||
|
sigaction(SIGSEGV, &previousHandler, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PageFaultManagerLinuxTest, givenPageFaultThatNEOShouldNotHandleWhenRegisterTwoSimpleHandlersThenBothHandlersAreRegistered) {
|
||||||
|
struct sigaction previousHandler = {};
|
||||||
|
struct sigaction previousHandler2 = {};
|
||||||
|
struct sigaction mockHandler = {};
|
||||||
|
struct sigaction mockHandler2 = {};
|
||||||
|
mockHandler.sa_handler = MockFailPageFaultManager::mockPageFaultSimpleHandler;
|
||||||
|
auto retVal = sigaction(SIGSEGV, &mockHandler, &previousHandler);
|
||||||
|
EXPECT_EQ(retVal, 0);
|
||||||
|
|
||||||
|
auto mockPageFaultManager = std::make_unique<MockFailPageFaultManager>();
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled2);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled2);
|
||||||
|
EXPECT_EQ(1ul, mockPageFaultManager->previousPageFaultHandlers.size());
|
||||||
|
|
||||||
|
std::raise(SIGSEGV);
|
||||||
|
EXPECT_TRUE(mockPageFaultManager->verifyCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled2);
|
||||||
|
EXPECT_TRUE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled2);
|
||||||
|
|
||||||
|
MockFailPageFaultManager::simpleMockCalled = false;
|
||||||
|
|
||||||
|
mockHandler2.sa_handler = MockFailPageFaultManager::mockPageFaultSimpleHandler2;
|
||||||
|
retVal = sigaction(SIGSEGV, &mockHandler2, &previousHandler2);
|
||||||
|
EXPECT_EQ(retVal, 0);
|
||||||
|
mockPageFaultManager->registerFaultHandler();
|
||||||
|
|
||||||
|
std::raise(SIGSEGV);
|
||||||
|
EXPECT_TRUE(mockPageFaultManager->verifyCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled2);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_TRUE(MockFailPageFaultManager::simpleMockCalled2);
|
||||||
|
EXPECT_EQ(2ul, mockPageFaultManager->previousPageFaultHandlers.size());
|
||||||
|
|
||||||
|
mockPageFaultManager.reset();
|
||||||
|
sigaction(SIGSEGV, &previousHandler, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PageFaultManagerLinuxTest, givenPageFaultThatNEOShouldNotHandleWhenRegisterTwoHandlersThenBothHandlersAreRegistered) {
|
||||||
|
struct sigaction previousHandler = {};
|
||||||
|
struct sigaction previousHandler2 = {};
|
||||||
|
struct sigaction mockHandler = {};
|
||||||
|
struct sigaction mockHandler2 = {};
|
||||||
|
mockHandler.sa_flags = SA_SIGINFO;
|
||||||
|
mockHandler.sa_sigaction = MockFailPageFaultManager::mockPageFaultHandler;
|
||||||
|
auto retVal = sigaction(SIGSEGV, &mockHandler, &previousHandler);
|
||||||
|
EXPECT_EQ(retVal, 0);
|
||||||
|
|
||||||
|
auto mockPageFaultManager = std::make_unique<MockFailPageFaultManager>();
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled2);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled2);
|
||||||
|
EXPECT_EQ(1ul, mockPageFaultManager->previousPageFaultHandlers.size());
|
||||||
|
|
||||||
|
std::raise(SIGSEGV);
|
||||||
|
EXPECT_TRUE(mockPageFaultManager->verifyCalled);
|
||||||
|
EXPECT_TRUE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled2);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled2);
|
||||||
|
|
||||||
|
MockFailPageFaultManager::mockCalled = false;
|
||||||
|
|
||||||
|
mockHandler2.sa_flags = SA_SIGINFO;
|
||||||
|
mockHandler2.sa_sigaction = MockFailPageFaultManager::mockPageFaultHandler2;
|
||||||
|
retVal = sigaction(SIGSEGV, &mockHandler2, &previousHandler2);
|
||||||
|
EXPECT_EQ(retVal, 0);
|
||||||
|
mockPageFaultManager->registerFaultHandler();
|
||||||
|
|
||||||
|
std::raise(SIGSEGV);
|
||||||
|
EXPECT_TRUE(mockPageFaultManager->verifyCalled);
|
||||||
|
EXPECT_TRUE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_TRUE(MockFailPageFaultManager::mockCalled2);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled2);
|
||||||
|
EXPECT_EQ(2ul, mockPageFaultManager->previousPageFaultHandlers.size());
|
||||||
|
|
||||||
|
mockPageFaultManager.reset();
|
||||||
|
sigaction(SIGSEGV, &previousHandler, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PageFaultManagerLinuxTest, givenPageFaultThatNEOShouldNotHandleWhenRegisterSimpleAndRegularHandlersThenBothHandlersAreRegistered) {
|
||||||
|
struct sigaction previousHandler = {};
|
||||||
|
struct sigaction previousHandler2 = {};
|
||||||
|
struct sigaction mockHandler = {};
|
||||||
|
struct sigaction mockHandler2 = {};
|
||||||
|
mockHandler.sa_handler = MockFailPageFaultManager::mockPageFaultSimpleHandler;
|
||||||
|
auto retVal = sigaction(SIGSEGV, &mockHandler, &previousHandler);
|
||||||
|
EXPECT_EQ(retVal, 0);
|
||||||
|
|
||||||
|
auto mockPageFaultManager = std::make_unique<MockFailPageFaultManager>();
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled2);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled2);
|
||||||
|
EXPECT_EQ(1ul, mockPageFaultManager->previousPageFaultHandlers.size());
|
||||||
|
|
||||||
|
std::raise(SIGSEGV);
|
||||||
|
EXPECT_TRUE(mockPageFaultManager->verifyCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled2);
|
||||||
|
EXPECT_TRUE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled2);
|
||||||
|
|
||||||
|
MockFailPageFaultManager::simpleMockCalled = false;
|
||||||
|
|
||||||
|
mockHandler2.sa_flags = SA_SIGINFO;
|
||||||
|
mockHandler2.sa_sigaction = MockFailPageFaultManager::mockPageFaultHandler2;
|
||||||
|
retVal = sigaction(SIGSEGV, &mockHandler2, &previousHandler2);
|
||||||
|
EXPECT_EQ(retVal, 0);
|
||||||
|
mockPageFaultManager->registerFaultHandler();
|
||||||
|
|
||||||
|
std::raise(SIGSEGV);
|
||||||
|
EXPECT_TRUE(mockPageFaultManager->verifyCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::mockCalled);
|
||||||
|
EXPECT_TRUE(MockFailPageFaultManager::mockCalled2);
|
||||||
|
EXPECT_TRUE(MockFailPageFaultManager::simpleMockCalled);
|
||||||
|
EXPECT_FALSE(MockFailPageFaultManager::simpleMockCalled2);
|
||||||
|
EXPECT_EQ(2ul, mockPageFaultManager->previousPageFaultHandlers.size());
|
||||||
|
|
||||||
|
mockPageFaultManager.reset();
|
||||||
|
sigaction(SIGSEGV, &previousHandler, nullptr);
|
||||||
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class MockFailPageFaultManager : public PageFaultManagerWindows {
|
|||||||
using PageFaultManagerWindows::checkFaultHandlerFromPageFaultManager;
|
using PageFaultManagerWindows::checkFaultHandlerFromPageFaultManager;
|
||||||
using PageFaultManagerWindows::PageFaultManagerWindows;
|
using PageFaultManagerWindows::PageFaultManagerWindows;
|
||||||
|
|
||||||
bool verifyPageFault(void *ptr) override {
|
bool verifyAndHandlePageFault(void *ptr, bool handlePageFault) override {
|
||||||
verifyCalled = true;
|
verifyCalled = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user