Implement deferrable allocation deletion

Change-Id: I5e99d1bbb920619f63b71573335dc76f19c796a6
Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski
2018-11-08 14:50:24 +01:00
committed by sys_ocldev
parent 3ad33bf1b8
commit d961bd8354
7 changed files with 169 additions and 0 deletions

View File

@@ -7,6 +7,7 @@
set(IGDRCL_SRCS_tests_memory_manager
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/address_mapper_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/deferrable_allocation_deletion_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/deferred_deleter_mt_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/graphics_allocation_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/host_ptr_manager_tests.cpp

View File

@@ -0,0 +1,103 @@
/*
* Copyright (C) 2017-2018 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "runtime/command_stream/command_stream_receiver.h"
#include "runtime/device/device.h"
#include "runtime/memory_manager/deferred_deleter.h"
#include "runtime/memory_manager/deferrable_allocation_deletion.h"
#include "unit_tests/mocks/mock_memory_manager.h"
#include "gtest/gtest.h"
using namespace OCLRT;
struct DeferredDeleterPublic : DeferredDeleter {
public:
using DeferredDeleter::doWorkInBackground;
using DeferredDeleter::queue;
using DeferredDeleter::queueMutex;
bool shouldStopReached = false;
bool allowExit = false;
bool shouldStop() override {
shouldStopReached = allowExit;
return allowExit;
}
};
struct DeferrableAllocationDeletionTest : ::testing::Test {
void SetUp() override {
auto executionEnvironment = std::make_unique<ExecutionEnvironment>();
memoryManager = new MockMemoryManager(*executionEnvironment);
executionEnvironment->memoryManager.reset(memoryManager);
device.reset(Device::create<Device>(nullptr, executionEnvironment.release(), 0u));
hwTag = device->getTagAddress();
asyncDeleter = std::make_unique<DeferredDeleterPublic>();
asyncDeleter->addClient();
}
void TearDown() override {
asyncDeleter->removeClient();
}
std::unique_ptr<DeferredDeleterPublic> asyncDeleter;
MockMemoryManager *memoryManager = nullptr;
std::unique_ptr<Device> device;
volatile uint32_t *hwTag = nullptr;
};
TEST_F(DeferrableAllocationDeletionTest, givenDeferrableAllocationWhenApplyThenWaitForEachTaskCount) {
EXPECT_EQ(1u, memoryManager->getOsContextCount());
auto allocation = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize);
allocation->updateTaskCount(1u, 0u);
*hwTag = 0u;
asyncDeleter->deferDeletion(new DeferrableAllocationDeletion(*memoryManager, *allocation));
while (!asyncDeleter->queue.peekIsEmpty()) // wait for async thread to get allocation from queue
;
EXPECT_EQ(0u, memoryManager->freeGraphicsMemoryCalled);
EXPECT_TRUE(allocation->isUsedByContext(0u));
// let async thread exit
asyncDeleter->allowExit = true;
*hwTag = 1u; // allow to destroy allocation
while (!asyncDeleter->shouldStopReached)
;
EXPECT_EQ(1u, memoryManager->freeGraphicsMemoryCalled);
}
TEST_F(DeferrableAllocationDeletionTest, givenAllocationUsedByTwoOsContextsWhenApplyDeletionThenWaitForBothContexts) {
std::unique_ptr<Device> secondDevice(Device::create<Device>(nullptr, device->getExecutionEnvironment(), 1u));
EXPECT_EQ(2u, memoryManager->getOsContextCount());
auto allocation = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize);
*hwTag = 0u;
*secondDevice->getTagAddress() = 1u;
allocation->updateTaskCount(1u, 0u);
allocation->updateTaskCount(1u, 1u);
EXPECT_TRUE(allocation->isUsedByContext(0u));
EXPECT_TRUE(allocation->isUsedByContext(1u));
EXPECT_EQ(0u, memoryManager->freeGraphicsMemoryCalled);
asyncDeleter->deferDeletion(new DeferrableAllocationDeletion(*memoryManager, *allocation));
while (allocation->isUsedByContext(1u)) // wait for second context completion signal
;
EXPECT_EQ(0u, memoryManager->freeGraphicsMemoryCalled);
asyncDeleter->allowExit = true;
*hwTag = 1u;
}
TEST_F(DeferrableAllocationDeletionTest, givenNotUsedAllocationWhenApplyDeletionThenDontWait) {
EXPECT_EQ(1u, memoryManager->getOsContextCount());
auto allocation = memoryManager->allocateGraphicsMemory(MemoryConstants::pageSize);
EXPECT_FALSE(allocation->isUsed());
EXPECT_EQ(0u, memoryManager->freeGraphicsMemoryCalled);
while (!asyncDeleter->doWorkInBackground)
; //wait for start async thread work
std::unique_lock<std::mutex> lock(asyncDeleter->queueMutex);
asyncDeleter->allowExit = true;
lock.unlock();
asyncDeleter->deferDeletion(new DeferrableAllocationDeletion(*memoryManager, *allocation));
while (!asyncDeleter->shouldStopReached) // wait async thread job end
;
EXPECT_EQ(1u, memoryManager->freeGraphicsMemoryCalled);
}

View File

@@ -41,6 +41,12 @@ class MockMemoryManager : public OsAgnosticMemoryManager {
GraphicsAllocation *allocateGraphicsMemoryInDevicePool(const AllocationData &allocationData, AllocationStatus &status) override;
GraphicsAllocation *allocateGraphicsMemory(size_t size, size_t alignment, bool forcePin, bool uncacheable) override;
void freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation) override {
freeGraphicsMemoryCalled++;
OsAgnosticMemoryManager::freeGraphicsMemoryImpl(gfxAllocation);
};
uint32_t freeGraphicsMemoryCalled = 0u;
bool allocationCreated = false;
bool allocation64kbPageCreated = false;
bool allocationInDevicePoolCreated = false;