Commit 68ef903a authored by Alexander Alekhin's avatar Alexander Alekhin

core(tls): don't use tlsSlots without synchronization

parent 06407b4d
...@@ -1306,7 +1306,8 @@ struct ThreadData ...@@ -1306,7 +1306,8 @@ struct ThreadData
class TlsStorage class TlsStorage
{ {
public: public:
TlsStorage() TlsStorage() :
tlsSlotsSize(0)
{ {
tlsSlots.reserve(32); tlsSlots.reserve(32);
threads.reserve(32); threads.reserve(32);
...@@ -1351,9 +1352,10 @@ public: ...@@ -1351,9 +1352,10 @@ public:
size_t reserveSlot() size_t reserveSlot()
{ {
AutoLock guard(mtxGlobalAccess); AutoLock guard(mtxGlobalAccess);
CV_Assert(tlsSlotsSize == tlsSlots.size());
// Find unused slots // Find unused slots
for(size_t slot = 0; slot < tlsSlots.size(); slot++) for(size_t slot = 0; slot < tlsSlotsSize; slot++)
{ {
if(!tlsSlots[slot]) if(!tlsSlots[slot])
{ {
...@@ -1363,15 +1365,16 @@ public: ...@@ -1363,15 +1365,16 @@ public:
} }
// Create new slot // Create new slot
tlsSlots.push_back(1); tlsSlots.push_back(1); tlsSlotsSize++;
return (tlsSlots.size()-1); return tlsSlotsSize - 1;
} }
// Release TLS storage index and pass associated data to caller // Release TLS storage index and pass associated data to caller
void releaseSlot(size_t slotIdx, std::vector<void*> &dataVec, bool keepSlot = false) void releaseSlot(size_t slotIdx, std::vector<void*> &dataVec, bool keepSlot = false)
{ {
AutoLock guard(mtxGlobalAccess); AutoLock guard(mtxGlobalAccess);
CV_Assert(tlsSlots.size() > slotIdx); CV_Assert(tlsSlotsSize == tlsSlots.size());
CV_Assert(tlsSlotsSize > slotIdx);
for(size_t i = 0; i < threads.size(); i++) for(size_t i = 0; i < threads.size(); i++)
{ {
...@@ -1393,7 +1396,7 @@ public: ...@@ -1393,7 +1396,7 @@ public:
// Get data by TLS storage index // Get data by TLS storage index
void* getData(size_t slotIdx) const void* getData(size_t slotIdx) const
{ {
CV_Assert(tlsSlots.size() > slotIdx); CV_Assert(tlsSlotsSize > slotIdx);
ThreadData* threadData = (ThreadData*)tls.GetData(); ThreadData* threadData = (ThreadData*)tls.GetData();
if(threadData && threadData->slots.size() > slotIdx) if(threadData && threadData->slots.size() > slotIdx)
...@@ -1406,7 +1409,8 @@ public: ...@@ -1406,7 +1409,8 @@ public:
void gather(size_t slotIdx, std::vector<void*> &dataVec) void gather(size_t slotIdx, std::vector<void*> &dataVec)
{ {
AutoLock guard(mtxGlobalAccess); AutoLock guard(mtxGlobalAccess);
CV_Assert(tlsSlots.size() > slotIdx); CV_Assert(tlsSlotsSize == tlsSlots.size());
CV_Assert(tlsSlotsSize > slotIdx);
for(size_t i = 0; i < threads.size(); i++) for(size_t i = 0; i < threads.size(); i++)
{ {
...@@ -1422,7 +1426,7 @@ public: ...@@ -1422,7 +1426,7 @@ public:
// Set data to storage index // Set data to storage index
void setData(size_t slotIdx, void* pData) void setData(size_t slotIdx, void* pData)
{ {
CV_Assert(tlsSlots.size() > slotIdx && pData != NULL); CV_Assert(tlsSlotsSize > slotIdx);
ThreadData* threadData = (ThreadData*)tls.GetData(); ThreadData* threadData = (ThreadData*)tls.GetData();
if(!threadData) if(!threadData)
...@@ -1438,9 +1442,8 @@ public: ...@@ -1438,9 +1442,8 @@ public:
if(slotIdx >= threadData->slots.size()) if(slotIdx >= threadData->slots.size())
{ {
AutoLock guard(mtxGlobalAccess); AutoLock guard(mtxGlobalAccess); // keep synchronization with gather() calls
while(slotIdx >= threadData->slots.size()) threadData->slots.resize(slotIdx + 1, NULL);
threadData->slots.push_back(NULL);
} }
threadData->slots[slotIdx] = pData; threadData->slots[slotIdx] = pData;
} }
...@@ -1449,6 +1452,8 @@ private: ...@@ -1449,6 +1452,8 @@ private:
TlsAbstraction tls; // TLS abstraction layer instance TlsAbstraction tls; // TLS abstraction layer instance
Mutex mtxGlobalAccess; // Shared objects operation guard Mutex mtxGlobalAccess; // Shared objects operation guard
size_t tlsSlotsSize; // equal to tlsSlots.size() in synchronized sections
// without synchronization this counter doesn't desrease - it is used for slotIdx sanity checks
std::vector<int> tlsSlots; // TLS keys state std::vector<int> tlsSlots; // TLS keys state
std::vector<ThreadData*> threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup std::vector<ThreadData*> threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment