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

@@ -123,7 +123,9 @@ CommandQueue::~CommandQueue() {
}
}
if (context && !context->isSpecialQueue(this)) {
//for normal queue, decrement ref count on context
//special queue is owned by context so ref count doesn't have to be decremented
if (context && !isSpecialCommandQueue) {
context->decRefInternal();
}
}

View File

@@ -372,6 +372,10 @@ class CommandQueue : public BaseObject<_cl_command_queue> {
bool setPerfCountersEnabled(bool perfCountersEnabled, cl_uint configuration);
void setIsSpecialCommandQueue(bool newValue) {
this->isSpecialCommandQueue = newValue;
}
uint16_t getPerfCountersUserRegistersNumber() {
return perfCountersUserRegistersNumber;
}
@@ -406,6 +410,7 @@ class CommandQueue : public BaseObject<_cl_command_queue> {
IndirectHeap *indirectHeap[NUM_HEAPS];
bool mapDcFlushRequired = false;
bool isSpecialCommandQueue = false;
};
typedef CommandQueue *(*CommandQueueCreateFunc)(

View File

@@ -72,6 +72,7 @@ class CompilerInterface {
}
static void shutdown() {
std::unique_lock<std::mutex> destructionLock(CompilerInterface::mtx);
if (pInstance) {
delete pInstance;
pInstance = nullptr;

View File

@@ -87,11 +87,12 @@ CommandQueue *Context::getSpecialQueue() {
void Context::setSpecialQueue(CommandQueue *commandQueue) {
specialQueue = commandQueue;
if (commandQueue) {
decRefInternal();
} else {
incRefInternal();
}
}
void Context::overrideSpecialQueueAndDecrementRefCount(CommandQueue *commandQueue) {
setSpecialQueue(commandQueue);
commandQueue->setIsSpecialCommandQueue(true);
//decrement ref count that special queue added
this->decRefInternal();
};
bool Context::isSpecialQueue(CommandQueue *commandQueue) {
@@ -179,8 +180,7 @@ bool Context::createImpl(const cl_context_properties *properties,
auto commandQueue = CommandQueue::create(this, devices[0], nullptr, errcodeRet);
DEBUG_BREAK_IF(commandQueue == nullptr);
setSpecialQueue(commandQueue);
overrideSpecialQueueAndDecrementRefCount(commandQueue);
return true;
}

View File

@@ -92,6 +92,7 @@ class Context : public BaseObject<_cl_context> {
CommandQueue *getSpecialQueue();
void setSpecialQueue(CommandQueue *commandQueue);
void overrideSpecialQueueAndDecrementRefCount(CommandQueue *commandQueue);
bool isSpecialQueue(CommandQueue *commandQueue);
void deleteSpecialQueue();

View File

@@ -102,56 +102,51 @@ Event::Event(
}
Event::~Event() {
try {
DBG_LOG(EventsDebugEnable, "~Event()", this);
//no commands should be registred
DEBUG_BREAK_IF(this->cmdToSubmit.load());
DBG_LOG(EventsDebugEnable, "~Event()", this);
//no commands should be registred
DEBUG_BREAK_IF(this->cmdToSubmit.load());
submitCommand(true);
submitCommand(true);
int32_t lastStatus = executionStatus;
if (isStatusCompleted(&lastStatus) == false) {
transitionExecutionStatus(-1);
DEBUG_BREAK_IF(peekHasCallbacks() || peekHasChildEvents());
}
// Note from OCL spec:
// "All callbacks registered for an event object must be called.
// All enqueued callbacks shall be called before the event object is destroyed."
if (peekHasCallbacks()) {
executeCallbacks(lastStatus);
}
{
// clean-up submitted command if needed
std::unique_ptr<Command> submittedCommand(submittedCmd.exchange(nullptr));
}
if (cmdQueue != nullptr) {
cmdQueue->decRefInternal();
}
if (ctx != nullptr) {
if (timeStampNode != nullptr) {
TagAllocator<HwTimeStamps> *allocator = ctx->getDevice(0)->getMemoryManager()->getEventTsAllocator();
allocator->returnTag(timeStampNode);
}
if (perfCounterNode != nullptr) {
TagAllocator<HwPerfCounter> *allocator = ctx->getDevice(0)->getMemoryManager()->getEventPerfCountAllocator();
allocator->returnTag(perfCounterNode);
}
ctx->decRefInternal();
}
if (perfConfigurationData) {
delete perfConfigurationData;
}
// in case event did not unblock child events before
unblockEventsBlockedByThis(executionStatus);
} catch (...) //Don't throw from destructor
{
DEBUG_BREAK_IF(false);
int32_t lastStatus = executionStatus;
if (isStatusCompleted(&lastStatus) == false) {
transitionExecutionStatus(-1);
DEBUG_BREAK_IF(peekHasCallbacks() || peekHasChildEvents());
}
// Note from OCL spec:
// "All callbacks registered for an event object must be called.
// All enqueued callbacks shall be called before the event object is destroyed."
if (peekHasCallbacks()) {
executeCallbacks(lastStatus);
}
{
// clean-up submitted command if needed
std::unique_ptr<Command> submittedCommand(submittedCmd.exchange(nullptr));
}
if (cmdQueue != nullptr) {
cmdQueue->decRefInternal();
}
if (ctx != nullptr) {
if (timeStampNode != nullptr) {
TagAllocator<HwTimeStamps> *allocator = ctx->getDevice(0)->getMemoryManager()->getEventTsAllocator();
allocator->returnTag(timeStampNode);
}
if (perfCounterNode != nullptr) {
TagAllocator<HwPerfCounter> *allocator = ctx->getDevice(0)->getMemoryManager()->getEventPerfCountAllocator();
allocator->returnTag(perfCounterNode);
}
ctx->decRefInternal();
}
if (perfConfigurationData) {
delete perfConfigurationData;
}
// in case event did not unblock child events before
unblockEventsBlockedByThis(executionStatus);
}
cl_int Event::getEventProfilingInfo(cl_profiling_info paramName,

View File

@@ -45,6 +45,15 @@ KernelOperation::~KernelOperation() {
alignedFree(commandStream->getBase());
}
CommandMapUnmap::CommandMapUnmap(MapOperationType op, MemObj &memObj, CommandStreamReceiver &csr, CommandQueue &cmdQ)
: memObj(memObj), csr(csr), cmdQ(cmdQ), op(op) {
memObj.incRefInternal();
}
CommandMapUnmap::~CommandMapUnmap() {
memObj.decRefInternal();
}
CompletionStamp &CommandMapUnmap::submit(uint32_t taskLevel, bool terminated) {
if (terminated) {
return completionStamp;
@@ -77,12 +86,12 @@ CompletionStamp &CommandMapUnmap::submit(uint32_t taskLevel, bool terminated) {
cmdQ.waitUntilComplete(completionStamp.taskCount, completionStamp.flushStamp);
if (m.isMemObjZeroCopy() == false) {
if (memObj.isMemObjZeroCopy() == false) {
if (op == MAP) {
m.transferDataToHostPtr();
memObj.transferDataToHostPtr();
} else {
DEBUG_BREAK_IF(op != UNMAP);
m.transferDataFromHostPtrToMemoryStorage();
memObj.transferDataFromHostPtrToMemoryStorage();
}
}

View File

@@ -59,13 +59,12 @@ class Command : public IFNode<Command> {
class CommandMapUnmap : public Command {
public:
CommandMapUnmap(MapOperationType op, MemObj &m, CommandStreamReceiver &csr, CommandQueue &cmdQ)
: m(m), csr(csr), cmdQ(cmdQ), op(op) {
}
CommandMapUnmap(MapOperationType op, MemObj &memObj, CommandStreamReceiver &csr, CommandQueue &cmdQ);
~CommandMapUnmap() override;
CompletionStamp &submit(uint32_t taskLevel, bool terminated) override;
private:
MemObj &m;
MemObj &memObj;
CommandStreamReceiver &csr;
CommandQueue &cmdQ;
MapOperationType op;

View File

@@ -124,8 +124,7 @@ Kernel::~Kernel() {
}
kernelArgHandlers.clear();
if (program)
program->release();
program->release();
}
// Checks if patch offset is invalid (undefined)

View File

@@ -132,7 +132,7 @@ class unique_ptr_if_unused : public std::unique_ptr<DataType, void (*)(DataType
template <typename DerivedClass>
class ReferenceTrackedObject {
public:
virtual ~ReferenceTrackedObject() = default;
virtual ~ReferenceTrackedObject();
int32_t getRefInternalCount() const {
return refInternal.peek();
@@ -181,4 +181,8 @@ class ReferenceTrackedObject {
RefCounter<> refInternal;
RefCounter<> refApi;
};
template <typename DerivedClass>
inline ReferenceTrackedObject<DerivedClass>::~ReferenceTrackedObject() {
UNRECOVERABLE_IF(refInternal.peek() > 1);
}
}