Skip to content

Commit 42e1fe3

Browse files
committed
ocl: allow recursive UMatData lock() calls with the same objects
OpenCLAllocator::copy() may call upload()/download() methods
1 parent 0c07836 commit 42e1fe3

File tree

1 file changed

+56
-21
lines changed

1 file changed

+56
-21
lines changed

modules/core/src/umatrix.cpp

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -149,45 +149,80 @@ void UMatData::unlock()
149149
}
150150

151151

152-
struct UMatDataAutoLockUsage
152+
// Do not allow several lock() calls with different UMatData objects.
153+
struct UMatDataAutoLocker
153154
{
154-
int count;
155-
UMatDataAutoLockUsage() : count(0) { }
155+
int usage_count;
156+
UMatData* locked_objects[2];
157+
UMatDataAutoLocker() : usage_count(0) { locked_objects[0] = NULL; locked_objects[1] = NULL; }
158+
159+
void lock(UMatData*& u1)
160+
{
161+
bool locked_1 = (u1 == locked_objects[0] || u1 == locked_objects[1]);
162+
if (locked_1)
163+
{
164+
u1 = NULL;
165+
return;
166+
}
167+
CV_Assert(usage_count == 0); // UMatDataAutoLock can't be used multiple times from the same thread
168+
usage_count = 1;
169+
locked_objects[0] = u1;
170+
u1->lock();
171+
}
172+
void lock(UMatData*& u1, UMatData*& u2)
173+
{
174+
bool locked_1 = (u1 == locked_objects[0] || u1 == locked_objects[1]);
175+
bool locked_2 = (u2 == locked_objects[0] || u2 == locked_objects[1]);
176+
if (locked_1)
177+
u1 = NULL;
178+
if (locked_2)
179+
u2 = NULL;
180+
if (locked_1 && locked_2)
181+
return;
182+
CV_Assert(usage_count == 0); // UMatDataAutoLock can't be used multiple times from the same thread
183+
usage_count = 1;
184+
locked_objects[0] = u1;
185+
locked_objects[1] = u2;
186+
if (u1)
187+
u1->lock();
188+
if (u2)
189+
u2->lock();
190+
}
191+
void release(UMatData* u1, UMatData* u2)
192+
{
193+
if (u1 == NULL && u2 == NULL)
194+
return;
195+
CV_Assert(usage_count == 1);
196+
usage_count = 0;
197+
if (u1)
198+
u1->unlock();
199+
if (u2)
200+
u2->unlock();
201+
locked_objects[0] = NULL; locked_objects[1] = NULL;
202+
}
156203
};
157-
static TLSData<UMatDataAutoLockUsage>& getUMatDataAutoLockUsageTLS()
204+
static TLSData<UMatDataAutoLocker>& getUMatDataAutoLockerTLS()
158205
{
159-
CV_SINGLETON_LAZY_INIT_REF(TLSData<UMatDataAutoLockUsage>, new TLSData<UMatDataAutoLockUsage>());
206+
CV_SINGLETON_LAZY_INIT_REF(TLSData<UMatDataAutoLocker>, new TLSData<UMatDataAutoLocker>());
160207
}
161-
static int& getUMatDataAutoLockUsage() { return getUMatDataAutoLockUsageTLS().get()->count; }
208+
static UMatDataAutoLocker& getUMatDataAutoLocker() { return getUMatDataAutoLockerTLS().getRef(); }
162209

163210

164211
UMatDataAutoLock::UMatDataAutoLock(UMatData* u) : u1(u), u2(NULL)
165212
{
166-
int& usage_count = getUMatDataAutoLockUsage();
167-
CV_Assert(usage_count == 0); // UMatDataAutoLock can't be used multiple times from the same thread
168-
usage_count = 1;
169-
u1->lock();
213+
getUMatDataAutoLocker().lock(u1);
170214
}
171215
UMatDataAutoLock::UMatDataAutoLock(UMatData* u1_, UMatData* u2_) : u1(u1_), u2(u2_)
172216
{
173-
int& usage_count = getUMatDataAutoLockUsage();
174-
CV_Assert(usage_count == 0); // UMatDataAutoLock can't be used multiple times from the same thread
175-
usage_count = 1;
176217
if (getUMatDataLockIndex(u1) > getUMatDataLockIndex(u2))
177218
{
178219
std::swap(u1, u2);
179220
}
180-
u1->lock();
181-
u2->lock();
221+
getUMatDataAutoLocker().lock(u1, u2);
182222
}
183223
UMatDataAutoLock::~UMatDataAutoLock()
184224
{
185-
int& usage_count = getUMatDataAutoLockUsage();
186-
CV_Assert(usage_count == 1);
187-
usage_count = 0;
188-
u1->unlock();
189-
if (u2)
190-
u2->unlock();
225+
getUMatDataAutoLocker().release(u1, u2);
191226
}
192227

193228

0 commit comments

Comments
 (0)