2018-11-28 18:09:56 +08:00
/*
2019-01-07 16:29:49 +08:00
* Copyright ( C ) 2017 - 2019 Intel Corporation
2018-11-28 18:09:56 +08:00
*
* SPDX - License - Identifier : MIT
*
*/
# include "runtime/command_stream/command_stream_receiver.h"
# include "runtime/device/device.h"
# include "runtime/memory_manager/deferrable_allocation_deletion.h"
2019-02-27 18:39:32 +08:00
# include "runtime/memory_manager/deferred_deleter.h"
2018-11-29 18:39:10 +08:00
# include "runtime/os_interface/os_context.h"
2019-01-23 18:59:54 +08:00
# include "runtime/platform/platform.h"
2019-02-27 18:39:32 +08:00
# include "test.h"
2019-01-03 21:48:24 +08:00
# include "unit_tests/libult/ult_command_stream_receiver.h"
2018-12-12 01:56:37 +08:00
# include "unit_tests/mocks/mock_allocation_properties.h"
2019-01-03 21:48:24 +08:00
# include "unit_tests/mocks/mock_device.h"
2018-11-28 18:09:56 +08:00
# include "unit_tests/mocks/mock_memory_manager.h"
2019-03-26 18:59:46 +08:00
using namespace NEO ;
2018-11-28 18:09:56 +08:00
struct DeferredDeleterPublic : DeferredDeleter {
public :
using DeferredDeleter : : doWorkInBackground ;
using DeferredDeleter : : queue ;
using DeferredDeleter : : queueMutex ;
bool shouldStopReached = false ;
bool allowExit = false ;
bool shouldStop ( ) override {
2018-11-29 18:20:02 +08:00
if ( allowExit ) {
EXPECT_TRUE ( queue . peekIsEmpty ( ) ) ;
}
2018-11-28 18:09:56 +08:00
shouldStopReached = allowExit ;
return allowExit ;
}
} ;
struct DeferrableAllocationDeletionTest : : : testing : : Test {
void SetUp ( ) override {
2019-01-23 18:59:54 +08:00
ExecutionEnvironment * executionEnvironment = platformImpl - > peekExecutionEnvironment ( ) ;
2018-11-28 18:09:56 +08:00
memoryManager = new MockMemoryManager ( * executionEnvironment ) ;
executionEnvironment - > memoryManager . reset ( memoryManager ) ;
2019-05-06 18:33:44 +08:00
device . reset ( Device : : create < MockDevice > ( executionEnvironment , 0u ) ) ;
2019-03-04 20:10:10 +08:00
hwTag = device - > getDefaultEngine ( ) . commandStreamReceiver - > getTagAddress ( ) ;
defaultOsContextId = device - > getDefaultEngine ( ) . osContext - > getContextId ( ) ;
2018-11-28 18:09:56 +08:00
asyncDeleter = std : : make_unique < DeferredDeleterPublic > ( ) ;
asyncDeleter - > addClient ( ) ;
}
void TearDown ( ) override {
2018-11-29 18:20:02 +08:00
asyncDeleter - > allowExit = true ;
2018-11-28 18:09:56 +08:00
asyncDeleter - > removeClient ( ) ;
}
std : : unique_ptr < DeferredDeleterPublic > asyncDeleter ;
MockMemoryManager * memoryManager = nullptr ;
2019-03-04 20:10:10 +08:00
std : : unique_ptr < MockDevice > device ;
uint32_t defaultOsContextId = 0 ;
2018-11-28 18:09:56 +08:00
volatile uint32_t * hwTag = nullptr ;
} ;
TEST_F ( DeferrableAllocationDeletionTest , givenDeferrableAllocationWhenApplyThenWaitForEachTaskCount ) {
2018-12-12 01:56:37 +08:00
auto allocation = memoryManager - > allocateGraphicsMemoryWithProperties ( MockAllocationProperties { MemoryConstants : : pageSize } ) ;
2019-03-04 20:10:10 +08:00
allocation - > updateTaskCount ( 1u , defaultOsContextId ) ;
2018-11-28 18:09:56 +08:00
* hwTag = 0u ;
asyncDeleter - > deferDeletion ( new DeferrableAllocationDeletion ( * memoryManager , * allocation ) ) ;
while ( ! asyncDeleter - > queue . peekIsEmpty ( ) ) // wait for async thread to get allocation from queue
std : : this_thread : : yield ( ) ;
EXPECT_EQ ( 0u , memoryManager - > freeGraphicsMemoryCalled ) ;
2019-03-04 20:10:10 +08:00
EXPECT_TRUE ( allocation - > isUsedByOsContext ( defaultOsContextId ) ) ;
2018-11-28 18:09:56 +08:00
// let async thread exit
asyncDeleter - > allowExit = true ;
* hwTag = 1u ; // allow to destroy allocation
while ( ! asyncDeleter - > shouldStopReached )
std : : this_thread : : yield ( ) ;
EXPECT_EQ ( 1u , memoryManager - > freeGraphicsMemoryCalled ) ;
}
2019-01-03 21:48:24 +08:00
HWTEST_F ( DeferrableAllocationDeletionTest , givenAllocationUsedByTwoOsContextsWhenApplyDeletionThenWaitForBothContextsAndFlushNotReadyCsr ) {
2019-11-05 20:38:20 +08:00
auto & nonDefaultCommandStreamReceiver = static_cast < UltCommandStreamReceiver < FamilyType > & > ( * device - > commandStreamReceivers [ 1 ] ) ;
2019-03-04 20:10:10 +08:00
auto nonDefaultOsContextId = nonDefaultCommandStreamReceiver . getOsContext ( ) . getContextId ( ) ;
2018-12-12 01:56:37 +08:00
auto allocation = memoryManager - > allocateGraphicsMemoryWithProperties ( MockAllocationProperties { MemoryConstants : : pageSize } ) ;
2018-11-28 18:09:56 +08:00
* hwTag = 0u ;
2019-03-04 20:10:10 +08:00
* nonDefaultCommandStreamReceiver . getTagAddress ( ) = 1u ;
allocation - > updateTaskCount ( 1u , defaultOsContextId ) ;
allocation - > updateTaskCount ( 1u , nonDefaultOsContextId ) ;
EXPECT_TRUE ( allocation - > isUsedByOsContext ( defaultOsContextId ) ) ;
EXPECT_TRUE ( allocation - > isUsedByOsContext ( nonDefaultOsContextId ) ) ;
2018-11-28 18:09:56 +08:00
EXPECT_EQ ( 0u , memoryManager - > freeGraphicsMemoryCalled ) ;
2019-03-04 20:10:10 +08:00
EXPECT_FALSE ( device - > getUltCommandStreamReceiver < FamilyType > ( ) . flushBatchedSubmissionsCalled ) ;
EXPECT_FALSE ( nonDefaultCommandStreamReceiver . flushBatchedSubmissionsCalled ) ;
2018-11-28 18:09:56 +08:00
asyncDeleter - > deferDeletion ( new DeferrableAllocationDeletion ( * memoryManager , * allocation ) ) ;
2019-03-04 20:10:10 +08:00
while ( allocation - > isUsedByOsContext ( nonDefaultOsContextId ) & & ! device - > getUltCommandStreamReceiver < FamilyType > ( ) . flushBatchedSubmissionsCalled ) // wait for second context completion signal
2018-11-28 18:09:56 +08:00
std : : this_thread : : yield ( ) ;
EXPECT_EQ ( 0u , memoryManager - > freeGraphicsMemoryCalled ) ;
2019-03-04 20:10:10 +08:00
EXPECT_FALSE ( nonDefaultCommandStreamReceiver . flushBatchedSubmissionsCalled ) ;
2018-11-28 18:09:56 +08:00
asyncDeleter - > allowExit = true ;
* hwTag = 1u ;
}
TEST_F ( DeferrableAllocationDeletionTest , givenNotUsedAllocationWhenApplyDeletionThenDontWait ) {
2018-12-12 01:56:37 +08:00
auto allocation = memoryManager - > allocateGraphicsMemoryWithProperties ( MockAllocationProperties { MemoryConstants : : pageSize } ) ;
2018-11-28 18:09:56 +08:00
EXPECT_FALSE ( allocation - > isUsed ( ) ) ;
EXPECT_EQ ( 0u , memoryManager - > freeGraphicsMemoryCalled ) ;
while ( ! asyncDeleter - > doWorkInBackground )
std : : this_thread : : yield ( ) ; //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
std : : this_thread : : yield ( ) ;
EXPECT_EQ ( 1u , memoryManager - > freeGraphicsMemoryCalled ) ;
}
2018-11-29 18:20:02 +08:00
TEST_F ( DeferrableAllocationDeletionTest , givenTwoAllocationsUsedByOneOsContextsEnqueuedToAsyncDeleterWhenOneAllocationIsCompletedThenReleaseThatAllocation ) {
2018-12-12 01:56:37 +08:00
auto allocation1 = memoryManager - > allocateGraphicsMemoryWithProperties ( MockAllocationProperties { MemoryConstants : : pageSize } ) ;
auto allocation2 = memoryManager - > allocateGraphicsMemoryWithProperties ( MockAllocationProperties { MemoryConstants : : pageSize } ) ;
2018-11-29 18:20:02 +08:00
* hwTag = 1u ;
2019-03-04 20:10:10 +08:00
allocation1 - > updateTaskCount ( 2u , defaultOsContextId ) ;
allocation2 - > updateTaskCount ( 1u , defaultOsContextId ) ;
2018-11-29 18:20:02 +08:00
EXPECT_EQ ( 0u , memoryManager - > freeGraphicsMemoryCalled ) ;
EXPECT_TRUE ( allocation1 - > isUsed ( ) ) ;
EXPECT_TRUE ( allocation2 - > isUsed ( ) ) ;
asyncDeleter - > deferDeletion ( new DeferrableAllocationDeletion ( * memoryManager , * allocation1 ) ) ;
asyncDeleter - > deferDeletion ( new DeferrableAllocationDeletion ( * memoryManager , * allocation2 ) ) ;
while ( 0u = = memoryManager - > freeGraphicsMemoryCalled ) // wait for delete second allocation
std : : this_thread : : yield ( ) ;
EXPECT_EQ ( 1u , memoryManager - > freeGraphicsMemoryCalled ) ;
asyncDeleter - > allowExit = true ;
* hwTag = 2u ;
}
TEST_F ( DeferrableAllocationDeletionTest , givenNotCompletedAllocationWhenDeletionIsAppliedThenReturnFalse ) {
2018-12-12 01:56:37 +08:00
auto allocation = memoryManager - > allocateGraphicsMemoryWithProperties ( MockAllocationProperties { MemoryConstants : : pageSize } ) ;
2018-11-29 18:20:02 +08:00
* hwTag = 0u ;
2019-03-04 20:10:10 +08:00
allocation - > updateTaskCount ( 1u , defaultOsContextId ) ;
2018-11-29 18:20:02 +08:00
EXPECT_EQ ( 0u , memoryManager - > freeGraphicsMemoryCalled ) ;
DeferrableAllocationDeletion deletion { * memoryManager , * allocation } ;
EXPECT_FALSE ( deletion . apply ( ) ) ;
EXPECT_EQ ( 0u , memoryManager - > freeGraphicsMemoryCalled ) ;
* hwTag = 1u ; // complete allocation
EXPECT_TRUE ( deletion . apply ( ) ) ;
EXPECT_EQ ( 1u , memoryManager - > freeGraphicsMemoryCalled ) ;
}
TEST_F ( DeferrableAllocationDeletionTest , givenNotUsedAllocationWhenDeletionIsAppliedThenReturnTrue ) {
2018-12-12 01:56:37 +08:00
auto allocation = memoryManager - > allocateGraphicsMemoryWithProperties ( MockAllocationProperties { MemoryConstants : : pageSize } ) ;
2018-11-29 18:20:02 +08:00
EXPECT_FALSE ( allocation - > isUsed ( ) ) ;
DeferrableAllocationDeletion deletion { * memoryManager , * allocation } ;
EXPECT_TRUE ( deletion . apply ( ) ) ;
EXPECT_EQ ( 1u , memoryManager - > freeGraphicsMemoryCalled ) ;
}
2019-11-05 20:13:20 +08:00
TEST_F ( DeferrableAllocationDeletionTest , givenAllocationUsedByUnregisteredEngineWhenDeletionIsAppliedThenReturnTrue ) {
auto allocation = memoryManager - > allocateGraphicsMemoryWithProperties ( MockAllocationProperties { MemoryConstants : : pageSize } ) ;
allocation - > updateTaskCount ( 2u , defaultOsContextId ) ;
EXPECT_TRUE ( allocation - > isUsed ( ) ) ;
DeferrableAllocationDeletion deletion { * memoryManager , * allocation } ;
device . reset ( ) ;
ExecutionEnvironment * executionEnvironment = platformImpl - > peekExecutionEnvironment ( ) ;
executionEnvironment - > rootDeviceEnvironments . clear ( ) ;
EXPECT_EQ ( 0u , memoryManager - > registeredEngines . size ( ) ) ;
EXPECT_TRUE ( allocation - > isUsed ( ) ) ;
memoryManager - > freeGraphicsMemoryCalled = 0u ;
EXPECT_TRUE ( deletion . apply ( ) ) ;
EXPECT_EQ ( 1u , memoryManager - > freeGraphicsMemoryCalled ) ;
}