Skip to content

Commit fffd0f5

Browse files
committed
Merge pull request opencv#9241 from alalek:tlsSlotsSize
2 parents 34f9c03 + d35422b commit fffd0f5

File tree

2 files changed

+31
-11
lines changed

2 files changed

+31
-11
lines changed

modules/core/include/opencv2/core/cvdef.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,17 @@ Cv64suf;
327327
# endif
328328
#endif
329329

330+
/****************************************************************************************\
331+
* Thread sanitizer *
332+
\****************************************************************************************/
333+
#ifndef CV_THREAD_SANITIZER
334+
# if defined(__has_feature)
335+
# if __has_feature(thread_sanitizer)
336+
# define CV_THREAD_SANITIZER
337+
# endif
338+
# endif
339+
#endif
340+
330341
/****************************************************************************************\
331342
* exchange-add operation for atomic operations on reference counters *
332343
\****************************************************************************************/

modules/core/src/system.cpp

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,7 +1306,8 @@ struct ThreadData
13061306
class TlsStorage
13071307
{
13081308
public:
1309-
TlsStorage()
1309+
TlsStorage() :
1310+
tlsSlotsSize(0)
13101311
{
13111312
tlsSlots.reserve(32);
13121313
threads.reserve(32);
@@ -1351,9 +1352,10 @@ class TlsStorage
13511352
size_t reserveSlot()
13521353
{
13531354
AutoLock guard(mtxGlobalAccess);
1355+
CV_Assert(tlsSlotsSize == tlsSlots.size());
13541356

13551357
// Find unused slots
1356-
for(size_t slot = 0; slot < tlsSlots.size(); slot++)
1358+
for(size_t slot = 0; slot < tlsSlotsSize; slot++)
13571359
{
13581360
if(!tlsSlots[slot])
13591361
{
@@ -1363,15 +1365,16 @@ class TlsStorage
13631365
}
13641366

13651367
// Create new slot
1366-
tlsSlots.push_back(1);
1367-
return (tlsSlots.size()-1);
1368+
tlsSlots.push_back(1); tlsSlotsSize++;
1369+
return tlsSlotsSize - 1;
13681370
}
13691371

13701372
// Release TLS storage index and pass associated data to caller
13711373
void releaseSlot(size_t slotIdx, std::vector<void*> &dataVec, bool keepSlot = false)
13721374
{
13731375
AutoLock guard(mtxGlobalAccess);
1374-
CV_Assert(tlsSlots.size() > slotIdx);
1376+
CV_Assert(tlsSlotsSize == tlsSlots.size());
1377+
CV_Assert(tlsSlotsSize > slotIdx);
13751378

13761379
for(size_t i = 0; i < threads.size(); i++)
13771380
{
@@ -1393,7 +1396,9 @@ class TlsStorage
13931396
// Get data by TLS storage index
13941397
void* getData(size_t slotIdx) const
13951398
{
1396-
CV_Assert(tlsSlots.size() > slotIdx);
1399+
#ifndef CV_THREAD_SANITIZER
1400+
CV_Assert(tlsSlotsSize > slotIdx);
1401+
#endif
13971402

13981403
ThreadData* threadData = (ThreadData*)tls.GetData();
13991404
if(threadData && threadData->slots.size() > slotIdx)
@@ -1406,7 +1411,8 @@ class TlsStorage
14061411
void gather(size_t slotIdx, std::vector<void*> &dataVec)
14071412
{
14081413
AutoLock guard(mtxGlobalAccess);
1409-
CV_Assert(tlsSlots.size() > slotIdx);
1414+
CV_Assert(tlsSlotsSize == tlsSlots.size());
1415+
CV_Assert(tlsSlotsSize > slotIdx);
14101416

14111417
for(size_t i = 0; i < threads.size(); i++)
14121418
{
@@ -1422,7 +1428,9 @@ class TlsStorage
14221428
// Set data to storage index
14231429
void setData(size_t slotIdx, void* pData)
14241430
{
1425-
CV_Assert(tlsSlots.size() > slotIdx && pData != NULL);
1431+
#ifndef CV_THREAD_SANITIZER
1432+
CV_Assert(tlsSlotsSize > slotIdx);
1433+
#endif
14261434

14271435
ThreadData* threadData = (ThreadData*)tls.GetData();
14281436
if(!threadData)
@@ -1438,9 +1446,8 @@ class TlsStorage
14381446

14391447
if(slotIdx >= threadData->slots.size())
14401448
{
1441-
AutoLock guard(mtxGlobalAccess);
1442-
while(slotIdx >= threadData->slots.size())
1443-
threadData->slots.push_back(NULL);
1449+
AutoLock guard(mtxGlobalAccess); // keep synchronization with gather() calls
1450+
threadData->slots.resize(slotIdx + 1, NULL);
14441451
}
14451452
threadData->slots[slotIdx] = pData;
14461453
}
@@ -1449,6 +1456,8 @@ class TlsStorage
14491456
TlsAbstraction tls; // TLS abstraction layer instance
14501457

14511458
Mutex mtxGlobalAccess; // Shared objects operation guard
1459+
size_t tlsSlotsSize; // equal to tlsSlots.size() in synchronized sections
1460+
// without synchronization this counter doesn't desrease - it is used for slotIdx sanity checks
14521461
std::vector<int> tlsSlots; // TLS keys state
14531462
std::vector<ThreadData*> threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup
14541463
};

0 commit comments

Comments
 (0)