Skip to content

Commit 68ef903

Browse files
committed
core(tls): don't use tlsSlots without synchronization
1 parent 06407b4 commit 68ef903

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

modules/core/src/system.cpp

Lines changed: 16 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,7 @@ class TlsStorage
13931396
// Get data by TLS storage index
13941397
void* getData(size_t slotIdx) const
13951398
{
1396-
CV_Assert(tlsSlots.size() > slotIdx);
1399+
CV_Assert(tlsSlotsSize > slotIdx);
13971400

13981401
ThreadData* threadData = (ThreadData*)tls.GetData();
13991402
if(threadData && threadData->slots.size() > slotIdx)
@@ -1406,7 +1409,8 @@ class TlsStorage
14061409
void gather(size_t slotIdx, std::vector<void*> &dataVec)
14071410
{
14081411
AutoLock guard(mtxGlobalAccess);
1409-
CV_Assert(tlsSlots.size() > slotIdx);
1412+
CV_Assert(tlsSlotsSize == tlsSlots.size());
1413+
CV_Assert(tlsSlotsSize > slotIdx);
14101414

14111415
for(size_t i = 0; i < threads.size(); i++)
14121416
{
@@ -1422,7 +1426,7 @@ class TlsStorage
14221426
// Set data to storage index
14231427
void setData(size_t slotIdx, void* pData)
14241428
{
1425-
CV_Assert(tlsSlots.size() > slotIdx && pData != NULL);
1429+
CV_Assert(tlsSlotsSize > slotIdx);
14261430

14271431
ThreadData* threadData = (ThreadData*)tls.GetData();
14281432
if(!threadData)
@@ -1438,9 +1442,8 @@ class TlsStorage
14381442

14391443
if(slotIdx >= threadData->slots.size())
14401444
{
1441-
AutoLock guard(mtxGlobalAccess);
1442-
while(slotIdx >= threadData->slots.size())
1443-
threadData->slots.push_back(NULL);
1445+
AutoLock guard(mtxGlobalAccess); // keep synchronization with gather() calls
1446+
threadData->slots.resize(slotIdx + 1, NULL);
14441447
}
14451448
threadData->slots[slotIdx] = pData;
14461449
}
@@ -1449,6 +1452,8 @@ class TlsStorage
14491452
TlsAbstraction tls; // TLS abstraction layer instance
14501453

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

0 commit comments

Comments
 (0)