diff --git a/runtime/command_queue/enqueue_common.h b/runtime/command_queue/enqueue_common.h index 1190f1674a..faf269fd28 100644 --- a/runtime/command_queue/enqueue_common.h +++ b/runtime/command_queue/enqueue_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -409,7 +409,7 @@ void CommandQueueHw::enqueueHandler(Surface **surfacesForResidency, if (printfHandler) { printfHandler->printEnqueueOutput(); } - commandStreamReceiver.cleanAllocationList(taskCount, TEMPORARY_ALLOCATION); + commandStreamReceiver.waitForTaskCountAndCleanAllocationList(taskCount, TEMPORARY_ALLOCATION); } } } diff --git a/runtime/command_queue/finish.h b/runtime/command_queue/finish.h index 7d74ac7448..67ce3923b2 100644 --- a/runtime/command_queue/finish.h +++ b/runtime/command_queue/finish.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -43,7 +43,7 @@ cl_int CommandQueueHw::finish(bool dcFlush) { // Stall until HW reaches CQ taskCount waitUntilComplete(taskCountToWaitFor, flushStampToWaitFor); - commandStreamReceiver.cleanAllocationList(taskCountToWaitFor, TEMPORARY_ALLOCATION); + commandStreamReceiver.waitForTaskCountAndCleanAllocationList(taskCountToWaitFor, TEMPORARY_ALLOCATION); return CL_SUCCESS; } diff --git a/runtime/command_stream/command_stream_receiver.cpp b/runtime/command_stream/command_stream_receiver.cpp index 4fdc7d6773..56ca02a280 100644 --- a/runtime/command_stream/command_stream_receiver.cpp +++ b/runtime/command_stream/command_stream_receiver.cpp @@ -98,7 +98,7 @@ GraphicsAllocation *CommandStreamReceiver::createAllocationAndHandleResidency(co return graphicsAllocation; } -void CommandStreamReceiver::cleanAllocationList(uint32_t requiredTaskCount, uint32_t allocationType) { +void CommandStreamReceiver::waitForTaskCountAndCleanAllocationList(uint32_t requiredTaskCount, uint32_t allocationType) { auto address = getTagAddress(); if (address && requiredTaskCount != (unsigned int)-1) { @@ -153,6 +153,9 @@ void CommandStreamReceiver::cleanupResources() { if (!memoryManager) return; + waitForTaskCountAndCleanAllocationList(this->latestFlushedTaskCount, TEMPORARY_ALLOCATION); + waitForTaskCountAndCleanAllocationList(this->latestFlushedTaskCount, REUSABLE_ALLOCATION); + if (scratchAllocation) { memoryManager->freeGraphicsMemory(scratchAllocation); scratchAllocation = nullptr; @@ -162,9 +165,6 @@ void CommandStreamReceiver::cleanupResources() { memoryManager->freeGraphicsMemory(preemptionCsrAllocation); } - cleanAllocationList(-1, TEMPORARY_ALLOCATION); - cleanAllocationList(-1, REUSABLE_ALLOCATION); - if (commandStream.getBase()) { memoryManager->freeGraphicsMemory(commandStream.getGraphicsAllocation()); commandStream.replaceGraphicsAllocation(nullptr); @@ -196,7 +196,7 @@ bool CommandStreamReceiver::waitForCompletionWithTimeout(bool enableTimeout, int void CommandStreamReceiver::setTagAllocation(GraphicsAllocation *allocation) { this->tagAllocation = allocation; - this->tagAddress = reinterpret_cast(allocation->getUnderlyingBuffer()); + this->tagAddress = allocation ? reinterpret_cast(allocation->getUnderlyingBuffer()) : nullptr; } void CommandStreamReceiver::setRequiredScratchSize(uint32_t newRequiredScratchSize) { diff --git a/runtime/command_stream/command_stream_receiver.h b/runtime/command_stream/command_stream_receiver.h index cccb64d13f..8fe7320e2b 100644 --- a/runtime/command_stream/command_stream_receiver.h +++ b/runtime/command_stream/command_stream_receiver.h @@ -75,7 +75,7 @@ class CommandStreamReceiver { void setMemoryManager(MemoryManager *mm); GraphicsAllocation *createAllocationAndHandleResidency(const void *address, size_t size, bool addToDefferFreeList = true); - void cleanAllocationList(uint32_t requiredTaskCount, uint32_t allocationType); + void waitForTaskCountAndCleanAllocationList(uint32_t requiredTaskCount, uint32_t allocationType); LinearStream &getCS(size_t minRequiredSize = 1024u); OSInterface *getOSInterface() { return osInterface.get(); }; diff --git a/runtime/device/device.cpp b/runtime/device/device.cpp index 4ca2568b3c..2414fb3c9c 100644 --- a/runtime/device/device.cpp +++ b/runtime/device/device.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -83,14 +83,14 @@ Device::Device(const HardwareInfo &hwInfo, Device::~Device() { DEBUG_BREAK_IF(nullptr == memoryManager); - if (memoryManager) { - memoryManager->freeGraphicsMemory(tagAllocation); - } - tagAllocation = nullptr; if (performanceCounters) { performanceCounters->shutdown(); } delete commandStreamReceiver; + if (memoryManager) { + memoryManager->freeGraphicsMemory(tagAllocation); + } + tagAllocation = nullptr; commandStreamReceiver = nullptr; if (memoryManager) { memoryManager->waitForDeletions(); diff --git a/unit_tests/command_queue/enqueue_thread_tests.cpp b/unit_tests/command_queue/enqueue_thread_tests.cpp index 0e62be8b79..daacec2c37 100644 --- a/unit_tests/command_queue/enqueue_thread_tests.cpp +++ b/unit_tests/command_queue/enqueue_thread_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -509,6 +509,7 @@ HWTEST_F(EnqueueThreading, flushWaitList_ReleaseOwnershipWhenQueueIsBlocked) { pMyDevice->setMemoryManager(memoryManager); auto pTagAllocation = memoryManager->allocateGraphicsMemory(sizeof(uint32_t), sizeof(uint32_t)); + *(uint32_t *)(pTagAllocation->getUnderlyingBuffer()) = initialHardwareTag; ASSERT_NE(nullptr, pTagAllocation); pMyDevice->setTagAllocation(pTagAllocation); diff --git a/unit_tests/command_stream/command_stream_receiver_hw_tests.cpp b/unit_tests/command_stream/command_stream_receiver_hw_tests.cpp index 7ac6c52636..f8fc783c03 100644 --- a/unit_tests/command_stream/command_stream_receiver_hw_tests.cpp +++ b/unit_tests/command_stream/command_stream_receiver_hw_tests.cpp @@ -2823,3 +2823,40 @@ HWTEST_F(CommandStreamReceiverFlushTaskTests, givenCsrInBatchingModeWhenThreeTas auto ppcAfterChange = genCmdCast(ppc3); EXPECT_NE(nullptr, ppcAfterChange); } + +typedef UltCommandStreamReceiverTest CommandStreamReceiverCleanupTests; +HWTEST_F(CommandStreamReceiverFlushTaskTests, givenCsrWhenTemporaryAndReusableAllocationsArePresentThenCleanupResourcesOnlyCleansThoseAboveLatestFlushTaskLevel) { + auto &commandStreamReceiver = pDevice->getUltCommandStreamReceiver(); + auto memoryManager = pDevice->getMemoryManager(); + + auto temporaryToClean = memoryManager->allocateGraphicsMemory(4096u); + auto temporaryToHold = memoryManager->allocateGraphicsMemory(4096u); + + auto reusableToClean = memoryManager->allocateGraphicsMemory(4096u); + auto reusableToHold = memoryManager->allocateGraphicsMemory(4096u); + + memoryManager->storeAllocation(std::unique_ptr(temporaryToClean), TEMPORARY_ALLOCATION); + memoryManager->storeAllocation(std::unique_ptr(temporaryToHold), TEMPORARY_ALLOCATION); + memoryManager->storeAllocation(std::unique_ptr(reusableToClean), REUSABLE_ALLOCATION); + memoryManager->storeAllocation(std::unique_ptr(reusableToHold), REUSABLE_ALLOCATION); + + temporaryToClean->taskCount = 1; + reusableToClean->taskCount = 1; + + temporaryToHold->taskCount = 10; + reusableToHold->taskCount = 10; + + commandStreamReceiver.latestFlushedTaskCount = 9; + commandStreamReceiver.cleanupResources(); + + EXPECT_EQ(reusableToHold, memoryManager->allocationsForReuse.peekHead()); + EXPECT_EQ(reusableToHold, memoryManager->allocationsForReuse.peekTail()); + + EXPECT_EQ(temporaryToHold, memoryManager->graphicsAllocations.peekHead()); + EXPECT_EQ(temporaryToHold, memoryManager->graphicsAllocations.peekTail()); + + commandStreamReceiver.latestFlushedTaskCount = 11; + commandStreamReceiver.cleanupResources(); + EXPECT_TRUE(memoryManager->allocationsForReuse.peekIsEmpty()); + EXPECT_TRUE(memoryManager->graphicsAllocations.peekIsEmpty()); +} \ No newline at end of file diff --git a/unit_tests/event/user_events_tests.cpp b/unit_tests/event/user_events_tests.cpp index 664eb0e432..0ef98d0b4a 100644 --- a/unit_tests/event/user_events_tests.cpp +++ b/unit_tests/event/user_events_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -909,7 +909,7 @@ TEST_F(EventTests, waitForEventsDestroysTemporaryAllocations) { MemoryManager *memoryManager = csr.getMemoryManager(); //kill some temporary objects that fixture creates. - csr.cleanAllocationList(-1, TEMPORARY_ALLOCATION); + csr.waitForTaskCountAndCleanAllocationList(-1, TEMPORARY_ALLOCATION); EXPECT_TRUE(memoryManager->graphicsAllocations.peekIsEmpty()); diff --git a/unit_tests/libult/ult_command_stream_receiver.h b/unit_tests/libult/ult_command_stream_receiver.h index 86b8c3711a..f12917ecb3 100644 --- a/unit_tests/libult/ult_command_stream_receiver.h +++ b/unit_tests/libult/ult_command_stream_receiver.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -46,6 +46,7 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw { using BaseClass::CommandStreamReceiver::lastSentCoherencyRequest; using BaseClass::CommandStreamReceiver::lastSentL3Config; using BaseClass::CommandStreamReceiver::lastSentThreadAribtrationPolicy; + using BaseClass::CommandStreamReceiver::latestFlushedTaskCount; using BaseClass::CommandStreamReceiver::latestSentStatelessMocsConfig; using BaseClass::CommandStreamReceiver::taskCount; using BaseClass::CommandStreamReceiver::taskLevel; @@ -77,16 +78,17 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw { } protected: - using BaseClass::CommandStreamReceiver::cleanAllocationList; using BaseClass::CommandStreamReceiver::memoryManager; using BaseClass::CommandStreamReceiver::tagAddress; using BaseClass::CommandStreamReceiver::tagAllocation; + using BaseClass::CommandStreamReceiver::waitForTaskCountAndCleanAllocationList; GraphicsAllocation *tempTagLocation; }; template UltCommandStreamReceiver::~UltCommandStreamReceiver() { + this->setTagAllocation(nullptr); delete tempTagLocation; } diff --git a/unit_tests/os_interface/linux/device_command_stream_tests.cpp b/unit_tests/os_interface/linux/device_command_stream_tests.cpp index 5956cf5d35..f7ab1ec156 100644 --- a/unit_tests/os_interface/linux/device_command_stream_tests.cpp +++ b/unit_tests/os_interface/linux/device_command_stream_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), diff --git a/unit_tests/os_interface/linux/drm_command_stream_tests.cpp b/unit_tests/os_interface/linux/drm_command_stream_tests.cpp index 06ed3129e3..9d05427ccf 100644 --- a/unit_tests/os_interface/linux/drm_command_stream_tests.cpp +++ b/unit_tests/os_interface/linux/drm_command_stream_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -981,6 +981,7 @@ TEST_F(DrmCommandStreamBatchingTests, givenCsrWhenDispatchPolicyIsSetToBatchingT mm->freeGraphicsMemory(dummyAllocation); mm->freeGraphicsMemory(commandBuffer); mm->freeGraphicsMemory(tagAllocation); + tCsr->setTagAllocation(nullptr); } TEST_F(DrmCommandStreamBatchingTests, givenRecordedCommandBufferWhenItIsSubmittedThenFlushTaskIsProperlyCalled) { @@ -1043,6 +1044,7 @@ TEST_F(DrmCommandStreamBatchingTests, givenRecordedCommandBufferWhenItIsSubmitte mm->freeGraphicsMemory(dummyAllocation); mm->freeGraphicsMemory(commandBuffer); mm->freeGraphicsMemory(tagAllocation); + tCsr->setTagAllocation(nullptr); } typedef Test DrmCommandStreamLeaksTest; diff --git a/unit_tests/os_interface/windows/device_command_stream_tests.cpp b/unit_tests/os_interface/windows/device_command_stream_tests.cpp index ef8ef856de..dd82f0da78 100644 --- a/unit_tests/os_interface/windows/device_command_stream_tests.cpp +++ b/unit_tests/os_interface/windows/device_command_stream_tests.cpp @@ -114,6 +114,8 @@ class WddmCommandStreamWithMockGdiFixture : public WddmFixture { mm->device = device; tagAllocation = mm->allocateGraphicsMemory(1024, 4096); + auto tagBuffer = (uint32_t *)tagAllocation->getUnderlyingBuffer(); + tagBuffer[0] = initialHardwareTag; } void TearDown() { @@ -339,7 +341,7 @@ TEST_F(WddmCommandStreamTest, killAllTemporaryAllocation) { ASSERT_NE(nullptr, graphicsAllocation); graphicsAllocation->taskCount = 1; - csr->cleanAllocationList(-1, TEMPORARY_ALLOCATION); + csr->waitForTaskCountAndCleanAllocationList(-1, TEMPORARY_ALLOCATION); //no memory leaks reported makes this test pass. } @@ -356,7 +358,7 @@ TEST_F(WddmCommandStreamTest, killCompletedAllocations) { graphicsAllocation->taskCount = 1; graphicsAllocation2->taskCount = 100; - csr->cleanAllocationList(1, TEMPORARY_ALLOCATION); + csr->waitForTaskCountAndCleanAllocationList(1, TEMPORARY_ALLOCATION); //graphicsAllocation2 still lives EXPECT_EQ(host_ptr2, graphicsAllocation2->getUnderlyingBuffer());