Fortify events

- add some debug breaks
- clean cmd ownership, there can't be situation when event holds 2 commands
- cmd meaning cleanup
- remove not needed try catch clause

Change-Id: I5ad6877e7235de2d7f48818467cb4b92655aab97
This commit is contained in:
Mrozek, Michal
2017-12-22 11:44:41 +01:00
committed by sys_ocldev
parent 6afb024f6f
commit 2b91ea85c6
13 changed files with 74 additions and 87 deletions

2
Jenkinsfile vendored
View File

@ -2,4 +2,4 @@
neoDependenciesRev='716918-671'
strategy='EQUAL'
allowedF=49
allowedCD=377
allowedCD=375

View File

@ -167,7 +167,7 @@ bool CommandQueue::isQueueBlocked() {
if (this->virtualEvent->peekExecutionStatus() <= CL_COMPLETE) {
UNRECOVERABLE_IF(this->virtualEvent == nullptr);
if (this->virtualEvent->peekIsCompletedByTermination() == false) {
if (this->virtualEvent->isStatusCompletedByTermination() == false) {
taskCount = this->virtualEvent->peekTaskCount();
flushStamp->setStamp(this->virtualEvent->flushStamp->peekStamp());
taskLevel = this->virtualEvent->taskLevel;

View File

@ -104,11 +104,15 @@ Event::Event(
Event::~Event() {
try {
DBG_LOG(EventsDebugEnable, "~Event()", this);
//no commands should be registred
DEBUG_BREAK_IF(this->cmdToSubmit.load());
submitCommand(true);
int32_t lastStatus = executionStatus;
if (peekIsCompleted(&lastStatus) == false) {
if (isStatusCompleted(&lastStatus) == false) {
transitionExecutionStatus(-1);
DEBUG_BREAK_IF(peekHasCallbacks() || peekHasChildEvents());
}
// Note from OCL spec:
@ -146,6 +150,7 @@ Event::~Event() {
unblockEventsBlockedByThis(executionStatus);
} catch (...) //Don't throw from destructor
{
DEBUG_BREAK_IF(false);
}
}
@ -162,7 +167,7 @@ cl_int Event::getEventProfilingInfo(cl_profiling_info paramName,
// CL_PROFILING_INFO_NOT_AVAILABLE if event refers to the clEnqueueSVMFree command
if (isUserEvent() != CL_FALSE || // or is a user event object.
!peekIsCompleted() || // if the execution status of the command identified by event is not CL_COMPLETE
!updateStatusAndCheckCompletion() || //if the execution status of the command identified by event is not CL_COMPLETE
!profilingEnabled) // the CL_QUEUE_PROFILING_ENABLE flag is not set for the command-queue,
{
return CL_PROFILING_INFO_NOT_AVAILABLE;
@ -203,7 +208,7 @@ cl_int Event::getEventProfilingInfo(cl_profiling_info paramName,
paramValueSizeRet,
getHwPerfCounter(),
perfConfigurationData,
peekIsCompleted())) {
updateStatusAndCheckCompletion())) {
return CL_PROFILING_INFO_NOT_AVAILABLE;
}
return CL_SUCCESS;
@ -305,7 +310,7 @@ void Event::updateExecutionStatus() {
}
int32_t statusSnapshot = executionStatus;
if (peekIsCompleted(&statusSnapshot)) {
if (isStatusCompleted(&statusSnapshot)) {
executeCallbacks(statusSnapshot);
return;
}
@ -317,7 +322,7 @@ void Event::updateExecutionStatus() {
}
if (statusSnapshot == CL_QUEUED) {
bool abortBlockedTasks = peekIsCompletedByTermination(&statusSnapshot);
bool abortBlockedTasks = isStatusCompletedByTermination(&statusSnapshot);
submitCommand(abortBlockedTasks);
transitionExecutionStatus(CL_SUBMITTED);
executeCallbacks(CL_SUBMITTED);
@ -353,11 +358,11 @@ void Event::unblockEventsBlockedByThis(int32_t transitionStatus) {
int32_t status = transitionStatus;
(void)status;
DEBUG_BREAK_IF(!(peekIsCompleted(&status) || (peekIsSubmitted(&status))));
DEBUG_BREAK_IF(!(isStatusCompleted(&status) || (peekIsSubmitted(&status))));
uint32_t taskLevelToPropagate = Event::eventNotReady;
if (peekIsCompletedByTermination(&transitionStatus) == false) {
if (isStatusCompletedByTermination(&transitionStatus) == false) {
//if we are event on top of the tree , obtain taskLevel from CSR
if (taskLevel == Event::eventNotReady) {
this->taskLevel = getTaskLevel();
@ -391,7 +396,7 @@ bool Event::setStatus(cl_int status) {
DBG_LOG(EventsDebugEnable, "setStatus event", this, " new status", status, "previousStatus", prevStatus);
if (peekIsCompleted(&prevStatus)) {
if (isStatusCompleted(&prevStatus)) {
return false;
}
@ -399,18 +404,18 @@ bool Event::setStatus(cl_int status) {
return false;
}
if (peekIsBlocked() && (peekIsCompletedByTermination(&status) == false)) {
if (peekIsBlocked() && (isStatusCompletedByTermination(&status) == false)) {
return false;
}
if ((status == CL_SUBMITTED) || (peekIsCompleted(&status))) {
bool abortBlockedTasks = peekIsCompletedByTermination(&status);
if ((status == CL_SUBMITTED) || (isStatusCompleted(&status))) {
bool abortBlockedTasks = isStatusCompletedByTermination(&status);
submitCommand(abortBlockedTasks);
}
this->incRefInternal();
transitionExecutionStatus(status);
if (peekIsCompleted(&status) || (status == CL_SUBMITTED)) {
if (isStatusCompleted(&status) || (status == CL_SUBMITTED)) {
unblockEventsBlockedByThis(status);
}
executeCallbacks(status);
@ -442,8 +447,7 @@ void Event::submitCommand(bool abortTasks) {
}
updateTaskCount(complStamp.taskCount);
flushStamp->setStamp(complStamp.flushStamp);
std::unique_ptr<Command> prevSubmittedCmd;
prevSubmittedCmd.reset(submittedCmd.exchange(cmdToProcess.release()));
submittedCmd.exchange(cmdToProcess.release());
} else if (profilingCpuPath && endTimeStamp == 0) {
setEndTimeStamp();
}
@ -494,17 +498,6 @@ cl_int Event::waitForEvents(cl_uint numEvents,
}
}
if (currentlyPendingEvents->size() == pendingEventsLeft->size()) {
// we're stuck because of some non-trivial (non-explicit) event dependencies
// (e.g. event will be signaled from within a callback of an unrelated event)
Event *baseEvent = castToObjectOrAbort<Event>((*currentlyPendingEvents)[0]);
Context *ctx = baseEvent->ctx;
if (ctx == nullptr) {
DEBUG_BREAK_IF(true);
return CL_INVALID_CONTEXT;
}
}
std::swap(currentlyPendingEvents, pendingEventsLeft);
pendingEventsLeft->clear();
}
@ -521,9 +514,9 @@ inline void Event::unblockEventBy(Event &event, uint32_t taskLevel, int32_t tran
DEBUG_BREAK_IF(numEventsBlockingThis < 0);
int32_t blockerStatus = transitionStatus;
DEBUG_BREAK_IF(!(peekIsCompleted(&blockerStatus) || peekIsSubmitted(&blockerStatus)));
DEBUG_BREAK_IF(!(isStatusCompleted(&blockerStatus) || peekIsSubmitted(&blockerStatus)));
if ((numEventsBlockingThis > 0) && (peekIsCompletedByTermination(&blockerStatus) == false)) {
if ((numEventsBlockingThis > 0) && (isStatusCompletedByTermination(&blockerStatus) == false)) {
return;
}
DBG_LOG(EventsDebugEnable, "Event", this, "is unblocked by", &event);
@ -535,7 +528,7 @@ inline void Event::unblockEventBy(Event &event, uint32_t taskLevel, int32_t tran
}
int32_t statusToPropagate = CL_SUBMITTED;
if (peekIsCompletedByTermination(&blockerStatus)) {
if (isStatusCompletedByTermination(&blockerStatus)) {
statusToPropagate = blockerStatus;
}
setStatus(statusToPropagate);
@ -544,6 +537,11 @@ inline void Event::unblockEventBy(Event &event, uint32_t taskLevel, int32_t tran
this->updateExecutionStatus();
}
bool Event::updateStatusAndCheckCompletion() {
auto currentStatus = updateEventAndReturnCurrentStatus();
return isStatusCompleted(&currentStatus);
}
bool Event::isReadyForSubmission() {
return taskLevel != Event::eventNotReady ? true : false;
}
@ -560,18 +558,12 @@ void Event::addCallback(Callback::ClbFuncT fn, cl_int type, void *data) {
// "All callbacks registered for an event object must be called.
// All enqueued callbacks shall be called before the event object is destroyed."
// That's why each registered calback increments the internal refcount
try {
incRefInternal();
DBG_LOG(EventsDebugEnable, "event", this, "addCallback", "ECallbackTarget", (uint32_t)type);
callbacks[(uint32_t)target].pushFrontOne(*new Callback(this, fn, type, data));
} catch (...) {
decRefInternal(); // in case we fail adding callback, we don't want to contaminate
// the internal ref counter
throw;
}
// Callback added after event reached its "completed" state
if (peekIsCompleted()) {
if (updateStatusAndCheckCompletion()) {
int32_t status = executionStatus;
DBG_LOG(EventsDebugEnable, "event", this, "addCallback executing callbacks with status", status);
executeCallbacks(status);
@ -586,7 +578,7 @@ void Event::addCallback(Callback::ClbFuncT fn, cl_int type, void *data) {
void Event::executeCallbacks(int32_t executionStatusIn) {
int32_t execStatus = executionStatusIn;
bool terminated = peekIsCompletedByTermination(&execStatus);
bool terminated = isStatusCompletedByTermination(&execStatus);
ECallbackTarget target;
if (terminated) {
target = ECallbackTarget::Completed;
@ -618,7 +610,7 @@ void Event::executeCallbacks(int32_t executionStatusIn) {
void Event::tryFlushEvent() {
//only if event is not completed, completed event has already been flushed
if (cmdQueue && (peekIsCompleted() == false)) {
if (cmdQueue && (updateStatusAndCheckCompletion() == false)) {
//flush the command queue only if it is not blocked event
if (taskLevel != Event::eventNotReady) {
cl_event ev = this;

View File

@ -109,8 +109,8 @@ class Event : public BaseObject<_cl_event>, public IDNode<Event> {
cl_ulong getDelta(cl_ulong startTime,
cl_ulong endTime);
bool calcProfilingData();
void setCPUProfilingPath(bool isCPUPath) { isCPUPath ? profilingCpuPath = CL_TRUE : profilingCpuPath = CL_FALSE; }
cl_bool isCPUProfilingPath() {
void setCPUProfilingPath(bool isCPUPath) { this->profilingCpuPath = isCPUPath; }
bool isCPUProfilingPath() {
return profilingCpuPath;
}
@ -119,11 +119,9 @@ class Event : public BaseObject<_cl_event>, public IDNode<Event> {
void *paramValue,
size_t *paramValueSizeRet);
cl_bool isProfilingEnabled() { return profilingEnabled; }
bool isProfilingEnabled() { return profilingEnabled; }
void setProfilingEnabled(cl_bool profilingEnabled) {
this->profilingEnabled = profilingEnabled;
}
void setProfilingEnabled(bool profilingEnabled) { this->profilingEnabled = profilingEnabled; }
HwTimeStamps *getHwTimeStamp();
GraphicsAllocation *getHwTimeStampAllocation();
@ -152,10 +150,10 @@ class Event : public BaseObject<_cl_event>, public IDNode<Event> {
const cl_event *eventList);
std::unique_ptr<Command> setCommand(std::unique_ptr<Command> newCmd) {
std::unique_ptr<Command> prevCmd;
prevCmd.reset(cmdToSubmit.exchange(newCmd.release()));
UNRECOVERABLE_IF(cmdToSubmit.load());
cmdToSubmit.exchange(newCmd.release());
eventWithoutCommand = false;
return prevCmd;
return nullptr;
}
Command *peekCommand() {
return cmdToSubmit;
@ -192,23 +190,20 @@ class Event : public BaseObject<_cl_event>, public IDNode<Event> {
}
// returns true if event is completed (in terms of definition provided by OCL spec)
bool peekIsCompleted(const int32_t *executionStatusSnapshot = nullptr) {
// Note from OLC spec :
// "A command is considered complete if its execution status
// is CL_COMPLETE or a negative value."
int32_t statusSnapshot = 0;
if (executionStatusSnapshot != nullptr) {
statusSnapshot = *executionStatusSnapshot;
} else {
statusSnapshot = updateEventAndReturnCurrentStatus();
}
return (statusSnapshot == CL_COMPLETE) || (statusSnapshot < 0);
bool isStatusCompleted(const int32_t *executionStatusSnapshot) {
return (*executionStatusSnapshot == CL_COMPLETE) || (*executionStatusSnapshot < 0);
}
bool updateStatusAndCheckCompletion();
// Note from OCL spec :
// "A negative integer value causes all enqueued commands that wait on this user event
// to be terminated."
bool peekIsCompletedByTermination(const int32_t *executionStatusSnapshot = nullptr) {
bool isStatusCompletedByTermination(const int32_t *executionStatusSnapshot = nullptr) {
if (executionStatusSnapshot == nullptr) {
return (peekExecutionStatus() < 0);
} else {
@ -373,8 +368,8 @@ class Event : public BaseObject<_cl_event>, public IDNode<Event> {
// e.g. CL_COMPLETE -> CL_SUBMITTED or CL_SUBMITTED -> CL_QUEUED becomes forbiden
mutable std::atomic<int32_t> executionStatus;
// Timestamps
cl_bool profilingEnabled;
cl_bool profilingCpuPath;
bool profilingEnabled;
bool profilingCpuPath;
bool dataCalculated;
TimeStampData queueTimeStamp;
TimeStampData submitTimeStamp;

View File

@ -38,7 +38,7 @@ void UserEvent::updateExecutionStatus() {
}
bool UserEvent::wait(bool blocking) {
while (peekIsCompleted() == false) {
while (updateStatusAndCheckCompletion() == false) {
if (blocking == false) {
return false;
}
@ -73,7 +73,7 @@ void VirtualEvent::updateExecutionStatus() {
}
bool VirtualEvent::wait(bool blocking) {
while (peekIsCompleted() == false) {
while (updateStatusAndCheckCompletion() == false) {
if (blocking == false) {
return false;
}
@ -94,7 +94,7 @@ uint32_t VirtualEvent::getTaskLevel() {
bool VirtualEvent::setStatus(cl_int status) {
// virtual events are just helper events and will have either
// "waiting" (after construction) or "complete" (on change if not blocked) execution state
if (peekIsCompletedByTermination(&status) == false) {
if (isStatusCompletedByTermination(&status) == false) {
status = CL_COMPLETE;
}
return Event::setStatus(status);

View File

@ -303,7 +303,7 @@ HWTEST_F(CommandQueueHwTest, GivenEventsWaitlistOnBlockingMapBufferWillWaitForEv
auto b1 = clCreateBuffer(context, CL_MEM_READ_WRITE, 20, nullptr, nullptr);
cl_event meAsClEv = me;
void *ptr1 = clEnqueueMapBuffer(pCmdQ, b1, CL_TRUE, CL_MAP_READ, 0, 8, 1, &meAsClEv, nullptr, nullptr);
ASSERT_TRUE(me->peekIsCompleted());
ASSERT_TRUE(me->updateStatusAndCheckCompletion());
ASSERT_LE(me->updateCountBeforeCompleted, me->updateCount);
clEnqueueUnmapMemObject(pCmdQ, b1, ptr1, 0, nullptr, nullptr);

View File

@ -232,7 +232,7 @@ HWTEST_F(BarrierTest, givenNotBlockedCommandQueueAndEnqueueBarrierWithWaitlistRe
EXPECT_EQ(latestTaskCountWaitedBeforeEnqueue, this->pCmdQ->latestTaskCountWaited);
auto pEvent = (Event *)event;
EXPECT_EQ(17u, pEvent->peekTaskCount());
EXPECT_TRUE(pEvent->peekIsCompleted());
EXPECT_TRUE(pEvent->updateStatusAndCheckCompletion());
delete pEvent;
}

View File

@ -318,7 +318,7 @@ TEST_F(EnqueueMapBufferTest, givenNonBlockingMapBufferOnZeroCopyBufferWhenItIsCa
//if task count of csr is higher then event task count with proper dc flushing then we are fine
EXPECT_EQ(1u, neoEvent->getCompletionStamp());
//this can't be completed as task count is not reached yet
EXPECT_FALSE(neoEvent->peekIsCompleted());
EXPECT_FALSE(neoEvent->updateStatusAndCheckCompletion());
auto callbackCalled = 0u;
@ -334,7 +334,7 @@ TEST_F(EnqueueMapBufferTest, givenNonBlockingMapBufferOnZeroCopyBufferWhenItIsCa
EXPECT_EQ(1u, commandStreamReceiver.peekTaskCount());
EXPECT_EQ(1u, pCmdQ->latestTaskCountWaited);
EXPECT_TRUE(neoEvent->peekIsCompleted());
EXPECT_TRUE(neoEvent->updateStatusAndCheckCompletion());
EXPECT_EQ(1u, callbackCalled);
@ -403,7 +403,7 @@ TEST_F(EnqueueMapBufferTest, givenNonBlockingMapBufferAfterL3IsAlreadyFlushedThe
auto neoEvent = castToObject<Event>(eventReturned);
//if task count of csr is higher then event task count with proper dc flushing then we are fine
EXPECT_EQ(1u, neoEvent->getCompletionStamp());
EXPECT_TRUE(neoEvent->peekIsCompleted());
EXPECT_TRUE(neoEvent->updateStatusAndCheckCompletion());
//flush task was not called
EXPECT_EQ(1u, commandStreamReceiver.peekLatestSentTaskCount());
@ -510,7 +510,7 @@ HWTEST_F(EnqueueMapBufferTest, MapBufferEventProperties) {
auto eventObject = castToObject<Event>(eventReturned);
EXPECT_EQ(0u, eventObject->peekTaskCount());
EXPECT_TRUE(eventObject->peekIsCompleted());
EXPECT_TRUE(eventObject->updateStatusAndCheckCompletion());
retVal = clEnqueueUnmapMemObject(
pCmdQ,

View File

@ -264,7 +264,7 @@ HWTEST_F(EnqueueMapImageTest, MapImageEventProperties) {
auto eventObject = castToObject<Event>(eventReturned);
EXPECT_EQ(forceTaskCount + 1, eventObject->peekTaskCount());
EXPECT_TRUE(eventObject->peekIsCompleted());
EXPECT_TRUE(eventObject->updateStatusAndCheckCompletion());
retVal = clEnqueueUnmapMemObject(
pCmdQ,
@ -318,7 +318,7 @@ HWTEST_F(EnqueueMapImageTest, givenZeroCopyImageWhenItIsMappedAndReturnsEventThe
auto eventObject = castToObject<Event>(eventReturned);
//this is CPU path , event is manually set to completed state so task count equalizies to CSR = 100
EXPECT_EQ(100u, eventObject->peekTaskCount());
EXPECT_TRUE(eventObject->peekIsCompleted());
EXPECT_TRUE(eventObject->updateStatusAndCheckCompletion());
retVal = clEnqueueUnmapMemObject(
pCmdQ,

View File

@ -166,7 +166,7 @@ HWTEST_F(EnqueueUnmapMemObjTest, UnmapEventProperties) {
auto eventObject = castToObject<Event>(eventReturned);
EXPECT_EQ(0u, eventObject->peekTaskCount());
EXPECT_TRUE(eventObject->peekIsCompleted());
EXPECT_TRUE(eventObject->updateStatusAndCheckCompletion());
clReleaseEvent(eventReturned);
}

View File

@ -199,7 +199,7 @@ TEST(EventBuilder, whenFinalizeIsCalledAndParentsListContainsManyEventsFromWhich
eventBuilder.addParentEvent(*userEventCompleted);
eventBuilder.addParentEvent(*userEventNotCompleted);
Event *event = eventBuilder.finalizeAndRelease();
EXPECT_FALSE(event->peekIsCompleted());
EXPECT_FALSE(event->updateStatusAndCheckCompletion());
EXPECT_EQ(1U, event->peekNumEventsBlockingThis());
ASSERT_EQ(nullptr, userEventCompleted->peekChildEvents());
ASSERT_NE(nullptr, userEventNotCompleted->peekChildEvents());

View File

@ -711,7 +711,7 @@ TEST_P(InternalsEventProfilingTest, GivenProfilingWhenEventCreatedThenProfilingS
std::unique_ptr<CommandQueue> pCmdQ(new CommandQueue(mockContext, pDevice, props));
std::unique_ptr<MockEvent<Event>> event(new MockEvent<Event>(pCmdQ.get(), GetParam(), 0, 0));
EXPECT_TRUE(event.get()->isProfilingEnabled() == CL_TRUE);
EXPECT_TRUE(event.get()->isProfilingEnabled());
}
INSTANTIATE_TEST_CASE_P(InternalsEventProfilingTest,
@ -723,7 +723,7 @@ TEST_F(InternalsEventTest, GivenProfilingWhenUserEventCreatedThenProfilingNotSet
std::unique_ptr<CommandQueue> pCmdQ(new CommandQueue(mockContext, pDevice, props));
std::unique_ptr<MockEvent<Event>> event(new MockEvent<Event>(pCmdQ.get(), CL_COMMAND_USER, 0, 0));
EXPECT_TRUE(event.get()->isProfilingEnabled() == CL_FALSE);
EXPECT_FALSE(event.get()->isProfilingEnabled());
}
TEST_F(InternalsEventTest, GIVENProfilingWHENMapOperationTHENTimesSet) {
@ -894,7 +894,7 @@ TEST_F(InternalsEventWithPerfCountersTest, IsPerfCounter_Enabled) {
CommandQueue *pCmdQ = new CommandQueue(mockContext, pDevice, props);
pCmdQ->setPerfCountersEnabled(true, 2);
Event *ev = new Event(pCmdQ, CL_COMMAND_COPY_BUFFER, 3, 0);
EXPECT_EQ(1u, ev->isProfilingEnabled());
EXPECT_TRUE(ev->isProfilingEnabled());
EXPECT_TRUE(ev->isPerfCountersEnabled());
delete ev;
delete pCmdQ;
@ -1165,13 +1165,13 @@ TEST_F(EventTest, hwPerfCounterMemoryIsPlacedInGraphicsAllocation) {
TEST_F(EventTest, IsPerfCounter_DisabledByNullQueue) {
Event ev(nullptr, CL_COMMAND_COPY_BUFFER, 3, 0);
EXPECT_EQ(0u, ev.isProfilingEnabled());
EXPECT_FALSE(ev.isProfilingEnabled());
EXPECT_FALSE(ev.isPerfCountersEnabled());
}
TEST_F(EventTest, IsPerfCounter_DisabledByNoProfiling) {
Event ev(pCmdQ, CL_COMMAND_COPY_BUFFER, 3, 0);
EXPECT_EQ(0u, ev.isProfilingEnabled());
EXPECT_FALSE(ev.isProfilingEnabled());
EXPECT_FALSE(ev.isPerfCountersEnabled());
}
@ -1180,7 +1180,7 @@ TEST_F(InternalsEventTest, IsPerfCounter_DisabledByNoPerfCounter) {
CommandQueue *pCmdQ = new CommandQueue(mockContext, pDevice, props);
Event *ev = new Event(pCmdQ, CL_COMMAND_COPY_BUFFER, 3, 0);
EXPECT_EQ(1u, ev->isProfilingEnabled());
EXPECT_TRUE(ev->isProfilingEnabled());
EXPECT_FALSE(ev->isPerfCountersEnabled());
delete ev;

View File

@ -269,7 +269,7 @@ TEST_F(EventTests, givenNormalEventThatHasParentUserEventWhenUserEventIsUnblocke
Event event(pCmdQ, CL_COMMAND_NDRANGE_KERNEL, 0, 0);
uEvent.addChild(event);
EXPECT_FALSE(event.peekIsCompleted());
EXPECT_FALSE(event.updateStatusAndCheckCompletion());
EXPECT_EQ(CL_QUEUED, event.peekExecutionStatus());
uEvent.setStatus(CL_COMPLETE);