diff --git a/Jenkinsfile b/Jenkinsfile index 4fa420abaa..5173b01b2f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,5 +1,5 @@ #!groovy dependenciesRevision='0dea8bf00d710a5d2da5d04eb5ae595d0df4ce47-1217' strategy='EQUAL' -allowedCD=275 +allowedCD=274 allowedF=4 diff --git a/runtime/memory_manager/host_ptr_manager.cpp b/runtime/memory_manager/host_ptr_manager.cpp index 3ca248e741..1bb8588a0a 100644 --- a/runtime/memory_manager/host_ptr_manager.cpp +++ b/runtime/memory_manager/host_ptr_manager.cpp @@ -7,8 +7,6 @@ #include "runtime/memory_manager/host_ptr_manager.h" -#include "runtime/command_stream/command_stream_receiver.h" -#include "runtime/memory_manager/internal_allocation_storage.h" #include "runtime/memory_manager/memory_manager.h" using namespace NEO; @@ -282,22 +280,14 @@ RequirementsStatus HostPtrManager::checkAllocationsForOverlapping(MemoryManager checkedFragments->fragments[i] = getFragmentAndCheckForOverlaps(requirements->AllocationFragments[i].allocationPtr, requirements->AllocationFragments[i].allocationSize, checkedFragments->status[i]); if (checkedFragments->status[i] == OverlapStatus::FRAGMENT_OVERLAPING_AND_BIGGER_THEN_STORED_FRAGMENT) { // clean temporary allocations - - auto commandStreamReceiver = memoryManager.getDefaultCommandStreamReceiver(0); - auto allocationStorage = commandStreamReceiver->getInternalAllocationStorage(); - uint32_t taskCount = *commandStreamReceiver->getTagAddress(); - allocationStorage->cleanAllocationList(taskCount, TEMPORARY_ALLOCATION); + memoryManager.cleanTemporaryAllocationListOnAllEngines(false); // check overlapping again checkedFragments->fragments[i] = getFragmentAndCheckForOverlaps(requirements->AllocationFragments[i].allocationPtr, requirements->AllocationFragments[i].allocationSize, checkedFragments->status[i]); if (checkedFragments->status[i] == OverlapStatus::FRAGMENT_OVERLAPING_AND_BIGGER_THEN_STORED_FRAGMENT) { // Wait for completion - while (*commandStreamReceiver->getTagAddress() < commandStreamReceiver->peekLatestSentTaskCount()) - ; - - taskCount = *commandStreamReceiver->getTagAddress(); - allocationStorage->cleanAllocationList(taskCount, TEMPORARY_ALLOCATION); + memoryManager.cleanTemporaryAllocationListOnAllEngines(true); // check overlapping last time checkedFragments->fragments[i] = getFragmentAndCheckForOverlaps(requirements->AllocationFragments[i].allocationPtr, requirements->AllocationFragments[i].allocationSize, checkedFragments->status[i]); diff --git a/runtime/memory_manager/memory_manager.cpp b/runtime/memory_manager/memory_manager.cpp index a7a0fd235d..fa17ad7845 100644 --- a/runtime/memory_manager/memory_manager.cpp +++ b/runtime/memory_manager/memory_manager.cpp @@ -439,4 +439,14 @@ void MemoryManager::waitForEnginesCompletion(GraphicsAllocation &graphicsAllocat } } +void MemoryManager::cleanTemporaryAllocationListOnAllEngines(bool waitForCompletion) { + for (auto &engine : getRegisteredEngines()) { + auto csr = engine.commandStreamReceiver; + if (waitForCompletion) { + csr->waitForCompletionWithTimeout(false, 0, csr->peekLatestSentTaskCount()); + } + csr->getInternalAllocationStorage()->cleanAllocationList(*csr->getTagAddress(), AllocationUsage::TEMPORARY_ALLOCATION); + } +} + } // namespace NEO diff --git a/runtime/memory_manager/memory_manager.h b/runtime/memory_manager/memory_manager.h index 23d33dbf88..c2682a29c0 100644 --- a/runtime/memory_manager/memory_manager.h +++ b/runtime/memory_manager/memory_manager.h @@ -165,6 +165,7 @@ class MemoryManager { void waitForDeletions(); void waitForEnginesCompletion(GraphicsAllocation &graphicsAllocation); + void cleanTemporaryAllocationListOnAllEngines(bool waitForCompletion); bool isAsyncDeleterEnabled() const; bool isLocalMemorySupported() const; diff --git a/unit_tests/memory_manager/host_ptr_manager_tests.cpp b/unit_tests/memory_manager/host_ptr_manager_tests.cpp index 7e23314244..a39aa0c844 100644 --- a/unit_tests/memory_manager/host_ptr_manager_tests.cpp +++ b/unit_tests/memory_manager/host_ptr_manager_tests.cpp @@ -5,6 +5,7 @@ * */ +#include "runtime/execution_environment/execution_environment.h" #include "runtime/helpers/aligned_memory.h" #include "runtime/helpers/ptr_math.h" #include "runtime/memory_manager/memory_constants.h" @@ -861,6 +862,61 @@ TEST_F(HostPtrAllocationTest, whenOverlappedFragmentIsBiggerThenStoredAndStoredF } } +HWTEST_F(HostPtrAllocationTest, givenOverlappingFragmentsWhenCheckIsCalledThenWaitAndCleanOnAllEngines) { + uint32_t taskCountReady = 2; + uint32_t taskCountNotReady = 1; + + auto &engines = memoryManager->getRegisteredEngines(); + EXPECT_EQ(1u, engines.size()); + + auto csr0 = static_cast(engines[0].commandStreamReceiver); + auto csr1 = new MockCommandStreamReceiver(executionEnvironment); + uint32_t csr0GpuTag = taskCountNotReady; + uint32_t csr1GpuTag = taskCountNotReady; + csr0->tagAddress = &csr0GpuTag; + csr1->tagAddress = &csr1GpuTag; + executionEnvironment.commandStreamReceivers[0].push_back(std::unique_ptr(csr1)); + auto osContext = memoryManager->createAndRegisterOsContext(csr1, aub_stream::EngineType::ENGINE_RCS, 0, PreemptionMode::Disabled, true); + csr1->setupContext(*osContext); + + void *cpuPtr = reinterpret_cast(0x100004); + + auto hostPtrManager = static_cast(memoryManager->getHostPtrManager()); + auto graphicsAllocation0 = memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{false, MemoryConstants::pageSize}, cpuPtr); + auto graphicsAllocation1 = memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{false, MemoryConstants::pageSize}, cpuPtr); + + auto storage0 = new MockInternalAllocationStorage(*csr0); + auto storage1 = new MockInternalAllocationStorage(*csr1); + csr0->internalAllocationStorage.reset(storage0); + storage0->storeAllocationWithTaskCount(std::unique_ptr(graphicsAllocation0), TEMPORARY_ALLOCATION, taskCountReady); + storage0->updateCompletionAfterCleaningList(taskCountReady); + csr1->internalAllocationStorage.reset(storage1); + storage1->storeAllocationWithTaskCount(std::unique_ptr(graphicsAllocation1), TEMPORARY_ALLOCATION, taskCountReady); + storage1->updateCompletionAfterCleaningList(taskCountReady); + + csr0->setLatestSentTaskCount(taskCountNotReady); + csr1->setLatestSentTaskCount(taskCountNotReady); + + AllocationRequirements requirements; + CheckedFragments checkedFragments; + + requirements.requiredFragmentsCount = 1; + requirements.totalRequiredSize = MemoryConstants::pageSize * 10; + + requirements.AllocationFragments[0].allocationPtr = alignDown(cpuPtr, MemoryConstants::pageSize); + requirements.AllocationFragments[0].allocationSize = MemoryConstants::pageSize * 10; + requirements.AllocationFragments[0].fragmentPosition = FragmentPosition::NONE; + + hostPtrManager->checkAllocationsForOverlapping(*memoryManager, &requirements, &checkedFragments); + + EXPECT_EQ(1u, csr0->waitForCompletionWithTimeoutCalled); + EXPECT_EQ(1u, csr1->waitForCompletionWithTimeoutCalled); + EXPECT_EQ(2u, storage0->cleanAllocationsCalled); + EXPECT_EQ(2u, storage0->lastCleanAllocationsTaskCount); + EXPECT_EQ(2u, storage1->cleanAllocationsCalled); + EXPECT_EQ(2u, storage1->lastCleanAllocationsTaskCount); +} + TEST_F(HostPtrAllocationTest, whenOverlappedFragmentIsBiggerThenStoredAndStoredFragmentCannotBeDestroyedThenCheckForOverlappingReturnsError) { void *cpuPtr1 = (void *)0x100004; diff --git a/unit_tests/mocks/mock_csr.h b/unit_tests/mocks/mock_csr.h index 02dc8885f9..fde3ae3492 100644 --- a/unit_tests/mocks/mock_csr.h +++ b/unit_tests/mocks/mock_csr.h @@ -215,10 +215,15 @@ class MockCommandStreamReceiver : public CommandStreamReceiver { using CommandStreamReceiver::tagAddress; std::vector instructionHeapReserveredData; int *flushBatchedSubmissionsCallCounter = nullptr; + uint32_t waitForCompletionWithTimeoutCalled = 0; ~MockCommandStreamReceiver() { } + bool waitForCompletionWithTimeout(bool enableTimeout, int64_t timeoutMicroseconds, uint32_t taskCountToWait) override { + waitForCompletionWithTimeoutCalled++; + return true; + } FlushStamp flush(BatchBuffer &batchBuffer, ResidencyContainer &allocationsForResidency) override; CompletionStamp flushTask( diff --git a/unit_tests/mocks/mock_internal_allocation_storage.h b/unit_tests/mocks/mock_internal_allocation_storage.h index cc93c36281..673f6a408e 100644 --- a/unit_tests/mocks/mock_internal_allocation_storage.h +++ b/unit_tests/mocks/mock_internal_allocation_storage.h @@ -14,6 +14,8 @@ class MockInternalAllocationStorage : public InternalAllocationStorage { public: using InternalAllocationStorage::InternalAllocationStorage; void cleanAllocationList(uint32_t waitTaskCount, uint32_t allocationUsage) override { + cleanAllocationsCalled++; + lastCleanAllocationsTaskCount = waitTaskCount; InternalAllocationStorage::cleanAllocationList(waitTaskCount, allocationUsage); if (doUpdateCompletion) { *commandStreamReceiver.getTagAddress() = valueToUpdateCompletion; @@ -26,5 +28,7 @@ class MockInternalAllocationStorage : public InternalAllocationStorage { } bool doUpdateCompletion = false; uint32_t valueToUpdateCompletion; + uint32_t lastCleanAllocationsTaskCount = 0; + uint32_t cleanAllocationsCalled = 0; }; } // namespace NEO