Fix race in events scenarios.

- It could happen that 2 threads try to update the same event within tree
- First thread starts to submit command, it releases cmdToSubmit
- Second thread doesn't see the command and follows
- Second thread thinks that it submitted the command so it follows to
subsequent steps which are child events notification
- We end up with corrupted enqueue sequence as child may submit prior to
parent.
- With this change each submit step is synchronized basing on task count
- When second thread enters submit command without task count being set
it wait for first thread to properly set it.

Change-Id: Ic2ddaea17f9af8cab6781320edae2c268dd0b189
Signed-off-by: Mrozek, Michal <michal.mrozek@intel.com>
This commit is contained in:
Mrozek, Michal
2019-07-09 12:55:26 +02:00
committed by sys_ocldev
parent d724b9ab11
commit 6ffcd51847
5 changed files with 34 additions and 8 deletions

View File

@@ -753,19 +753,38 @@ HWTEST_F(CommandQueueHwTest, givenCommandQueueThatIsBlockedAndUsesCpuCopyWhenEve
clReleaseEvent(returnEvent);
}
HWTEST_F(CommandQueueHwTest, givenEventWithRecordedCommandWhenSubmitCommandIsCalledThenTaskCountIsNotUpdated) {
HWTEST_F(CommandQueueHwTest, givenEventWithRecordedCommandWhenSubmitCommandIsCalledThenTaskCountMustBeUpdatedFromOtherThread) {
std::atomic_bool go{false};
struct mockEvent : public Event {
using Event::Event;
using Event::eventWithoutCommand;
using Event::submitCommand;
void synchronizeTaskCount() override {
*atomicFence = true;
Event::synchronizeTaskCount();
}
uint32_t synchronizeCallCount = 0u;
std::atomic_bool *atomicFence = nullptr;
};
mockEvent neoEvent(this->pCmdQ, CL_COMMAND_MAP_BUFFER, Event::eventNotReady, Event::eventNotReady);
neoEvent.atomicFence = &go;
EXPECT_TRUE(neoEvent.eventWithoutCommand);
neoEvent.eventWithoutCommand = false;
neoEvent.submitCommand(false);
EXPECT_EQ(Event::eventNotReady, neoEvent.peekTaskCount());
std::thread t([&]() {
while (!go)
;
neoEvent.updateTaskCount(77u);
});
neoEvent.submitCommand(false);
EXPECT_EQ(77u, neoEvent.peekTaskCount());
t.join();
}
HWTEST_F(CommandQueueHwTest, GivenBuiltinKernelWhenBuiltinDispatchInfoBuilderIsProvidedThenThisBuilderIsUsedForCreatingDispatchInfo) {

View File

@@ -120,6 +120,7 @@ TEST_F(EventTests, givenoneThreadUpdatingUserEventAnotherWaitingOnFinishWhenFini
cl_event returnedEvent = nullptr;
std::atomic_bool go{false};
std::atomic_bool updateEvent{true};
std::thread t([&]() {
while (!go)
@@ -132,7 +133,9 @@ TEST_F(EventTests, givenoneThreadUpdatingUserEventAnotherWaitingOnFinishWhenFini
EXPECT_EQ(CL_SUCCESS, retVal);
std::thread t2([&]() {
castToObject<Event>(returnedEvent)->updateExecutionStatus();
while (updateEvent) {
castToObject<Event>(returnedEvent)->updateExecutionStatus();
}
});
go = true;
@@ -141,6 +144,7 @@ TEST_F(EventTests, givenoneThreadUpdatingUserEventAnotherWaitingOnFinishWhenFini
EXPECT_EQ(pCmdQ->latestTaskCountWaited, i + 1);
t.join();
updateEvent = false;
t2.join();
clReleaseEvent(returnedEvent);
}