mirror of
https://github.com/opencv/opencv.git
synced 2025-06-08 01:53:19 +08:00
core(ocl): fix deadlock in UMatDataAutoLock
UMatData locks are not mapped on real locks (they are mapped to some "pre-initialized" pool). Concurrent execution of these statements may lead to deadlock: - a.copyTo(b) from thread 1 - c.copyTo(d) from thread 2 where: - 'a' and 'd' are mapped to single lock "A". - 'b' and 'c' are mapped to single lock "B". Workaround is to process locks with strict order.
This commit is contained in:
parent
ab8cf31ae9
commit
cec700525c
@ -545,14 +545,6 @@ struct CV_EXPORTS UMatData
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct CV_EXPORTS UMatDataAutoLock
|
|
||||||
{
|
|
||||||
explicit UMatDataAutoLock(UMatData* u);
|
|
||||||
~UMatDataAutoLock();
|
|
||||||
UMatData* u;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct CV_EXPORTS MatSize
|
struct CV_EXPORTS MatSize
|
||||||
{
|
{
|
||||||
explicit MatSize(int* _p);
|
explicit MatSize(int* _p);
|
||||||
|
@ -3911,9 +3911,6 @@ inline void UMatData::markDeviceCopyObsolete(bool flag)
|
|||||||
flags &= ~DEVICE_COPY_OBSOLETE;
|
flags &= ~DEVICE_COPY_OBSOLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline UMatDataAutoLock::UMatDataAutoLock(UMatData* _u) : u(_u) { u->lock(); }
|
|
||||||
inline UMatDataAutoLock::~UMatDataAutoLock() { u->unlock(); }
|
|
||||||
|
|
||||||
//! @endcond
|
//! @endcond
|
||||||
|
|
||||||
} //cv
|
} //cv
|
||||||
|
@ -123,6 +123,8 @@
|
|||||||
#include "opencv2/core/opencl/opencl_svm.hpp"
|
#include "opencv2/core/opencl/opencl_svm.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "umatrix.hpp"
|
||||||
|
|
||||||
namespace cv { namespace ocl {
|
namespace cv { namespace ocl {
|
||||||
|
|
||||||
#define IMPLEMENT_REFCOUNTABLE() \
|
#define IMPLEMENT_REFCOUNTABLE() \
|
||||||
@ -5424,8 +5426,7 @@ public:
|
|||||||
srcrawofs, new_srcofs, new_srcstep,
|
srcrawofs, new_srcofs, new_srcstep,
|
||||||
dstrawofs, new_dstofs, new_dststep);
|
dstrawofs, new_dstofs, new_dststep);
|
||||||
|
|
||||||
UMatDataAutoLock src_autolock(src);
|
UMatDataAutoLock src_autolock(src, dst);
|
||||||
UMatDataAutoLock dst_autolock(dst);
|
|
||||||
|
|
||||||
if( !src->handle || (src->data && src->hostCopyObsolete() < src->deviceCopyObsolete()) )
|
if( !src->handle || (src->data && src->hostCopyObsolete() < src->deviceCopyObsolete()) )
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#include "precomp.hpp"
|
#include "precomp.hpp"
|
||||||
#include "opencl_kernels_core.hpp"
|
#include "opencl_kernels_core.hpp"
|
||||||
|
#include "umatrix.hpp"
|
||||||
|
|
||||||
///////////////////////////////// UMat implementation ///////////////////////////////
|
///////////////////////////////// UMat implementation ///////////////////////////////
|
||||||
|
|
||||||
@ -127,14 +128,66 @@ UMatData::~UMatData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t getUMatDataLockIndex(const UMatData* u)
|
||||||
|
{
|
||||||
|
size_t idx = ((size_t)(void*)u) % UMAT_NLOCKS;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
void UMatData::lock()
|
void UMatData::lock()
|
||||||
{
|
{
|
||||||
umatLocks[(size_t)(void*)this % UMAT_NLOCKS].lock();
|
size_t idx = getUMatDataLockIndex(this);
|
||||||
|
//printf("%d lock(%d)\n", cv::utils::getThreadID(), (int)idx);
|
||||||
|
umatLocks[idx].lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UMatData::unlock()
|
void UMatData::unlock()
|
||||||
{
|
{
|
||||||
umatLocks[(size_t)(void*)this % UMAT_NLOCKS].unlock();
|
size_t idx = getUMatDataLockIndex(this);
|
||||||
|
//printf("%d unlock(%d)\n", cv::utils::getThreadID(), (int)idx);
|
||||||
|
umatLocks[idx].unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct UMatDataAutoLockUsage
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
UMatDataAutoLockUsage() : count(0) { }
|
||||||
|
};
|
||||||
|
static TLSData<UMatDataAutoLockUsage>& getUMatDataAutoLockUsageTLS()
|
||||||
|
{
|
||||||
|
CV_SINGLETON_LAZY_INIT_REF(TLSData<UMatDataAutoLockUsage>, new TLSData<UMatDataAutoLockUsage>());
|
||||||
|
}
|
||||||
|
static int& getUMatDataAutoLockUsage() { return getUMatDataAutoLockUsageTLS().get()->count; }
|
||||||
|
|
||||||
|
|
||||||
|
UMatDataAutoLock::UMatDataAutoLock(UMatData* u) : u1(u), u2(NULL)
|
||||||
|
{
|
||||||
|
int& usage_count = getUMatDataAutoLockUsage();
|
||||||
|
CV_Assert(usage_count == 0); // UMatDataAutoLock can't be used multiple times from the same thread
|
||||||
|
usage_count = 1;
|
||||||
|
u1->lock();
|
||||||
|
}
|
||||||
|
UMatDataAutoLock::UMatDataAutoLock(UMatData* u1_, UMatData* u2_) : u1(u1_), u2(u2_)
|
||||||
|
{
|
||||||
|
int& usage_count = getUMatDataAutoLockUsage();
|
||||||
|
CV_Assert(usage_count == 0); // UMatDataAutoLock can't be used multiple times from the same thread
|
||||||
|
usage_count = 1;
|
||||||
|
if (getUMatDataLockIndex(u1) > getUMatDataLockIndex(u2))
|
||||||
|
{
|
||||||
|
std::swap(u1, u2);
|
||||||
|
}
|
||||||
|
u1->lock();
|
||||||
|
u2->lock();
|
||||||
|
}
|
||||||
|
UMatDataAutoLock::~UMatDataAutoLock()
|
||||||
|
{
|
||||||
|
int& usage_count = getUMatDataAutoLockUsage();
|
||||||
|
CV_Assert(usage_count == 1);
|
||||||
|
usage_count = 0;
|
||||||
|
u1->unlock();
|
||||||
|
if (u2)
|
||||||
|
u2->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
20
modules/core/src/umatrix.hpp
Normal file
20
modules/core/src/umatrix.hpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||||
|
// of this distribution and at http://opencv.org/license.html.
|
||||||
|
#ifndef OPENCV_CORE_SRC_UMATRIX_HPP
|
||||||
|
#define OPENCV_CORE_SRC_UMATRIX_HPP
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
|
||||||
|
struct CV_EXPORTS UMatDataAutoLock
|
||||||
|
{
|
||||||
|
explicit UMatDataAutoLock(UMatData* u);
|
||||||
|
UMatDataAutoLock(UMatData* u1, UMatData* u2);
|
||||||
|
~UMatDataAutoLock();
|
||||||
|
UMatData* u1;
|
||||||
|
UMatData* u2;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENCV_CORE_SRC_UMATRIX_HPP
|
Loading…
Reference in New Issue
Block a user