From a30c70d84b79e4b1f2d630c9c4ca4a46ae06a9e6 Mon Sep 17 00:00:00 2001 From: Mateusz Jablonski Date: Fri, 26 Oct 2018 11:05:31 +0000 Subject: [PATCH] Remove cleaning allocation lists methods from memory manager Change-Id: I4a58a5373e7dc4cf8dc5d90390e84c4f23689139 Signed-off-by: Mateusz Jablonski --- .../command_stream_receiver.cpp | 6 +- runtime/event/event.cpp | 9 +- runtime/memory_manager/host_ptr_manager.cpp | 8 +- .../internal_allocation_storage.h | 5 +- runtime/memory_manager/memory_manager.cpp | 9 - runtime/memory_manager/memory_manager.h | 4 - .../command_queue/command_queue_hw_tests.cpp | 4 +- .../fixtures/memory_manager_fixture.cpp | 8 +- unit_tests/fixtures/memory_manager_fixture.h | 10 +- .../kernel/substitute_kernel_heap_tests.cpp | 10 +- .../memory_manager/host_ptr_manager_tests.cpp | 202 ++++++++++++++- .../memory_manager/memory_manager_tests.cpp | 240 +----------------- unit_tests/mocks/CMakeLists.txt | 1 + unit_tests/mocks/mock_csr.h | 1 + .../mocks/mock_internal_allocation_storage.h | 30 +++ unit_tests/mocks/mock_memory_manager.h | 4 - 16 files changed, 263 insertions(+), 288 deletions(-) create mode 100644 unit_tests/mocks/mock_internal_allocation_storage.h diff --git a/runtime/command_stream/command_stream_receiver.cpp b/runtime/command_stream/command_stream_receiver.cpp index ac5f857b86..9aec0dffad 100644 --- a/runtime/command_stream/command_stream_receiver.cpp +++ b/runtime/command_stream/command_stream_receiver.cpp @@ -51,10 +51,10 @@ CommandStreamReceiver::~CommandStreamReceiver() { cleanupResources(); if (!allocationsForReuse.peekIsEmpty()) { - getMemoryManager()->freeAllocationsList(-1, allocationsForReuse); + internalAllocationStorage->freeAllocationsList(-1, allocationsForReuse); } if (!temporaryAllocations.peekIsEmpty()) { - getMemoryManager()->freeAllocationsList(-1, temporaryAllocations); + internalAllocationStorage->freeAllocationsList(-1, temporaryAllocations); } } @@ -115,7 +115,7 @@ void CommandStreamReceiver::waitForTaskCountAndCleanAllocationList(uint32_t requ if (allocationList.peekIsEmpty()) { return; } - getMemoryManager()->freeAllocationsList(requiredTaskCount, allocationList); + internalAllocationStorage->freeAllocationsList(requiredTaskCount, allocationList); } MemoryManager *CommandStreamReceiver::getMemoryManager() const { diff --git a/runtime/event/event.cpp b/runtime/event/event.cpp index cf1bc1b994..4937cb3786 100644 --- a/runtime/event/event.cpp +++ b/runtime/event/event.cpp @@ -8,7 +8,7 @@ #include "public/cl_ext_private.h" #include "runtime/command_queue/command_queue.h" #include "runtime/command_stream/command_stream_receiver.h" -#include "runtime/memory_manager/memory_manager.h" +#include "runtime/memory_manager/internal_allocation_storage.h" #include "runtime/context/context.h" #include "runtime/device/device.h" #include "runtime/event/event.h" @@ -310,8 +310,8 @@ inline bool Event::wait(bool blocking, bool useQuickKmdSleep) { DEBUG_BREAK_IF(this->taskLevel == Event::eventNotReady && this->executionStatus >= 0); - auto *memoryManager = cmdQueue->getDevice().getMemoryManager(); - memoryManager->cleanAllocationList(this->taskCount, TEMPORARY_ALLOCATION); + auto *allocationStorage = cmdQueue->getDevice().getCommandStreamReceiver().getInternalAllocationStorage(); + allocationStorage->cleanAllocationList(this->taskCount, TEMPORARY_ALLOCATION); return true; } @@ -346,7 +346,8 @@ void Event::updateExecutionStatus() { transitionExecutionStatus(CL_COMPLETE); executeCallbacks(CL_COMPLETE); unblockEventsBlockedByThis(CL_COMPLETE); - cmdQueue->getDevice().getMemoryManager()->cleanAllocationList(this->taskCount, TEMPORARY_ALLOCATION); + auto *allocationStorage = cmdQueue->getDevice().getCommandStreamReceiver().getInternalAllocationStorage(); + allocationStorage->cleanAllocationList(this->taskCount, TEMPORARY_ALLOCATION); return; } diff --git a/runtime/memory_manager/host_ptr_manager.cpp b/runtime/memory_manager/host_ptr_manager.cpp index 65aecedcc2..0e88f0ddc7 100644 --- a/runtime/memory_manager/host_ptr_manager.cpp +++ b/runtime/memory_manager/host_ptr_manager.cpp @@ -7,6 +7,7 @@ #include "runtime/command_stream/command_stream_receiver.h" #include "runtime/memory_manager/host_ptr_manager.h" +#include "runtime/memory_manager/internal_allocation_storage.h" #include "runtime/memory_manager/memory_manager.h" using namespace OCLRT; @@ -282,8 +283,9 @@ RequirementsStatus HostPtrManager::checkAllocationsForOverlapping(MemoryManager // clean temporary allocations auto commandStreamReceiver = memoryManager.getCommandStreamReceiver(0); + auto allocationStorage = commandStreamReceiver->getInternalAllocationStorage(); uint32_t taskCount = *commandStreamReceiver->getTagAddress(); - memoryManager.cleanAllocationList(taskCount, TEMPORARY_ALLOCATION); + allocationStorage->cleanAllocationList(taskCount, TEMPORARY_ALLOCATION); // check overlapping again checkedFragments->fragments[i] = getFragmentAndCheckForOverlaps(requirements->AllocationFragments[i].allocationPtr, requirements->AllocationFragments[i].allocationSize, checkedFragments->status[i]); @@ -294,7 +296,7 @@ RequirementsStatus HostPtrManager::checkAllocationsForOverlapping(MemoryManager ; taskCount = *commandStreamReceiver->getTagAddress(); - memoryManager.cleanAllocationList(taskCount, TEMPORARY_ALLOCATION); + allocationStorage->cleanAllocationList(taskCount, TEMPORARY_ALLOCATION); // check overlapping last time checkedFragments->fragments[i] = getFragmentAndCheckForOverlaps(requirements->AllocationFragments[i].allocationPtr, requirements->AllocationFragments[i].allocationSize, checkedFragments->status[i]); @@ -306,4 +308,4 @@ RequirementsStatus HostPtrManager::checkAllocationsForOverlapping(MemoryManager } } return status; -} \ No newline at end of file +} diff --git a/runtime/memory_manager/internal_allocation_storage.h b/runtime/memory_manager/internal_allocation_storage.h index 5438f6b5da..efb95dba82 100644 --- a/runtime/memory_manager/internal_allocation_storage.h +++ b/runtime/memory_manager/internal_allocation_storage.h @@ -17,14 +17,15 @@ class GraphicsAllocation; class InternalAllocationStorage { public: + MOCKABLE_VIRTUAL ~InternalAllocationStorage() = default; InternalAllocationStorage(CommandStreamReceiver &commandStreamReceiver); - void cleanAllocationList(uint32_t waitTaskCount, uint32_t allocationUsage); + MOCKABLE_VIRTUAL void cleanAllocationList(uint32_t waitTaskCount, uint32_t allocationUsage); void freeAllocationsList(uint32_t waitTaskCount, AllocationsList &allocationsList); void storeAllocation(std::unique_ptr gfxAllocation, uint32_t allocationUsage); void storeAllocationWithTaskCount(std::unique_ptr gfxAllocation, uint32_t allocationUsage, uint32_t taskCount); std::unique_ptr obtainReusableAllocation(size_t requiredSize, bool isInternalAllocationRequired); - private: + protected: std::recursive_mutex mutex; CommandStreamReceiver &commandStreamReceiver; }; diff --git a/runtime/memory_manager/memory_manager.cpp b/runtime/memory_manager/memory_manager.cpp index 692a87f5e0..bf375c522a 100644 --- a/runtime/memory_manager/memory_manager.cpp +++ b/runtime/memory_manager/memory_manager.cpp @@ -171,15 +171,6 @@ void MemoryManager::applyCommonCleanup() { } } -bool MemoryManager::cleanAllocationList(uint32_t waitTaskCount, uint32_t allocationUsage) { - getCommandStreamReceiver(0)->getInternalAllocationStorage()->cleanAllocationList(waitTaskCount, allocationUsage); - return false; -} - -void MemoryManager::freeAllocationsList(uint32_t waitTaskCount, AllocationsList &allocationsList) { - getCommandStreamReceiver(0)->getInternalAllocationStorage()->freeAllocationsList(waitTaskCount, allocationsList); -} - TagAllocator *MemoryManager::getEventTsAllocator() { if (profilingTimeStampAllocator.get() == nullptr) { profilingTimeStampAllocator = std::make_unique>(this, TagCount, MemoryConstants::cacheLineSize); diff --git a/runtime/memory_manager/memory_manager.h b/runtime/memory_manager/memory_manager.h index 171c052807..93578e1dd2 100644 --- a/runtime/memory_manager/memory_manager.h +++ b/runtime/memory_manager/memory_manager.h @@ -200,10 +200,6 @@ class MemoryManager { virtual uint64_t getInternalHeapBaseAddress() = 0; - virtual bool cleanAllocationList(uint32_t waitTaskCount, uint32_t allocationUsage); - - void freeAllocationsList(uint32_t waitTaskCount, AllocationsList &allocationsList); - TagAllocator *getEventTsAllocator(); TagAllocator *getEventPerfCountAllocator(); TagAllocator *getTimestampPacketAllocator(); diff --git a/unit_tests/command_queue/command_queue_hw_tests.cpp b/unit_tests/command_queue/command_queue_hw_tests.cpp index eddef677ba..d81a056581 100644 --- a/unit_tests/command_queue/command_queue_hw_tests.cpp +++ b/unit_tests/command_queue/command_queue_hw_tests.cpp @@ -1053,7 +1053,7 @@ HWTEST_F(CommandQueueHwTest, givenReadOnlyHostPointerWhenAllocationForHostSurfac EXPECT_NE(memory, allocation->getUnderlyingBuffer()); EXPECT_THAT(allocation->getUnderlyingBuffer(), MemCompare(memory, size)); - gmockMemoryManager->cleanAllocationList(-1, TEMPORARY_ALLOCATION); + allocation->taskCount = device->getCommandStreamReceiver().peekLatestFlushedTaskCount(); mockCmdQ->release(); mockContext->release(); } @@ -1091,7 +1091,6 @@ HWTEST_F(CommandQueueHwTest, givenReadOnlyHostPointerWhenAllocationForHostSurfac auto allocation = surface.getAllocation(); EXPECT_EQ(nullptr, allocation); - gmockMemoryManager->cleanAllocationList(-1, TEMPORARY_ALLOCATION); mockCmdQ->release(); mockContext->release(); } @@ -1117,7 +1116,6 @@ struct ReducedAddrSpaceCommandQueueHwTest : public CommandQueueHwTest { void TearDown() override { CommandQueueHwTest::TearDown(); - gmockMemoryManager->cleanAllocationList(-1, TEMPORARY_ALLOCATION); mockContext->release(); } }; diff --git a/unit_tests/fixtures/memory_manager_fixture.cpp b/unit_tests/fixtures/memory_manager_fixture.cpp index 37cbcde30d..4578fbcfc1 100644 --- a/unit_tests/fixtures/memory_manager_fixture.cpp +++ b/unit_tests/fixtures/memory_manager_fixture.cpp @@ -10,17 +10,11 @@ #include "unit_tests/mocks/mock_memory_manager.h" using namespace OCLRT; -using ::testing::NiceMock; void MemoryManagerWithCsrFixture::SetUp() { csr = new MockCommandStreamReceiver(this->executionEnvironment); - gmockMemoryManager = new NiceMock(executionEnvironment); - memoryManager = gmockMemoryManager; + memoryManager = new MockMemoryManager(executionEnvironment); executionEnvironment.memoryManager.reset(memoryManager); - - ON_CALL(*gmockMemoryManager, cleanAllocationList(::testing::_, ::testing::_)).WillByDefault(::testing::Invoke(gmockMemoryManager, &GMockMemoryManager::MemoryManagerCleanAllocationList)); - ON_CALL(*gmockMemoryManager, populateOsHandles(::testing::_)).WillByDefault(::testing::Invoke(gmockMemoryManager, &GMockMemoryManager::MemoryManagerPopulateOsHandles)); - csr->tagAddress = ¤tGpuTag; executionEnvironment.commandStreamReceivers.push_back(std::unique_ptr(csr)); } diff --git a/unit_tests/fixtures/memory_manager_fixture.h b/unit_tests/fixtures/memory_manager_fixture.h index c774680512..225dca8566 100644 --- a/unit_tests/fixtures/memory_manager_fixture.h +++ b/unit_tests/fixtures/memory_manager_fixture.h @@ -6,19 +6,19 @@ */ #pragma once -#include "unit_tests/mocks/mock_csr.h" +#include "runtime/execution_environment/execution_environment.h" +#include "runtime/helpers/options.h" using namespace OCLRT; +class MockCommandStreamReceiver; namespace OCLRT { -class MemoryManager; -class GMockMemoryManager; +class MockMemoryManager; }; // namespace OCLRT class MemoryManagerWithCsrFixture { public: - MemoryManager *memoryManager; - GMockMemoryManager *gmockMemoryManager; + MockMemoryManager *memoryManager; ExecutionEnvironment executionEnvironment; MockCommandStreamReceiver *csr; uint32_t taskCount = 0; diff --git a/unit_tests/kernel/substitute_kernel_heap_tests.cpp b/unit_tests/kernel/substitute_kernel_heap_tests.cpp index 8201f79494..54a715385b 100644 --- a/unit_tests/kernel/substitute_kernel_heap_tests.cpp +++ b/unit_tests/kernel/substitute_kernel_heap_tests.cpp @@ -5,6 +5,7 @@ * */ +#include "runtime/memory_manager/internal_allocation_storage.h" #include "unit_tests/fixtures/device_fixture.h" #include "unit_tests/mocks/mock_kernel.h" #include "test.h" @@ -108,6 +109,7 @@ TEST_F(KernelSubstituteTest, givenKernelWithUsedKernelAllocationWhenSubstituteKe MockKernelWithInternals kernel(*pDevice); auto pHeader = const_cast(kernel.kernelInfo.heapInfo.pKernelHeader); auto memoryManager = pDevice->getMemoryManager(); + auto &commandStreamReceiver = pDevice->getCommandStreamReceiver(); const size_t initialHeapSize = 0x40; pHeader->KernelHeapSize = initialHeapSize; @@ -120,13 +122,13 @@ TEST_F(KernelSubstituteTest, givenKernelWithUsedKernelAllocationWhenSubstituteKe const size_t newHeapSize = initialHeapSize + 1; char newHeap[newHeapSize]; - EXPECT_TRUE(memoryManager->getCommandStreamReceiver(0)->getTemporaryAllocations().peekIsEmpty()); + EXPECT_TRUE(commandStreamReceiver.getTemporaryAllocations().peekIsEmpty()); kernel.mockKernel->substituteKernelHeap(newHeap, newHeapSize); auto secondAllocation = kernel.kernelInfo.kernelAllocation; - EXPECT_FALSE(memoryManager->getCommandStreamReceiver(0)->getTemporaryAllocations().peekIsEmpty()); - EXPECT_EQ(memoryManager->getCommandStreamReceiver(0)->getTemporaryAllocations().peekHead(), firstAllocation); + EXPECT_FALSE(commandStreamReceiver.getTemporaryAllocations().peekIsEmpty()); + EXPECT_EQ(commandStreamReceiver.getTemporaryAllocations().peekHead(), firstAllocation); memoryManager->checkGpuUsageAndDestroyGraphicsAllocations(secondAllocation); - memoryManager->cleanAllocationList(firstAllocation->taskCount, TEMPORARY_ALLOCATION); + commandStreamReceiver.getInternalAllocationStorage()->cleanAllocationList(firstAllocation->taskCount, TEMPORARY_ALLOCATION); } diff --git a/unit_tests/memory_manager/host_ptr_manager_tests.cpp b/unit_tests/memory_manager/host_ptr_manager_tests.cpp index 845f83c2af..f0a3c6aadb 100644 --- a/unit_tests/memory_manager/host_ptr_manager_tests.cpp +++ b/unit_tests/memory_manager/host_ptr_manager_tests.cpp @@ -11,6 +11,9 @@ #include "unit_tests/fixtures/memory_manager_fixture.h" #include "unit_tests/gen_common/test.h" #include "unit_tests/mocks/mock_host_ptr_manager.h" +#include "unit_tests/mocks/mock_internal_allocation_storage.h" +#include "unit_tests/mocks/mock_memory_manager.h" +#include "unit_tests/mocks/mock_csr.h" using namespace OCLRT; @@ -807,4 +810,201 @@ TEST_F(HostPtrAllocationTest, whenPrepareOsHandlesForAllocationThenPopulateAsMan memoryManager->cleanOsHandles(osStorage); EXPECT_EQ(0u, hostPtrManager->getFragmentCount()); } -} \ No newline at end of file +} + +TEST_F(HostPtrAllocationTest, whenOverlappedFragmentIsBiggerThenStoredAndStoredFragmentIsDestroyedDuringSecondCleaningThenCheckForOverlappingReturnsSuccess) { + + void *cpuPtr1 = (void *)0x100004; + + auto hostPtrManager = static_cast(memoryManager->getHostPtrManager()); + auto graphicsAllocation1 = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize, cpuPtr1); + EXPECT_EQ(2u, hostPtrManager->getFragmentCount()); + + EXPECT_NE(nullptr, graphicsAllocation1); + + auto fragment1 = hostPtrManager->getFragment(alignDown(cpuPtr1, MemoryConstants::pageSize)); + EXPECT_NE(nullptr, fragment1); + auto fragment2 = hostPtrManager->getFragment(alignUp(cpuPtr1, MemoryConstants::pageSize)); + EXPECT_NE(nullptr, fragment2); + + uint32_t taskCountReady = 2; + auto storage = new MockInternalAllocationStorage(*csr); + csr->internalAllocationStorage.reset(storage); + storage->storeAllocationWithTaskCount(std::unique_ptr(graphicsAllocation1), TEMPORARY_ALLOCATION, taskCountReady); + storage->updateCompletionAfterCleaningList(taskCountReady); + + // All fragments ready for release + currentGpuTag = 1; + csr->latestSentTaskCount = taskCountReady - 1; + + AllocationRequirements requirements; + CheckedFragments checkedFragments; + + requirements.requiredFragmentsCount = 1; + requirements.totalRequiredSize = MemoryConstants::pageSize * 10; + + requirements.AllocationFragments[0].allocationPtr = alignDown(cpuPtr1, MemoryConstants::pageSize); + requirements.AllocationFragments[0].allocationSize = MemoryConstants::pageSize * 10; + requirements.AllocationFragments[0].fragmentPosition = FragmentPosition::NONE; + + RequirementsStatus status = hostPtrManager->checkAllocationsForOverlapping(*memoryManager, &requirements, &checkedFragments); + + EXPECT_EQ(RequirementsStatus::SUCCESS, status); + EXPECT_EQ(1u, checkedFragments.count); + EXPECT_EQ(OverlapStatus::FRAGMENT_NOT_OVERLAPING_WITH_ANY_OTHER, checkedFragments.status[0]); + EXPECT_EQ(nullptr, checkedFragments.fragments[0]); + + for (uint32_t i = 1; i < maxFragmentsCount; i++) { + EXPECT_EQ(OverlapStatus::FRAGMENT_NOT_CHECKED, checkedFragments.status[i]); + EXPECT_EQ(nullptr, checkedFragments.fragments[i]); + } +} + +TEST_F(HostPtrAllocationTest, whenOverlappedFragmentIsBiggerThenStoredAndStoredFragmentCannotBeDestroyedThenCheckForOverlappingReturnsError) { + + void *cpuPtr1 = (void *)0x100004; + + auto hostPtrManager = static_cast(memoryManager->getHostPtrManager()); + auto graphicsAllocation1 = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize, cpuPtr1); + EXPECT_EQ(2u, hostPtrManager->getFragmentCount()); + + EXPECT_NE(nullptr, graphicsAllocation1); + + auto fragment1 = hostPtrManager->getFragment(alignDown(cpuPtr1, MemoryConstants::pageSize)); + EXPECT_NE(nullptr, fragment1); + auto fragment2 = hostPtrManager->getFragment(alignUp(cpuPtr1, MemoryConstants::pageSize)); + EXPECT_NE(nullptr, fragment2); + + uint32_t taskCountReady = 2; + auto storage = csr->getInternalAllocationStorage(); + storage->storeAllocationWithTaskCount(std::unique_ptr(graphicsAllocation1), TEMPORARY_ALLOCATION, taskCountReady); + + // All fragments ready for release + currentGpuTag = taskCountReady - 1; + csr->latestSentTaskCount = taskCountReady - 1; + + AllocationRequirements requirements; + CheckedFragments checkedFragments; + + requirements.requiredFragmentsCount = 1; + requirements.totalRequiredSize = MemoryConstants::pageSize * 10; + + requirements.AllocationFragments[0].allocationPtr = alignDown(cpuPtr1, MemoryConstants::pageSize); + requirements.AllocationFragments[0].allocationSize = MemoryConstants::pageSize * 10; + requirements.AllocationFragments[0].fragmentPosition = FragmentPosition::NONE; + + RequirementsStatus status = hostPtrManager->checkAllocationsForOverlapping(*memoryManager, &requirements, &checkedFragments); + + EXPECT_EQ(RequirementsStatus::FATAL, status); + EXPECT_EQ(1u, checkedFragments.count); + EXPECT_EQ(OverlapStatus::FRAGMENT_OVERLAPING_AND_BIGGER_THEN_STORED_FRAGMENT, checkedFragments.status[0]); + EXPECT_EQ(nullptr, checkedFragments.fragments[0]); + + for (uint32_t i = 1; i < maxFragmentsCount; i++) { + EXPECT_EQ(OverlapStatus::FRAGMENT_NOT_CHECKED, checkedFragments.status[i]); + EXPECT_EQ(nullptr, checkedFragments.fragments[i]); + } +} + +TEST_F(HostPtrAllocationTest, checkAllocationsForOverlappingWithoutBiggerOverlap) { + + void *cpuPtr1 = (void *)0x100004; + void *cpuPtr2 = (void *)0x101008; + + auto hostPtrManager = static_cast(memoryManager->getHostPtrManager()); + auto graphicsAllocation1 = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize, cpuPtr1); + EXPECT_EQ(2u, hostPtrManager->getFragmentCount()); + + auto graphicsAllocation2 = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize * 3, cpuPtr2); + EXPECT_EQ(4u, hostPtrManager->getFragmentCount()); + + EXPECT_NE(nullptr, graphicsAllocation1); + EXPECT_NE(nullptr, graphicsAllocation2); + + auto fragment1 = hostPtrManager->getFragment(alignDown(cpuPtr1, MemoryConstants::pageSize)); + EXPECT_NE(nullptr, fragment1); + auto fragment2 = hostPtrManager->getFragment(alignUp(cpuPtr1, MemoryConstants::pageSize)); + EXPECT_NE(nullptr, fragment2); + auto fragment3 = hostPtrManager->getFragment(alignDown(cpuPtr2, MemoryConstants::pageSize)); + EXPECT_NE(nullptr, fragment3); + auto fragment4 = hostPtrManager->getFragment(alignUp(cpuPtr2, MemoryConstants::pageSize)); + EXPECT_NE(nullptr, fragment4); + + AllocationRequirements requirements; + CheckedFragments checkedFragments; + + requirements.requiredFragmentsCount = 2; + requirements.totalRequiredSize = MemoryConstants::pageSize * 2; + + requirements.AllocationFragments[0].allocationPtr = alignDown(cpuPtr1, MemoryConstants::pageSize); + requirements.AllocationFragments[0].allocationSize = MemoryConstants::pageSize; + requirements.AllocationFragments[0].fragmentPosition = FragmentPosition::LEADING; + + requirements.AllocationFragments[1].allocationPtr = alignUp(cpuPtr1, MemoryConstants::pageSize); + requirements.AllocationFragments[1].allocationSize = MemoryConstants::pageSize; + requirements.AllocationFragments[1].fragmentPosition = FragmentPosition::TRAILING; + + RequirementsStatus status = hostPtrManager->checkAllocationsForOverlapping(*memoryManager, &requirements, &checkedFragments); + + EXPECT_EQ(RequirementsStatus::SUCCESS, status); + EXPECT_EQ(2u, checkedFragments.count); + + EXPECT_EQ(OverlapStatus::FRAGMENT_WITH_EXACT_SIZE_AS_STORED_FRAGMENT, checkedFragments.status[0]); + EXPECT_EQ(alignDown(cpuPtr1, MemoryConstants::pageSize), checkedFragments.fragments[0]->fragmentCpuPointer); + EXPECT_EQ(MemoryConstants::pageSize, checkedFragments.fragments[0]->fragmentSize); + EXPECT_EQ(1, checkedFragments.fragments[0]->refCount); + + EXPECT_EQ(OverlapStatus::FRAGMENT_WITH_EXACT_SIZE_AS_STORED_FRAGMENT, checkedFragments.status[1]); + EXPECT_EQ(alignUp(cpuPtr1, MemoryConstants::pageSize), checkedFragments.fragments[1]->fragmentCpuPointer); + EXPECT_EQ(MemoryConstants::pageSize, checkedFragments.fragments[1]->fragmentSize); + EXPECT_EQ(2, checkedFragments.fragments[1]->refCount); + + memoryManager->freeGraphicsMemory(graphicsAllocation1); + memoryManager->freeGraphicsMemory(graphicsAllocation2); +} + +TEST_F(HostPtrAllocationTest, checkAllocationsForOverlappingWithBiggerOverlapUntilFirstClean) { + + void *cpuPtr1 = (void *)0x100004; + + auto graphicsAllocation1 = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize, cpuPtr1); + auto hostPtrManager = static_cast(memoryManager->getHostPtrManager()); + EXPECT_EQ(2u, hostPtrManager->getFragmentCount()); + + EXPECT_NE(nullptr, graphicsAllocation1); + + auto fragment1 = hostPtrManager->getFragment(alignDown(cpuPtr1, MemoryConstants::pageSize)); + EXPECT_NE(nullptr, fragment1); + auto fragment2 = hostPtrManager->getFragment(alignUp(cpuPtr1, MemoryConstants::pageSize)); + EXPECT_NE(nullptr, fragment2); + + uint32_t taskCountReady = 1; + auto storage = csr->getInternalAllocationStorage(); + storage->storeAllocationWithTaskCount(std::unique_ptr(graphicsAllocation1), TEMPORARY_ALLOCATION, taskCountReady); + + // All fragments ready for release + taskCount = taskCountReady; + csr->latestSentTaskCount = taskCountReady; + + AllocationRequirements requirements; + CheckedFragments checkedFragments; + + requirements.requiredFragmentsCount = 1; + requirements.totalRequiredSize = MemoryConstants::pageSize * 10; + + requirements.AllocationFragments[0].allocationPtr = alignDown(cpuPtr1, MemoryConstants::pageSize); + requirements.AllocationFragments[0].allocationSize = MemoryConstants::pageSize * 10; + requirements.AllocationFragments[0].fragmentPosition = FragmentPosition::NONE; + + RequirementsStatus status = hostPtrManager->checkAllocationsForOverlapping(*memoryManager, &requirements, &checkedFragments); + + EXPECT_EQ(RequirementsStatus::SUCCESS, status); + EXPECT_EQ(1u, checkedFragments.count); + EXPECT_EQ(OverlapStatus::FRAGMENT_NOT_OVERLAPING_WITH_ANY_OTHER, checkedFragments.status[0]); + EXPECT_EQ(nullptr, checkedFragments.fragments[0]); + + for (uint32_t i = 1; i < maxFragmentsCount; i++) { + EXPECT_EQ(OverlapStatus::FRAGMENT_NOT_CHECKED, checkedFragments.status[i]); + EXPECT_EQ(nullptr, checkedFragments.fragments[i]); + } +} diff --git a/unit_tests/memory_manager/memory_manager_tests.cpp b/unit_tests/memory_manager/memory_manager_tests.cpp index a44b6b959f..79beed4573 100644 --- a/unit_tests/memory_manager/memory_manager_tests.cpp +++ b/unit_tests/memory_manager/memory_manager_tests.cpp @@ -24,6 +24,7 @@ #include "unit_tests/helpers/memory_management.h" #include "unit_tests/helpers/variable_backup.h" #include "unit_tests/mocks/mock_context.h" +#include "unit_tests/mocks/mock_csr.h" #include "unit_tests/mocks/mock_deferrable_deletion.h" #include "unit_tests/mocks/mock_deferred_deleter.h" #include "unit_tests/mocks/mock_device.h" @@ -228,31 +229,6 @@ TEST_F(MemoryAllocatorTest, allocateGraphicsMoreThanPageAligned) { memoryManager->freeGraphicsMemory(allocation); } -TEST_F(MemoryAllocatorTest, givenMemoryManagerWhenCleanTempoaryAllocationsThenUseFirstCommandStreamReceiver) { - void *host_ptr = (void *)0x1234; - auto allocation = memoryManager->allocateGraphicsMemory(1, host_ptr); - allocation->taskCount = 1; - auto csr = memoryManager->getCommandStreamReceiver(0); - EXPECT_TRUE(csr->getTemporaryAllocations().peekIsEmpty()); - - csr->getInternalAllocationStorage()->storeAllocation(std::unique_ptr(allocation), TEMPORARY_ALLOCATION); - EXPECT_FALSE(csr->getTemporaryAllocations().peekIsEmpty()); - memoryManager->cleanAllocationList(1, TEMPORARY_ALLOCATION); - EXPECT_TRUE(csr->getTemporaryAllocations().peekIsEmpty()); -} - -TEST_F(MemoryAllocatorTest, givenMemoryManagerWhenCleanReusableAllocationsThenUseFirstCommandStreamReceiver) { - void *host_ptr = (void *)0x1234; - auto allocation = memoryManager->allocateGraphicsMemory(1, host_ptr); - allocation->taskCount = 1; - auto csr = memoryManager->getCommandStreamReceiver(0); - EXPECT_TRUE(csr->getAllocationsForReuse().peekIsEmpty()); - csr->getInternalAllocationStorage()->storeAllocation(std::unique_ptr(allocation), REUSABLE_ALLOCATION); - EXPECT_FALSE(csr->getAllocationsForReuse().peekIsEmpty()); - memoryManager->cleanAllocationList(1, REUSABLE_ALLOCATION); - EXPECT_TRUE(csr->getAllocationsForReuse().peekIsEmpty()); -} - TEST_F(MemoryAllocatorTest, AlignedHostPtrWithAlignedSizeWhenAskedForGraphicsAllocationReturnsNullStorageFromHostPtrManager) { auto ptr = (void *)0x1000; MockMemoryManager mockMemoryManager(*executionEnvironment); @@ -1219,220 +1195,6 @@ TEST_F(MemoryManagerWithCsrTest, GivenAllocationsInHostPtrManagerReadyForCleanin memoryManager->freeGraphicsMemory(graphicsAllocation3); } -TEST_F(MemoryManagerWithCsrTest, checkAllocationsForOverlappingWithoutBiggerOverlap) { - - void *cpuPtr1 = (void *)0x100004; - void *cpuPtr2 = (void *)0x101008; - - auto hostPtrManager = static_cast(memoryManager->getHostPtrManager()); - auto graphicsAllocation1 = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize, cpuPtr1); - EXPECT_EQ(2u, hostPtrManager->getFragmentCount()); - - auto graphicsAllocation2 = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize * 3, cpuPtr2); - EXPECT_EQ(4u, hostPtrManager->getFragmentCount()); - - EXPECT_NE(nullptr, graphicsAllocation1); - EXPECT_NE(nullptr, graphicsAllocation2); - - auto fragment1 = hostPtrManager->getFragment(alignDown(cpuPtr1, MemoryConstants::pageSize)); - EXPECT_NE(nullptr, fragment1); - auto fragment2 = hostPtrManager->getFragment(alignUp(cpuPtr1, MemoryConstants::pageSize)); - EXPECT_NE(nullptr, fragment2); - auto fragment3 = hostPtrManager->getFragment(alignDown(cpuPtr2, MemoryConstants::pageSize)); - EXPECT_NE(nullptr, fragment3); - auto fragment4 = hostPtrManager->getFragment(alignUp(cpuPtr2, MemoryConstants::pageSize)); - EXPECT_NE(nullptr, fragment4); - - AllocationRequirements requirements; - CheckedFragments checkedFragments; - - requirements.requiredFragmentsCount = 2; - requirements.totalRequiredSize = MemoryConstants::pageSize * 2; - - requirements.AllocationFragments[0].allocationPtr = alignDown(cpuPtr1, MemoryConstants::pageSize); - requirements.AllocationFragments[0].allocationSize = MemoryConstants::pageSize; - requirements.AllocationFragments[0].fragmentPosition = FragmentPosition::LEADING; - - requirements.AllocationFragments[1].allocationPtr = alignUp(cpuPtr1, MemoryConstants::pageSize); - requirements.AllocationFragments[1].allocationSize = MemoryConstants::pageSize; - requirements.AllocationFragments[1].fragmentPosition = FragmentPosition::TRAILING; - - RequirementsStatus status = hostPtrManager->checkAllocationsForOverlapping(*memoryManager, &requirements, &checkedFragments); - - EXPECT_EQ(RequirementsStatus::SUCCESS, status); - EXPECT_EQ(2u, checkedFragments.count); - - EXPECT_EQ(OverlapStatus::FRAGMENT_WITH_EXACT_SIZE_AS_STORED_FRAGMENT, checkedFragments.status[0]); - EXPECT_EQ(alignDown(cpuPtr1, MemoryConstants::pageSize), checkedFragments.fragments[0]->fragmentCpuPointer); - EXPECT_EQ(MemoryConstants::pageSize, checkedFragments.fragments[0]->fragmentSize); - EXPECT_EQ(1, checkedFragments.fragments[0]->refCount); - - EXPECT_EQ(OverlapStatus::FRAGMENT_WITH_EXACT_SIZE_AS_STORED_FRAGMENT, checkedFragments.status[1]); - EXPECT_EQ(alignUp(cpuPtr1, MemoryConstants::pageSize), checkedFragments.fragments[1]->fragmentCpuPointer); - EXPECT_EQ(MemoryConstants::pageSize, checkedFragments.fragments[1]->fragmentSize); - EXPECT_EQ(2, checkedFragments.fragments[1]->refCount); - - memoryManager->freeGraphicsMemory(graphicsAllocation1); - memoryManager->freeGraphicsMemory(graphicsAllocation2); -} - -TEST_F(MemoryManagerWithCsrTest, checkAllocationsForOverlappingWithBiggerOverlapUntilFirstClean) { - - void *cpuPtr1 = (void *)0x100004; - - auto graphicsAllocation1 = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize, cpuPtr1); - auto hostPtrManager = static_cast(memoryManager->getHostPtrManager()); - EXPECT_EQ(2u, hostPtrManager->getFragmentCount()); - - EXPECT_NE(nullptr, graphicsAllocation1); - - auto fragment1 = hostPtrManager->getFragment(alignDown(cpuPtr1, MemoryConstants::pageSize)); - EXPECT_NE(nullptr, fragment1); - auto fragment2 = hostPtrManager->getFragment(alignUp(cpuPtr1, MemoryConstants::pageSize)); - EXPECT_NE(nullptr, fragment2); - - uint32_t taskCountReady = 1; - auto storage = csr->getInternalAllocationStorage(); - storage->storeAllocationWithTaskCount(std::unique_ptr(graphicsAllocation1), TEMPORARY_ALLOCATION, taskCountReady); - - // All fragments ready for release - taskCount = taskCountReady; - csr->latestSentTaskCount = taskCountReady; - - AllocationRequirements requirements; - CheckedFragments checkedFragments; - - requirements.requiredFragmentsCount = 1; - requirements.totalRequiredSize = MemoryConstants::pageSize * 10; - - requirements.AllocationFragments[0].allocationPtr = alignDown(cpuPtr1, MemoryConstants::pageSize); - requirements.AllocationFragments[0].allocationSize = MemoryConstants::pageSize * 10; - requirements.AllocationFragments[0].fragmentPosition = FragmentPosition::NONE; - - RequirementsStatus status = hostPtrManager->checkAllocationsForOverlapping(*memoryManager, &requirements, &checkedFragments); - - EXPECT_EQ(RequirementsStatus::SUCCESS, status); - EXPECT_EQ(1u, checkedFragments.count); - EXPECT_EQ(OverlapStatus::FRAGMENT_NOT_OVERLAPING_WITH_ANY_OTHER, checkedFragments.status[0]); - EXPECT_EQ(nullptr, checkedFragments.fragments[0]); - - for (uint32_t i = 1; i < maxFragmentsCount; i++) { - EXPECT_EQ(OverlapStatus::FRAGMENT_NOT_CHECKED, checkedFragments.status[i]); - EXPECT_EQ(nullptr, checkedFragments.fragments[i]); - } -} - -TEST_F(MemoryManagerWithCsrTest, checkAllocationsForOverlappingWithBiggerOverlapUntilWaitForCompletionAndSecondClean) { - - void *cpuPtr1 = (void *)0x100004; - - auto hostPtrManager = static_cast(memoryManager->getHostPtrManager()); - auto graphicsAllocation1 = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize, cpuPtr1); - EXPECT_EQ(2u, hostPtrManager->getFragmentCount()); - - EXPECT_NE(nullptr, graphicsAllocation1); - - auto fragment1 = hostPtrManager->getFragment(alignDown(cpuPtr1, MemoryConstants::pageSize)); - EXPECT_NE(nullptr, fragment1); - auto fragment2 = hostPtrManager->getFragment(alignUp(cpuPtr1, MemoryConstants::pageSize)); - EXPECT_NE(nullptr, fragment2); - - uint32_t taskCountReady = 2; - auto storage = csr->getInternalAllocationStorage(); - storage->storeAllocationWithTaskCount(std::unique_ptr(graphicsAllocation1), TEMPORARY_ALLOCATION, taskCountReady); - - // All fragments ready for release - currentGpuTag = 1; - csr->latestSentTaskCount = taskCountReady - 1; - - AllocationRequirements requirements; - CheckedFragments checkedFragments; - - requirements.requiredFragmentsCount = 1; - requirements.totalRequiredSize = MemoryConstants::pageSize * 10; - - requirements.AllocationFragments[0].allocationPtr = alignDown(cpuPtr1, MemoryConstants::pageSize); - requirements.AllocationFragments[0].allocationSize = MemoryConstants::pageSize * 10; - requirements.AllocationFragments[0].fragmentPosition = FragmentPosition::NONE; - - GMockMemoryManager *memMngr = gmockMemoryManager; - - auto cleanAllocations = [memMngr](uint32_t waitTaskCount, uint32_t allocationUsage) -> bool { - return memMngr->MemoryManagerCleanAllocationList(waitTaskCount, allocationUsage); - }; - - auto cleanAllocationsWithTaskCount = [taskCountReady, memMngr](uint32_t waitTaskCount, uint32_t allocationUsage) -> bool { - return memMngr->MemoryManagerCleanAllocationList(taskCountReady, allocationUsage); - }; - - EXPECT_CALL(*gmockMemoryManager, cleanAllocationList(::testing::_, ::testing::_)).Times(2).WillOnce(::testing::Invoke(cleanAllocations)).WillOnce(::testing::Invoke(cleanAllocationsWithTaskCount)); - - RequirementsStatus status = hostPtrManager->checkAllocationsForOverlapping(*memoryManager, &requirements, &checkedFragments); - - EXPECT_EQ(RequirementsStatus::SUCCESS, status); - EXPECT_EQ(1u, checkedFragments.count); - EXPECT_EQ(OverlapStatus::FRAGMENT_NOT_OVERLAPING_WITH_ANY_OTHER, checkedFragments.status[0]); - EXPECT_EQ(nullptr, checkedFragments.fragments[0]); - - for (uint32_t i = 1; i < maxFragmentsCount; i++) { - EXPECT_EQ(OverlapStatus::FRAGMENT_NOT_CHECKED, checkedFragments.status[i]); - EXPECT_EQ(nullptr, checkedFragments.fragments[i]); - } -} - -TEST_F(MemoryManagerWithCsrTest, checkAllocationsForOverlappingWithBiggerOverlapForever) { - - void *cpuPtr1 = (void *)0x100004; - - auto hostPtrManager = static_cast(memoryManager->getHostPtrManager()); - auto graphicsAllocation1 = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize, cpuPtr1); - EXPECT_EQ(2u, hostPtrManager->getFragmentCount()); - - EXPECT_NE(nullptr, graphicsAllocation1); - - auto fragment1 = hostPtrManager->getFragment(alignDown(cpuPtr1, MemoryConstants::pageSize)); - EXPECT_NE(nullptr, fragment1); - auto fragment2 = hostPtrManager->getFragment(alignUp(cpuPtr1, MemoryConstants::pageSize)); - EXPECT_NE(nullptr, fragment2); - - uint32_t taskCountReady = 2; - auto storage = csr->getInternalAllocationStorage(); - storage->storeAllocationWithTaskCount(std::unique_ptr(graphicsAllocation1), TEMPORARY_ALLOCATION, taskCountReady); - - // All fragments ready for release - currentGpuTag = taskCountReady - 1; - csr->latestSentTaskCount = taskCountReady - 1; - - AllocationRequirements requirements; - CheckedFragments checkedFragments; - - requirements.requiredFragmentsCount = 1; - requirements.totalRequiredSize = MemoryConstants::pageSize * 10; - - requirements.AllocationFragments[0].allocationPtr = alignDown(cpuPtr1, MemoryConstants::pageSize); - requirements.AllocationFragments[0].allocationSize = MemoryConstants::pageSize * 10; - requirements.AllocationFragments[0].fragmentPosition = FragmentPosition::NONE; - - GMockMemoryManager *memMngr = gmockMemoryManager; - - auto cleanAllocations = [memMngr](uint32_t waitTaskCount, uint32_t allocationUsage) -> bool { - return memMngr->MemoryManagerCleanAllocationList(waitTaskCount, allocationUsage); - }; - - EXPECT_CALL(*gmockMemoryManager, cleanAllocationList(::testing::_, ::testing::_)).Times(2).WillRepeatedly(::testing::Invoke(cleanAllocations)); - - RequirementsStatus status = hostPtrManager->checkAllocationsForOverlapping(*memoryManager, &requirements, &checkedFragments); - - EXPECT_EQ(RequirementsStatus::FATAL, status); - EXPECT_EQ(1u, checkedFragments.count); - EXPECT_EQ(OverlapStatus::FRAGMENT_OVERLAPING_AND_BIGGER_THEN_STORED_FRAGMENT, checkedFragments.status[0]); - EXPECT_EQ(nullptr, checkedFragments.fragments[0]); - - for (uint32_t i = 1; i < maxFragmentsCount; i++) { - EXPECT_EQ(OverlapStatus::FRAGMENT_NOT_CHECKED, checkedFragments.status[i]); - EXPECT_EQ(nullptr, checkedFragments.fragments[i]); - } -} TEST_F(MemoryManagerWithCsrTest, givenAllocationThatWasNotUsedWhencheckGpuUsageAndDestroyGraphicsAllocationsIsCalledThenItIsDestroyedInPlace) { auto notUsedAllocation = memoryManager->allocateGraphicsMemory(4096); memoryManager->checkGpuUsageAndDestroyGraphicsAllocations(notUsedAllocation); diff --git a/unit_tests/mocks/CMakeLists.txt b/unit_tests/mocks/CMakeLists.txt index 3939eeddf5..26bd95f790 100644 --- a/unit_tests/mocks/CMakeLists.txt +++ b/unit_tests/mocks/CMakeLists.txt @@ -43,6 +43,7 @@ set(IGDRCL_SRCS_tests_mocks ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/mock_gmm_client_context.cpp ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/mock_gmm_client_context.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_host_ptr_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/mock_internal_allocation_storage.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_image.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_kernel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mock_kernel.h diff --git a/unit_tests/mocks/mock_csr.h b/unit_tests/mocks/mock_csr.h index aeaf22ec40..3770295ff4 100644 --- a/unit_tests/mocks/mock_csr.h +++ b/unit_tests/mocks/mock_csr.h @@ -209,6 +209,7 @@ class MockFlatBatchBufferHelper : public FlatBatchBufferHelperHw { class MockCommandStreamReceiver : public CommandStreamReceiver { public: using CommandStreamReceiver::CommandStreamReceiver; + using CommandStreamReceiver::internalAllocationStorage; using CommandStreamReceiver::latestFlushedTaskCount; using CommandStreamReceiver::latestSentTaskCount; using CommandStreamReceiver::tagAddress; diff --git a/unit_tests/mocks/mock_internal_allocation_storage.h b/unit_tests/mocks/mock_internal_allocation_storage.h new file mode 100644 index 0000000000..4707407ab8 --- /dev/null +++ b/unit_tests/mocks/mock_internal_allocation_storage.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "runtime/command_stream/command_stream_receiver.h" +#include "runtime/memory_manager/internal_allocation_storage.h" + +namespace OCLRT { +class MockInternalAllocationStorage : public InternalAllocationStorage { + public: + using InternalAllocationStorage::InternalAllocationStorage; + void cleanAllocationList(uint32_t waitTaskCount, uint32_t allocationUsage) override { + InternalAllocationStorage::cleanAllocationList(waitTaskCount, allocationUsage); + if (doUpdateCompletion) { + *commandStreamReceiver.getTagAddress() = valueToUpdateCompletion; + doUpdateCompletion = false; + } + } + void updateCompletionAfterCleaningList(uint32_t newValue) { + doUpdateCompletion = true; + valueToUpdateCompletion = newValue; + } + bool doUpdateCompletion = false; + uint32_t valueToUpdateCompletion; +}; +} // namespace OCLRT diff --git a/unit_tests/mocks/mock_memory_manager.h b/unit_tests/mocks/mock_memory_manager.h index db581c7595..8d4ea77852 100644 --- a/unit_tests/mocks/mock_memory_manager.h +++ b/unit_tests/mocks/mock_memory_manager.h @@ -55,13 +55,9 @@ class MockMemoryManager : public OsAgnosticMemoryManager { class GMockMemoryManager : public MockMemoryManager { public: GMockMemoryManager(const ExecutionEnvironment &executionEnvironment) : MockMemoryManager(const_cast(executionEnvironment)){}; - MOCK_METHOD2(cleanAllocationList, bool(uint32_t waitTaskCount, uint32_t allocationUsage)); - // cleanAllocationList call defined in MemoryManager. - MOCK_METHOD1(populateOsHandles, MemoryManager::AllocationStatus(OsHandleStorage &handleStorage)); MOCK_METHOD2(allocateGraphicsMemoryForNonSvmHostPtr, GraphicsAllocation *(size_t, void *)); - bool MemoryManagerCleanAllocationList(uint32_t waitTaskCount, uint32_t allocationUsage) { return MemoryManager::cleanAllocationList(waitTaskCount, allocationUsage); } MemoryManager::AllocationStatus MemoryManagerPopulateOsHandles(OsHandleStorage &handleStorage) { return OsAgnosticMemoryManager::populateOsHandles(handleStorage); } };