Fix multithreading issue in allocation cleanup.
Resolves: NEO-3582 Change-Id: I269fbe8b17cdafa198ed0c89e4b55c15acbc5126 Signed-off-by: Zdunowski, Piotr <piotr.zdunowski@intel.com>
This commit is contained in:
parent
072048105d
commit
41ef3d6ebc
|
@ -8,6 +8,8 @@
|
|||
#pragma once
|
||||
#include "core/memory_manager/graphics_allocation.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace NEO {
|
||||
class CommandStreamReceiver;
|
||||
|
||||
|
@ -15,7 +17,10 @@ class AllocationsList : public IDList<GraphicsAllocation, true, true> {
|
|||
public:
|
||||
std::unique_ptr<GraphicsAllocation> detachAllocation(size_t requiredMinimalSize, CommandStreamReceiver &commandStreamReceiver, GraphicsAllocation::AllocationType allocationType);
|
||||
|
||||
std::unique_lock<std::mutex> obtainUniqueOwnership();
|
||||
|
||||
private:
|
||||
GraphicsAllocation *detachAllocationImpl(GraphicsAllocation *, void *);
|
||||
std::mutex mutex;
|
||||
};
|
||||
} // namespace NEO
|
||||
|
|
|
@ -39,6 +39,7 @@ void InternalAllocationStorage::cleanAllocationList(uint32_t waitTaskCount, uint
|
|||
}
|
||||
|
||||
void InternalAllocationStorage::freeAllocationsList(uint32_t waitTaskCount, AllocationsList &allocationsList) {
|
||||
auto lock = allocationsList.obtainUniqueOwnership();
|
||||
auto memoryManager = commandStreamReceiver.getMemoryManager();
|
||||
GraphicsAllocation *curr = allocationsList.detachNodes();
|
||||
|
||||
|
@ -96,4 +97,8 @@ GraphicsAllocation *AllocationsList::detachAllocationImpl(GraphicsAllocation *,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> AllocationsList::obtainUniqueOwnership() {
|
||||
return std::unique_lock<std::mutex>(mutex);
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "test.h"
|
||||
#include "unit_tests/fixtures/memory_allocator_fixture.h"
|
||||
#include "unit_tests/mocks/mock_allocation_properties.h"
|
||||
#include "unit_tests/mocks/mock_graphics_allocation.h"
|
||||
|
||||
struct InternalAllocationStorageTest : public MemoryAllocatorFixture,
|
||||
public ::testing::Test {
|
||||
|
@ -192,3 +193,52 @@ TEST_F(InternalAllocationStorageTest, givenAllocationWhenItIsPutOnReusableListWh
|
|||
auto internalAllocation = storage->obtainReusableAllocation(1, GraphicsAllocation::AllocationType::INTERNAL_HEAP);
|
||||
EXPECT_EQ(nullptr, internalAllocation);
|
||||
}
|
||||
|
||||
class WaitAtDeletionAllocation : public MockGraphicsAllocation {
|
||||
public:
|
||||
WaitAtDeletionAllocation(void *buffer, size_t sizeIn)
|
||||
: MockGraphicsAllocation(buffer, sizeIn) {
|
||||
inDestructor = false;
|
||||
}
|
||||
|
||||
std::mutex mutex;
|
||||
std::atomic<bool> inDestructor;
|
||||
~WaitAtDeletionAllocation() {
|
||||
inDestructor = true;
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(InternalAllocationStorageTest, givenAllocationListWhenTwoThreadsCleanConcurrentlyThenBothThreadsCanAccessTheList) {
|
||||
auto allocation1 = new WaitAtDeletionAllocation(nullptr, 0);
|
||||
allocation1->updateTaskCount(1, csr->getOsContext().getContextId());
|
||||
storage->storeAllocation(std::unique_ptr<GraphicsAllocation>(allocation1), TEMPORARY_ALLOCATION);
|
||||
|
||||
std::unique_lock<std::mutex> allocationDeletionLock(allocation1->mutex);
|
||||
|
||||
auto allocation2 = memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize});
|
||||
allocation2->updateTaskCount(2, csr->getOsContext().getContextId());
|
||||
storage->storeAllocation(std::unique_ptr<GraphicsAllocation>(allocation2), TEMPORARY_ALLOCATION);
|
||||
|
||||
std::mutex mutex;
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
|
||||
std::thread thread1([&] {
|
||||
storage->cleanAllocationList(1, TEMPORARY_ALLOCATION);
|
||||
});
|
||||
|
||||
std::thread thread2([&] {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
storage->cleanAllocationList(2, TEMPORARY_ALLOCATION);
|
||||
});
|
||||
|
||||
while (!allocation1->inDestructor)
|
||||
;
|
||||
lock.unlock();
|
||||
allocationDeletionLock.unlock();
|
||||
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
|
||||
EXPECT_TRUE(csr->getTemporaryAllocations().peekIsEmpty());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue