Add refcount on MemObj in blocked scenarios.

- Prevents destruction of MemObj while it may still be in use.
- Add UNRECOVERABLE to check whether object is deleted while having
dependencies, fix all problems is tests due to that fact.
- Fix special queue setting, clean interfaces.

Change-Id: I2a467e80df00ea1650decdcfa6866acf10b441f8
This commit is contained in:
Mrozek, Michal
2018-01-05 11:33:30 +01:00
committed by sys_ocldev
parent c838a7dfc6
commit b00819cafe
24 changed files with 247 additions and 160 deletions

View File

@@ -64,7 +64,12 @@ void CommandQueueHwFixture::SetUp(
}
void CommandQueueHwFixture::TearDown() {
delete pCmdQ;
//resolve event dependencies
if (pCmdQ) {
auto blocked = pCmdQ->isQueueBlocked();
UNRECOVERABLE_IF(blocked);
pCmdQ->release();
}
context->release();
}

View File

@@ -121,6 +121,29 @@ HWTEST_F(CommandQueueHwTest, addMapUnmapToWaitlistEventsDependenciesCreateVirtua
pHwQ->virtualEvent = nullptr;
}
HWTEST_F(CommandQueueHwTest, givenBlockedMapBufferCallWhenMemObjectIsPassedToCommandThenItsRefCountIsBeingIncreased) {
CommandQueueHw<FamilyType> *pHwQ = reinterpret_cast<CommandQueueHw<FamilyType> *>(pCmdQ);
MockBuffer buffer;
pHwQ->virtualEvent = nullptr;
auto currentRefCount = buffer.getRefInternalCount();
MockEventBuilder eventBuilder;
pHwQ->addMapUnmapToWaitlistEventsDependencies(nullptr,
0,
MAP,
&buffer,
eventBuilder);
EXPECT_EQ(currentRefCount + 1, buffer.getRefInternalCount());
ASSERT_NE(nullptr, pHwQ->virtualEvent);
pHwQ->virtualEvent->decRefInternal();
pHwQ->virtualEvent = nullptr;
EXPECT_EQ(currentRefCount, buffer.getRefInternalCount());
}
HWTEST_F(CommandQueueHwTest, givenNoReturnEventWhenCallingAddMapUnmapToWaitlistEventsDependenciesThenVirtualEventIncrementsCommandQueueInternalRefCount) {
CommandQueueHw<FamilyType> *pHwQ = reinterpret_cast<CommandQueueHw<FamilyType> *>(pCmdQ);
@@ -148,11 +171,11 @@ HWTEST_F(CommandQueueHwTest, givenNoReturnEventWhenCallingAddMapUnmapToWaitlistE
HWTEST_F(CommandQueueHwTest, addMapUnmapToWaitlistEventsDoesntAddDependenciesIntoChild) {
MockBuffer buffer;
auto buffer = new MockBuffer;
CommandQueueHw<FamilyType> *pHwQ = reinterpret_cast<CommandQueueHw<FamilyType> *>(pCmdQ);
Event *returnEvent = new Event(pHwQ, CL_COMMAND_MAP_BUFFER, 0, 0);
Event event(pHwQ, CL_COMMAND_MAP_BUFFER, 0, 0);
const cl_event eventWaitList = &event;
auto returnEvent = new Event(pHwQ, CL_COMMAND_MAP_BUFFER, 0, 0);
auto event = new Event(pHwQ, CL_COMMAND_MAP_BUFFER, 0, 0);
const cl_event eventWaitList = event;
pHwQ->virtualEvent = nullptr;
@@ -160,47 +183,50 @@ HWTEST_F(CommandQueueHwTest, addMapUnmapToWaitlistEventsDoesntAddDependenciesInt
pHwQ->addMapUnmapToWaitlistEventsDependencies(&eventWaitList,
1,
MAP,
&buffer,
buffer,
eventBuilder);
EXPECT_EQ(returnEvent, pHwQ->virtualEvent);
ASSERT_EQ(nullptr, event.peekChildEvents());
ASSERT_EQ(nullptr, event->peekChildEvents());
// Release API refcount (i.e. from workload's perspective)
returnEvent->release();
event->decRefInternal();
buffer->decRefInternal();
}
HWTEST_F(CommandQueueHwTest, givenMapCommandWhenZeroStateCommandIsSubmittedThenTaskCountIsBeingWaited) {
MockBuffer buffer;
auto buffer = new MockBuffer;
CommandQueueHw<FamilyType> *pHwQ = reinterpret_cast<CommandQueueHw<FamilyType> *>(pCmdQ);
MockEventBuilder eventBuilder;
pHwQ->addMapUnmapToWaitlistEventsDependencies(nullptr,
0,
MAP,
&buffer,
buffer,
eventBuilder);
EXPECT_NE(nullptr, pHwQ->virtualEvent);
pHwQ->virtualEvent->setStatus(CL_COMPLETE);
EXPECT_EQ(1u, pHwQ->latestTaskCountWaited);
buffer->decRefInternal();
}
HWTEST_F(CommandQueueHwTest, addMapUnmapToWaitlistEventsDependenciesInjectedCommand) {
CommandQueueHw<FamilyType> *pHwQ = reinterpret_cast<CommandQueueHw<FamilyType> *>(pCmdQ);
Event *returnEvent = new Event(pHwQ, CL_COMMAND_MAP_BUFFER, 0, 0);
MockBuffer buffer;
auto buffer = new MockBuffer;
pHwQ->virtualEvent = nullptr;
MockEventBuilder eventBuilder(returnEvent);
pHwQ->addMapUnmapToWaitlistEventsDependencies(nullptr,
0,
MAP,
&buffer,
buffer,
eventBuilder);
eventBuilder.finalizeAndRelease();
@@ -211,11 +237,12 @@ HWTEST_F(CommandQueueHwTest, addMapUnmapToWaitlistEventsDependenciesInjectedComm
pHwQ->virtualEvent = nullptr;
// now delete
delete returnEvent;
buffer->decRefInternal();
}
HWTEST_F(CommandQueueHwTest, addMapUnmapToWaitlistEventsDependenciesPreviousEventHasNotInjectedChild) {
MockBuffer buffer;
auto buffer = new MockBuffer;
CommandQueueHw<FamilyType> *pHwQ = reinterpret_cast<CommandQueueHw<FamilyType> *>(pCmdQ);
Event *returnEvent = new Event(pHwQ, CL_COMMAND_MAP_BUFFER, 0, 0);
Event event(pHwQ, CL_COMMAND_MAP_BUFFER, 0, 0);
@@ -230,13 +257,14 @@ HWTEST_F(CommandQueueHwTest, addMapUnmapToWaitlistEventsDependenciesPreviousEven
pHwQ->addMapUnmapToWaitlistEventsDependencies(nullptr,
0,
MAP,
&buffer,
buffer,
eventBuilder);
EXPECT_EQ(returnEvent, pHwQ->virtualEvent);
ASSERT_EQ(nullptr, event.peekChildEvents());
returnEvent->release();
buffer->decRefInternal();
}
HWTEST_F(CommandQueueHwTest, GivenNonEmptyQueueOnBlockingMapBufferWillWaitForPrecedingCommandsToComplete) {
@@ -612,8 +640,8 @@ HWTEST_F(CommandQueueHwTest, GivenEventThatIsNotCompletedWhenFinishIsCalledAndIt
};
auto Value = 0u;
Event ev(this->pCmdQ, CL_COMMAND_COPY_BUFFER, 3, Event::eventNotReady + 1);
clSetEventCallback(&ev, CL_COMPLETE, ClbFuncTempStruct::ClbFuncT, &Value);
auto ev = new Event(this->pCmdQ, CL_COMMAND_COPY_BUFFER, 3, Event::eventNotReady + 1);
clSetEventCallback(ev, CL_COMPLETE, ClbFuncTempStruct::ClbFuncT, &Value);
auto &csr = this->pCmdQ->getDevice().getCommandStreamReceiver();
EXPECT_GT(3u, csr.peekTaskCount());
@@ -621,7 +649,9 @@ HWTEST_F(CommandQueueHwTest, GivenEventThatIsNotCompletedWhenFinishIsCalledAndIt
ret = clFinish(this->pCmdQ);
ASSERT_EQ(CL_SUCCESS, ret);
EXPECT_EQ(0u, Value); // will be handled asynchronously
ev->updateExecutionStatus();
EXPECT_EQ(1u, Value);
ev->decRefInternal();
}
void CloneMdi(MultiDispatchInfo &dst, const MultiDispatchInfo &src) {
@@ -802,35 +832,36 @@ HWTEST_F(CommandQueueHwTest, givenBlockedInOrderCmdQueueAndAsynchronouslyComplet
}
};
Event event(cmdQHw, CL_COMMAND_NDRANGE_KERNEL, 10, 0);
auto event = new Event(cmdQHw, CL_COMMAND_NDRANGE_KERNEL, 10, 0);
uint32_t virtualEventTaskLevel = 77;
uint32_t virtualEventTaskCount = 80;
MockEventWithSetCompleteOnUpdate virtualEvent(cmdQHw, CL_COMMAND_NDRANGE_KERNEL, virtualEventTaskLevel, virtualEventTaskCount);
virtualEvent.setStatus(CL_SUBMITTED);
auto virtualEvent = new MockEventWithSetCompleteOnUpdate(cmdQHw, CL_COMMAND_NDRANGE_KERNEL, virtualEventTaskLevel, virtualEventTaskCount);
virtualEvent->setStatus(CL_SUBMITTED);
cl_event blockedEvent = &event;
cl_event blockedEvent = event;
// Put Queue in blocked state by assigning virtualEvent
virtualEvent.incRefInternal();
event.addChild(virtualEvent);
cmdQHw->virtualEvent = &virtualEvent;
cmdQHw->incRefInternal();
event->addChild(*virtualEvent);
virtualEvent->incRefInternal();
cmdQHw->virtualEvent = virtualEvent;
cmdQHw->taskLevel = 23;
cmdQHw->enqueueKernel(mockKernel, 1, &offset, &size, &size, 1, &blockedEvent, nullptr);
//new virtual event is created on enqueue, bind it to the created virtual event
EXPECT_NE(cmdQHw->virtualEvent, &virtualEvent);
EXPECT_NE(cmdQHw->virtualEvent, virtualEvent);
event.setStatus(CL_SUBMITTED);
event->setStatus(CL_SUBMITTED);
virtualEvent.Event::updateExecutionStatus();
virtualEvent->Event::updateExecutionStatus();
EXPECT_FALSE(cmdQHw->isQueueBlocked());
// +1 for next level after virtualEvent is unblocked
// +1 as virtualEvent was a parent for event with actual command that is being submitted
EXPECT_EQ(virtualEventTaskLevel + 2, cmdQHw->taskLevel);
//command being submitted was dependant only on virtual event hence only +1
EXPECT_EQ(virtualEventTaskLevel + 1, mockCSR->lastTaskLevelToFlushTask);
virtualEvent->decRefInternal();
event->decRefInternal();
}
HWTEST_F(OOQueueHwTest, givenBlockedOutOfOrderCmdQueueAndAsynchronouslyCompletedEventWhenEnqueueCompletesVirtualEventThenUpdatedTaskLevelIsPassedToEnqueueAndFlushTask) {
@@ -868,7 +899,6 @@ HWTEST_F(OOQueueHwTest, givenBlockedOutOfOrderCmdQueueAndAsynchronouslyCompleted
virtualEvent.incRefInternal();
event.addChild(virtualEvent);
cmdQHw->virtualEvent = &virtualEvent;
cmdQHw->incRefInternal();
cmdQHw->taskLevel = 23;
cmdQHw->enqueueKernel(mockKernel, 1, &offset, &size, &size, 1, &blockedEvent, nullptr);

View File

@@ -212,40 +212,44 @@ TEST(CommandQueue, GivenOOQwhenUpdateFromCompletionStampWithTrueIsCalledThenTask
}
TEST(CommandQueue, givenCmdQueueBlockedByReadyVirtualEventWhenUnblockingThenUpdateFlushTaskFromEvent) {
MockContext context;
CommandQueue cmdQ(&context, nullptr, 0);
Event userEvent(&cmdQ, CL_COMMAND_NDRANGE_KERNEL, 0, 0);
userEvent.setStatus(CL_COMPLETE);
userEvent.flushStamp->setStamp(5);
auto context = new MockContext;
auto cmdQ = new CommandQueue(context, nullptr, 0);
auto userEvent = new Event(cmdQ, CL_COMMAND_NDRANGE_KERNEL, 0, 0);
userEvent->setStatus(CL_COMPLETE);
userEvent->flushStamp->setStamp(5);
userEvent->incRefInternal();
FlushStamp expectedFlushStamp = 0;
EXPECT_EQ(expectedFlushStamp, cmdQ.flushStamp->peekStamp());
userEvent.incRefInternal();
cmdQ.virtualEvent = &userEvent;
cmdQ.incRefInternal();
EXPECT_EQ(expectedFlushStamp, cmdQ->flushStamp->peekStamp());
cmdQ->virtualEvent = userEvent;
EXPECT_FALSE(cmdQ.isQueueBlocked());
EXPECT_EQ(userEvent.flushStamp->peekStamp(), cmdQ.flushStamp->peekStamp());
EXPECT_FALSE(cmdQ->isQueueBlocked());
EXPECT_EQ(userEvent->flushStamp->peekStamp(), cmdQ->flushStamp->peekStamp());
userEvent->decRefInternal();
cmdQ->decRefInternal();
context->decRefInternal();
}
TEST(CommandQueue, givenCmdQueueBlockedByAbortedVirtualEventWhenUnblockingThenUpdateFlushTaskFromEvent) {
MockContext context;
auto context = new MockContext;
std::unique_ptr<MockDevice> mockDevice(Device::create<MockDevice>(nullptr));
CommandQueue cmdQ(&context, mockDevice.get(), 0);
auto cmdQ = new CommandQueue(context, mockDevice.get(), 0);
Event userEvent(&cmdQ, CL_COMMAND_NDRANGE_KERNEL, 0, 0);
userEvent.setStatus(-1);
userEvent.flushStamp->setStamp(5);
auto userEvent = new Event(cmdQ, CL_COMMAND_NDRANGE_KERNEL, 0, 0);
userEvent->setStatus(-1);
userEvent->flushStamp->setStamp(5);
FlushStamp expectedFlushStamp = 0;
EXPECT_EQ(expectedFlushStamp, cmdQ.flushStamp->peekStamp());
userEvent.incRefInternal();
cmdQ.virtualEvent = &userEvent;
cmdQ.incRefInternal();
EXPECT_EQ(expectedFlushStamp, cmdQ->flushStamp->peekStamp());
userEvent->incRefInternal();
cmdQ->virtualEvent = userEvent;
EXPECT_FALSE(cmdQ.isQueueBlocked());
EXPECT_EQ(expectedFlushStamp, cmdQ.flushStamp->peekStamp());
EXPECT_FALSE(cmdQ->isQueueBlocked());
EXPECT_EQ(expectedFlushStamp, cmdQ->flushStamp->peekStamp());
userEvent->decRefInternal();
cmdQ->decRefInternal();
context->decRefInternal();
}
struct CommandQueueCommandStreamTest : public CommandQueueMemoryDevice,
@@ -272,7 +276,6 @@ HWTEST_F(CommandQueueCommandStreamTest, givenCommandQueueThatWaitsOnAbortedUserE
userEvent.setStatus(-1);
userEvent.incRefInternal();
cmdQ.virtualEvent = &userEvent;
cmdQ.incRefInternal();
EXPECT_FALSE(cmdQ.isQueueBlocked());
EXPECT_EQ(100u, cmdQ.taskLevel);

View File

@@ -37,13 +37,15 @@ class EnqueueHandlerTest : public DeviceFixture,
public testing::Test {
public:
void SetUp() override {
context = new MockContext;
DeviceFixture::SetUp();
}
void TearDown() override {
DeviceFixture::TearDown();
context->decRefInternal();
}
MockContext context;
MockContext *context;
};
HWTEST_F(EnqueueHandlerTest, enqueueHandlerWithKernelCallsProcessEvictionOnCSR) {
@@ -52,7 +54,7 @@ HWTEST_F(EnqueueHandlerTest, enqueueHandlerWithKernelCallsProcessEvictionOnCSR)
pDevice->resetCommandStreamReceiver(csr);
MockKernelWithInternals mockKernel(*pDevice);
auto mockCmdQ = std::unique_ptr<MockCommandQueueHw<FamilyType>>(new MockCommandQueueHw<FamilyType>(&context, pDevice, 0));
auto mockCmdQ = std::unique_ptr<MockCommandQueueHw<FamilyType>>(new MockCommandQueueHw<FamilyType>(context, pDevice, 0));
size_t gws[] = {1, 1, 1};
mockCmdQ->enqueueKernel(mockKernel.mockKernel, 1, nullptr, gws, nullptr, 0, nullptr, nullptr);
@@ -65,7 +67,7 @@ HWTEST_F(EnqueueHandlerTest, enqueueHandlerCallOnEnqueueMarkerDoesntCallProcessE
auto csr = new MockCsrBase<FamilyType>(tag);
pDevice->resetCommandStreamReceiver(csr);
auto mockCmdQ = std::unique_ptr<MockCommandQueueHw<FamilyType>>(new MockCommandQueueHw<FamilyType>(&context, pDevice, 0));
auto mockCmdQ = std::unique_ptr<MockCommandQueueHw<FamilyType>>(new MockCommandQueueHw<FamilyType>(context, pDevice, 0));
mockCmdQ->enqueueMarkerWithWaitList(
0,
@@ -82,7 +84,7 @@ HWTEST_F(EnqueueHandlerTest, enqueueHandlerForMarkerOnUnblockedQueueDoesntIncrem
auto csr = new MockCsrBase<FamilyType>(tag);
pDevice->resetCommandStreamReceiver(csr);
auto mockCmdQ = std::unique_ptr<MockCommandQueueHw<FamilyType>>(new MockCommandQueueHw<FamilyType>(&context, pDevice, 0));
auto mockCmdQ = std::unique_ptr<MockCommandQueueHw<FamilyType>>(new MockCommandQueueHw<FamilyType>(context, pDevice, 0));
// put queue into initial unblocked state
mockCmdQ->taskLevel = 0;
@@ -100,7 +102,7 @@ HWTEST_F(EnqueueHandlerTest, enqueueHandlerForMarkerOnBlockedQueueShouldNotIncre
auto csr = new MockCsrBase<FamilyType>(tag);
pDevice->resetCommandStreamReceiver(csr);
auto mockCmdQ = std::unique_ptr<MockCommandQueueHw<FamilyType>>(new MockCommandQueueHw<FamilyType>(&context, pDevice, 0));
auto mockCmdQ = std::unique_ptr<MockCommandQueueHw<FamilyType>>(new MockCommandQueueHw<FamilyType>(context, pDevice, 0));
// put queue into initial blocked state
mockCmdQ->taskLevel = Event::eventNotReady;
@@ -115,13 +117,13 @@ HWTEST_F(EnqueueHandlerTest, enqueueHandlerForMarkerOnBlockedQueueShouldNotIncre
HWTEST_F(EnqueueHandlerTest, enqueueBlockedWithoutReturnEventCreatesVirtualEventAndIncremetsCommandQueueInternalRefCount) {
MockKernelWithInternals kernelInternals(*pDevice, &context);
MockKernelWithInternals kernelInternals(*pDevice, context);
Kernel *kernel = kernelInternals.mockKernel;
MockMultiDispatchInfo multiDispatchInfo(kernel);
auto mockCmdQ = new MockCommandQueueHw<FamilyType>(&context, pDevice, 0);
auto mockCmdQ = new MockCommandQueueHw<FamilyType>(context, pDevice, 0);
// put queue into initial blocked state
mockCmdQ->taskLevel = Event::eventNotReady;
@@ -142,19 +144,20 @@ HWTEST_F(EnqueueHandlerTest, enqueueBlockedWithoutReturnEventCreatesVirtualEvent
auto refCountInternal = mockCmdQ->getRefInternalCount();
EXPECT_EQ(initialRefCountInternal + 1, refCountInternal);
mockCmdQ->decRefInternal();
mockCmdQ->virtualEvent->setStatus(CL_COMPLETE);
mockCmdQ->isQueueBlocked();
mockCmdQ->release();
}
HWTEST_F(EnqueueHandlerTest, enqueueBlockedSetsVirtualEventAsCurrentCmdQVirtualEvent) {
MockKernelWithInternals kernelInternals(*pDevice, &context);
MockKernelWithInternals kernelInternals(*pDevice, context);
Kernel *kernel = kernelInternals.mockKernel;
MockMultiDispatchInfo multiDispatchInfo(kernel);
auto mockCmdQ = new MockCommandQueueHw<FamilyType>(&context, pDevice, 0);
auto mockCmdQ = new MockCommandQueueHw<FamilyType>(context, pDevice, 0);
// put queue into initial blocked state
mockCmdQ->taskLevel = Event::eventNotReady;
@@ -172,7 +175,8 @@ HWTEST_F(EnqueueHandlerTest, enqueueBlockedSetsVirtualEventAsCurrentCmdQVirtualE
EXPECT_TRUE(mockCmdQ->virtualEvent->isCurrentCmdQVirtualEvent());
mockCmdQ->decRefInternal();
mockCmdQ->virtualEvent->setStatus(CL_COMPLETE);
mockCmdQ->isQueueBlocked();
mockCmdQ->release();
}
@@ -181,13 +185,13 @@ HWTEST_F(EnqueueHandlerTest, enqueueBlockedUnsetsCurrentCmdQVirtualEventForPrevi
UserEvent userEvent;
cl_event clUserEvent = &userEvent;
MockKernelWithInternals kernelInternals(*pDevice, &context);
MockKernelWithInternals kernelInternals(*pDevice, context);
Kernel *kernel = kernelInternals.mockKernel;
MockMultiDispatchInfo multiDispatchInfo(kernel);
auto mockCmdQ = new MockCommandQueueHw<FamilyType>(&context, pDevice, 0);
auto mockCmdQ = new MockCommandQueueHw<FamilyType>(context, pDevice, 0);
// put queue into initial blocked state with userEvent
@@ -218,12 +222,12 @@ HWTEST_F(EnqueueHandlerTest, enqueueBlockedUnsetsCurrentCmdQVirtualEventForPrevi
}
HWTEST_F(EnqueueHandlerTest, enqueueWithOutputEventRegistersEvent) {
MockKernelWithInternals kernelInternals(*pDevice, &context);
MockKernelWithInternals kernelInternals(*pDevice, context);
Kernel *kernel = kernelInternals.mockKernel;
MockMultiDispatchInfo multiDispatchInfo(kernel);
cl_event outputEvent = nullptr;
auto mockCmdQ = new MockCommandQueueHw<FamilyType>(&context, pDevice, 0);
auto mockCmdQ = new MockCommandQueueHw<FamilyType>(context, pDevice, 0);
bool blocking = false;
mockCmdQ->template enqueueHandler<CL_COMMAND_NDRANGE_KERNEL>(nullptr,

View File

@@ -80,10 +80,10 @@ struct EnqueueWaitlistTest : public EnqueueWaitlistFixture,
}
void TearDown() override {
delete buffer;
delete bufferNonZeroCopy;
delete image;
delete imageNonZeroCopy;
buffer->decRefInternal();
bufferNonZeroCopy->decRefInternal();
image->decRefInternal();
imageNonZeroCopy->decRefInternal();
EnqueueWaitlistFixture::TearDown();
}