mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-03 06:49:52 +08:00
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:
committed by
sys_ocldev
parent
6afb024f6f
commit
2b91ea85c6
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,9 +166,9 @@ 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
|
||||
!profilingEnabled) // the CL_QUEUE_PROFILING_ENABLE flag is not set for the command-queue,
|
||||
if (isUserEvent() != CL_FALSE || // or is a user event object.
|
||||
!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(¤tStatus);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
incRefInternal();
|
||||
DBG_LOG(EventsDebugEnable, "event", this, "addCallback", "ECallbackTarget", (uint32_t)type);
|
||||
callbacks[(uint32_t)target].pushFrontOne(*new Callback(this, fn, type, data));
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -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);
|
||||
// Note from OLC spec :
|
||||
// "A command is considered complete if its execution status
|
||||
// is CL_COMPLETE or a negative value."
|
||||
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user