Skip to content
Snippets Groups Projects
Commit 3f7b060f authored by Rye Mutt's avatar Rye Mutt :bread:
Browse files

Pull in Kitty's changes to de-slow the queued thread system

parent 2b22097d
No related branches found
No related tags found
No related merge requests found
...@@ -36,9 +36,10 @@ ...@@ -36,9 +36,10 @@
LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) : LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) :
LLThread(name), LLThread(name),
mThreaded(threaded), mThreaded(threaded),
mIdleThread(TRUE), mStarted(false),
mNextHandle(0), mIdleThread(true),
mStarted(FALSE) mRequestQueueSize(0),
mNextHandle(0)
{ {
if (mThreaded) if (mThreaded)
{ {
...@@ -117,7 +118,7 @@ S32 LLQueuedThread::update(F32 max_time_ms) ...@@ -117,7 +118,7 @@ S32 LLQueuedThread::update(F32 max_time_ms)
if (!mThreaded) if (!mThreaded)
{ {
startThread(); startThread();
mStarted = TRUE; mStarted = true;
} }
} }
return updateQueue(max_time_ms); return updateQueue(max_time_ms);
...@@ -162,17 +163,6 @@ void LLQueuedThread::incQueue() ...@@ -162,17 +163,6 @@ void LLQueuedThread::incQueue()
} }
} }
//virtual
// May be called from any thread
S32 LLQueuedThread::getPending()
{
S32 res;
lockData();
res = mRequestQueue.size();
unlockData();
return res;
}
// MAIN thread // MAIN thread
void LLQueuedThread::waitOnPending() void LLQueuedThread::waitOnPending()
{ {
...@@ -236,6 +226,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req) ...@@ -236,6 +226,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
#if _DEBUG #if _DEBUG
// LL_INFOS() << llformat("LLQueuedThread::Added req [%08d]",handle) << LL_ENDL; // LL_INFOS() << llformat("LLQueuedThread::Added req [%08d]",handle) << LL_ENDL;
#endif #endif
mRequestQueueSize = mRequestQueue.size();
unlockData(); unlockData();
incQueue(); incQueue();
...@@ -289,7 +280,7 @@ LLQueuedThread::QueuedRequest* LLQueuedThread::getRequest(handle_t handle) ...@@ -289,7 +280,7 @@ LLQueuedThread::QueuedRequest* LLQueuedThread::getRequest(handle_t handle)
{ {
if (handle == nullHandle()) if (handle == nullHandle())
{ {
return 0; return nullptr;
} }
lockData(); lockData();
QueuedRequest* res = (QueuedRequest*)mRequestHash.find(handle); QueuedRequest* res = (QueuedRequest*)mRequestHash.find(handle);
...@@ -429,6 +420,10 @@ S32 LLQueuedThread::processNextRequest() ...@@ -429,6 +420,10 @@ S32 LLQueuedThread::processNextRequest()
llassert_always(req->getStatus() == STATUS_QUEUED); llassert_always(req->getStatus() == STATUS_QUEUED);
break; break;
} }
// Update queue size after processing
mRequestQueueSize = mRequestQueue.size();
U32 start_priority = 0 ; U32 start_priority = 0 ;
if (req) if (req)
{ {
...@@ -463,6 +458,7 @@ S32 LLQueuedThread::processNextRequest() ...@@ -463,6 +458,7 @@ S32 LLQueuedThread::processNextRequest()
lockData(); lockData();
req->setStatus(STATUS_QUEUED); req->setStatus(STATUS_QUEUED);
mRequestQueue.insert(req); mRequestQueue.insert(req);
mRequestQueueSize = mRequestQueue.size();
unlockData(); unlockData();
if (mThreaded && start_priority < PRIORITY_NORMAL) if (mThreaded && start_priority < PRIORITY_NORMAL)
{ {
...@@ -481,10 +477,7 @@ S32 LLQueuedThread::processNextRequest() ...@@ -481,10 +477,7 @@ S32 LLQueuedThread::processNextRequest()
bool LLQueuedThread::runCondition() bool LLQueuedThread::runCondition()
{ {
// mRunCondition must be locked here // mRunCondition must be locked here
if (mRequestQueue.empty() && mIdleThread) return !((mRequestQueueSize <= 0) && mIdleThread);
return false;
else
return true;
} }
// virtual // virtual
...@@ -493,7 +486,7 @@ void LLQueuedThread::run() ...@@ -493,7 +486,7 @@ void LLQueuedThread::run()
// call checPause() immediately so we don't try to do anything before the class is fully constructed // call checPause() immediately so we don't try to do anything before the class is fully constructed
checkPause(); checkPause();
startThread(); startThread();
mStarted = TRUE; mStarted = true;
while (1) while (1)
{ {
...@@ -507,7 +500,7 @@ void LLQueuedThread::run() ...@@ -507,7 +500,7 @@ void LLQueuedThread::run()
break; break;
} }
mIdleThread = FALSE; mIdleThread = false;
threadedUpdate(); threadedUpdate();
...@@ -515,7 +508,7 @@ void LLQueuedThread::run() ...@@ -515,7 +508,7 @@ void LLQueuedThread::run()
if (pending_work == 0) if (pending_work == 0)
{ {
mIdleThread = TRUE; mIdleThread = true;
ms_sleep(1); ms_sleep(1);
} }
//LLThread::yield(); // thread should yield after each request //LLThread::yield(); // thread should yield after each request
......
...@@ -153,11 +153,10 @@ class LL_COMMON_API LLQueuedThread : public LLThread ...@@ -153,11 +153,10 @@ class LL_COMMON_API LLQueuedThread : public LLThread
virtual ~LLQueuedThread(); virtual ~LLQueuedThread();
virtual void shutdown(); virtual void shutdown();
private: LLQueuedThread(const LLQueuedThread&) = delete;
// No copy constructor or copy assignment LLQueuedThread& operator=(const LLQueuedThread&) = delete;
LLQueuedThread(const LLQueuedThread&);
LLQueuedThread& operator=(const LLQueuedThread&);
private:
virtual bool runCondition(void); virtual bool runCondition(void);
virtual void run(void); virtual void run(void);
virtual void startThread(void); virtual void startThread(void);
...@@ -179,8 +178,8 @@ class LL_COMMON_API LLQueuedThread : public LLThread ...@@ -179,8 +178,8 @@ class LL_COMMON_API LLQueuedThread : public LLThread
void waitOnPending(); void waitOnPending();
void printQueueStats(); void printQueueStats();
virtual S32 getPending(); virtual S32 getPending() const { return mRequestQueueSize; } // May be called from any thread
bool getThreaded() { return mThreaded ? true : false; } bool getThreaded() const { return mThreaded; }
// Request accessors // Request accessors
status_t getRequestStatus(handle_t handle); status_t getRequestStatus(handle_t handle);
...@@ -196,12 +195,13 @@ class LL_COMMON_API LLQueuedThread : public LLThread ...@@ -196,12 +195,13 @@ class LL_COMMON_API LLQueuedThread : public LLThread
bool check(); bool check();
protected: protected:
BOOL mThreaded; // if false, run on main thread and do updates during update() bool mThreaded; // if false, run on main thread and do updates during update()
BOOL mStarted; // required when mThreaded is false to call startThread() from update() bool mStarted; // required when mThreaded is false to call startThread() from update()
LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t; typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
request_queue_t mRequestQueue; request_queue_t mRequestQueue;
std::atomic<S32> mRequestQueueSize;
enum { REQUEST_HASH_SIZE = 512 }; // must be power of 2 enum { REQUEST_HASH_SIZE = 512 }; // must be power of 2
typedef LLSimpleHash<handle_t, REQUEST_HASH_SIZE> request_hash_t; typedef LLSimpleHash<handle_t, REQUEST_HASH_SIZE> request_hash_t;
......
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
// Run on MAIN thread // Run on MAIN thread
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) : LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) :
LLQueuedThread(name, threaded, should_pause) LLQueuedThread(name, threaded, should_pause),
mDeleteListSize(0)
{ {
mDeleteMutex = new LLMutex(); mDeleteMutex = new LLMutex();
...@@ -76,6 +77,7 @@ void LLWorkerThread::clearDeleteList() ...@@ -76,6 +77,7 @@ void LLWorkerThread::clearDeleteList()
delete *iter ; delete *iter ;
} }
mDeleteList.clear() ; mDeleteList.clear() ;
mDeleteListSize = mDeleteList.size();
mDeleteMutex->unlock() ; mDeleteMutex->unlock() ;
} }
} }
...@@ -87,26 +89,30 @@ S32 LLWorkerThread::update(F32 max_time_ms) ...@@ -87,26 +89,30 @@ S32 LLWorkerThread::update(F32 max_time_ms)
// Delete scheduled workers // Delete scheduled workers
std::vector<LLWorkerClass*> delete_list; std::vector<LLWorkerClass*> delete_list;
std::vector<LLWorkerClass*> abort_list; std::vector<LLWorkerClass*> abort_list;
mDeleteMutex->lock(); if (mDeleteListSize)
for (delete_list_t::iterator iter = mDeleteList.begin();
iter != mDeleteList.end(); )
{ {
delete_list_t::iterator curiter = iter++; mDeleteMutex->lock();
LLWorkerClass* worker = *curiter; for (delete_list_t::iterator iter = mDeleteList.begin();
if (worker->deleteOK()) iter != mDeleteList.end(); )
{ {
if (worker->getFlags(LLWorkerClass::WCF_WORK_FINISHED)) delete_list_t::iterator curiter = iter++;
{ LLWorkerClass* worker = *curiter;
delete_list.push_back(worker); if (worker->deleteOK())
mDeleteList.erase(curiter);
}
else if (!worker->getFlags(LLWorkerClass::WCF_ABORT_REQUESTED))
{ {
abort_list.push_back(worker); if (worker->getFlags(LLWorkerClass::WCF_WORK_FINISHED))
{
delete_list.push_back(worker);
mDeleteList.erase(curiter);
}
else if (!worker->getFlags(LLWorkerClass::WCF_ABORT_REQUESTED))
{
abort_list.push_back(worker);
}
} }
} }
mDeleteListSize = mDeleteList.size();
mDeleteMutex->unlock();
} }
mDeleteMutex->unlock();
// abort and delete after releasing mutex // abort and delete after releasing mutex
for (std::vector<LLWorkerClass*>::iterator iter = abort_list.begin(); for (std::vector<LLWorkerClass*>::iterator iter = abort_list.begin();
iter != abort_list.end(); ++iter) iter != abort_list.end(); ++iter)
...@@ -154,6 +160,7 @@ void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass) ...@@ -154,6 +160,7 @@ void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass)
{ {
mDeleteMutex->lock(); mDeleteMutex->lock();
mDeleteList.push_back(workerclass); mDeleteList.push_back(workerclass);
mDeleteListSize = mDeleteList.size();
mDeleteMutex->unlock(); mDeleteMutex->unlock();
} }
......
...@@ -81,6 +81,7 @@ class LL_COMMON_API LLWorkerThread : public LLQueuedThread ...@@ -81,6 +81,7 @@ class LL_COMMON_API LLWorkerThread : public LLQueuedThread
private: private:
typedef std::list<LLWorkerClass*> delete_list_t; typedef std::list<LLWorkerClass*> delete_list_t;
delete_list_t mDeleteList; delete_list_t mDeleteList;
std::atomic<S32> mDeleteListSize;
LLMutex* mDeleteMutex; LLMutex* mDeleteMutex;
public: public:
...@@ -91,7 +92,7 @@ class LL_COMMON_API LLWorkerThread : public LLQueuedThread ...@@ -91,7 +92,7 @@ class LL_COMMON_API LLWorkerThread : public LLQueuedThread
handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL); handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
S32 getNumDeletes() { return (S32)mDeleteList.size(); } // debug S32 getNumDeletes() const { return mDeleteListSize; } // debug
private: private:
void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
// MAIN THREAD // MAIN THREAD
LLImageDecodeThread::LLImageDecodeThread(bool threaded) LLImageDecodeThread::LLImageDecodeThread(bool threaded)
: LLQueuedThread("imagedecode", threaded) : LLQueuedThread("imagedecode", threaded)
, mCreationListSize(0)
{ {
mCreationMutex = new LLMutex(); mCreationMutex = new LLMutex();
} }
...@@ -48,22 +49,26 @@ LLImageDecodeThread::~LLImageDecodeThread() ...@@ -48,22 +49,26 @@ LLImageDecodeThread::~LLImageDecodeThread()
// virtual // virtual
S32 LLImageDecodeThread::update(F32 max_time_ms) S32 LLImageDecodeThread::update(F32 max_time_ms)
{ {
LLMutexLock lock(mCreationMutex); if (mCreationListSize > 0)
for (creation_list_t::iterator iter = mCreationList.begin();
iter != mCreationList.end(); ++iter)
{ {
creation_info& info = *iter; LLMutexLock lock(mCreationMutex);
ImageRequest* req = new ImageRequest(info.handle, info.image, for (creation_list_t::iterator iter = mCreationList.begin();
info.priority, info.discard, info.needs_aux, iter != mCreationList.end(); ++iter)
info.responder);
bool res = addRequest(req);
if (!res)
{ {
LL_ERRS() << "request added after LLLFSThread::cleanupClass()" << LL_ENDL; creation_info& info = *iter;
ImageRequest* req = new ImageRequest(info.handle, info.image,
info.priority, info.discard, info.needs_aux,
info.responder);
bool res = addRequest(req);
if (!res)
{
LL_ERRS() << "request added after LLLFSThread::cleanupClass()" << LL_ENDL;
}
} }
mCreationList.clear();
mCreationListSize = 0;
} }
mCreationList.clear();
S32 res = LLQueuedThread::update(max_time_ms); S32 res = LLQueuedThread::update(max_time_ms);
return res; return res;
} }
...@@ -74,6 +79,7 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* ...@@ -74,6 +79,7 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted*
LLMutexLock lock(mCreationMutex); LLMutexLock lock(mCreationMutex);
handle_t handle = generateHandle(); handle_t handle = generateHandle();
mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder)); mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
mCreationListSize = mCreationList.size();
return handle; return handle;
} }
......
...@@ -86,18 +86,20 @@ class LLImageDecodeThread : public LLQueuedThread ...@@ -86,18 +86,20 @@ class LLImageDecodeThread : public LLQueuedThread
private: private:
struct creation_info struct creation_info
{ {
handle_t handle;
LLPointer<LLImageFormatted> image; LLPointer<LLImageFormatted> image;
LLPointer<Responder> responder;
handle_t handle;
U32 priority; U32 priority;
S32 discard; S32 discard;
BOOL needs_aux; BOOL needs_aux;
LLPointer<Responder> responder;
creation_info(handle_t h, LLImageFormatted* i, U32 p, S32 d, BOOL aux, Responder* r) creation_info(handle_t h, LLImageFormatted* i, U32 p, S32 d, BOOL aux, Responder* r)
: handle(h), image(i), priority(p), discard(d), needs_aux(aux), responder(r) : image(i), responder(r), handle(h), priority(p), discard(d), needs_aux(aux)
{} {}
}; };
typedef std::list<creation_info> creation_list_t; typedef std::list<creation_info> creation_list_t;
creation_list_t mCreationList; creation_list_t mCreationList;
std::atomic<S32> mCreationListSize;
LLMutex* mCreationMutex; LLMutex* mCreationMutex;
}; };
......
...@@ -831,6 +831,8 @@ LLTextureCache::LLTextureCache(bool threaded) ...@@ -831,6 +831,8 @@ LLTextureCache::LLTextureCache(bool threaded)
mListMutex(), mListMutex(),
mFastCacheMutex(), mFastCacheMutex(),
mHeaderAPRFile(NULL), mHeaderAPRFile(NULL),
mPrioritizeWriteListEmpty(true),
mCompletedListEmpty(true),
mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called. mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called.
mTexturesSizeTotal(0), mTexturesSizeTotal(0),
mDoPurge(FALSE), mDoPurge(FALSE),
...@@ -862,35 +864,41 @@ S32 LLTextureCache::update(F32 max_time_ms) ...@@ -862,35 +864,41 @@ S32 LLTextureCache::update(F32 max_time_ms)
S32 res; S32 res;
res = LLWorkerThread::update(max_time_ms); res = LLWorkerThread::update(max_time_ms);
mListMutex.lock(); handle_list_t priorty_list;
handle_list_t priorty_list = mPrioritizeWriteList; // copy list responder_list_t completed_list;
mPrioritizeWriteList.clear(); if ((!mPrioritizeWriteListEmpty) || (!mCompletedListEmpty))
responder_list_t completed_list = mCompletedList; // copy list {
mCompletedList.clear(); LLMutexLock lock(&mListMutex);
mListMutex.unlock(); priorty_list.swap(mPrioritizeWriteList); // copy list
mPrioritizeWriteList.clear();
lockWorkers(); mPrioritizeWriteListEmpty = mPrioritizeWriteList.empty();
completed_list.swap(mCompletedList); // copy list
mCompletedList.clear();
mCompletedListEmpty = mCompletedList.empty();
}
for (handle_list_t::iterator iter1 = priorty_list.begin(); if (!priorty_list.empty())
iter1 != priorty_list.end(); ++iter1)
{ {
handle_t handle = *iter1; lockWorkers();
handle_map_t::iterator iter2 = mWriters.find(handle);
if(iter2 != mWriters.end()) for (handle_t handle : priorty_list)
{ {
LLTextureCacheWorker* worker = iter2->second; handle_map_t::iterator iter2 = mWriters.find(handle);
worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mPriority); if (iter2 != mWriters.end())
{
LLTextureCacheWorker* worker = iter2->second;
worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mPriority);
}
} }
}
unlockWorkers(); unlockWorkers();
}
// call 'completed' with workers list unlocked (may call readComplete() or writeComplete() // call 'completed' with workers list unlocked (may call readComplete() or writeComplete()
for (responder_list_t::iterator iter1 = completed_list.begin(); for (auto& iter1 : completed_list)
iter1 != completed_list.end(); ++iter1) {
{ Responder *responder = iter1.first;
Responder *responder = iter1->first; bool success = iter1.second;
bool success = iter1->second;
responder->completed(success); responder->completed(success);
} }
...@@ -917,7 +925,7 @@ std::string LLTextureCache::getLocalFileName(const LLUUID& id) ...@@ -917,7 +925,7 @@ std::string LLTextureCache::getLocalFileName(const LLUUID& id)
std::string LLTextureCache::getTextureFileName(const LLUUID& id) std::string LLTextureCache::getTextureFileName(const LLUUID& id)
{ {
std::string idstr = id.asString(); std::string idstr = id.asString();
std::string delem = gDirUtilp->getDirDelimiter(); const std::string& delem = gDirUtilp->getDirDelimiter();
std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr + ".texture"; std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr + ".texture";
return filename; return filename;
} }
...@@ -993,8 +1001,6 @@ const char* fast_cache_filename = "FastCache.cache"; ...@@ -993,8 +1001,6 @@ const char* fast_cache_filename = "FastCache.cache";
void LLTextureCache::setDirNames(ELLPath location) void LLTextureCache::setDirNames(ELLPath location)
{ {
std::string delem = gDirUtilp->getDirDelimiter();
mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, entries_filename); mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, entries_filename);
mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, cache_filename); mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, cache_filename);
mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname); mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname);
...@@ -2300,12 +2306,14 @@ void LLTextureCache::prioritizeWrite(handle_t handle) ...@@ -2300,12 +2306,14 @@ void LLTextureCache::prioritizeWrite(handle_t handle)
// which could create a deadlock // which could create a deadlock
LLMutexLock lock(&mListMutex); LLMutexLock lock(&mListMutex);
mPrioritizeWriteList.push_back(handle); mPrioritizeWriteList.push_back(handle);
mPrioritizeWriteListEmpty = mPrioritizeWriteList.empty();
} }
void LLTextureCache::addCompleted(Responder* responder, bool success) void LLTextureCache::addCompleted(Responder* responder, bool success)
{ {
LLMutexLock lock(&mListMutex); LLMutexLock lock(&mListMutex);
mCompletedList.push_back(std::make_pair(responder,success)); mCompletedList.push_back(std::make_pair(responder,success));
mCompletedListEmpty = mCompletedList.empty();
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
......
...@@ -210,9 +210,11 @@ class LLTextureCache : public LLWorkerThread ...@@ -210,9 +210,11 @@ class LLTextureCache : public LLWorkerThread
typedef std::vector<handle_t> handle_list_t; typedef std::vector<handle_t> handle_list_t;
handle_list_t mPrioritizeWriteList; handle_list_t mPrioritizeWriteList;
std::atomic<bool> mPrioritizeWriteListEmpty;
typedef std::vector<std::pair<LLPointer<Responder>, bool> > responder_list_t; typedef std::vector<std::pair<LLPointer<Responder>, bool> > responder_list_t;
responder_list_t mCompletedList; responder_list_t mCompletedList;
std::atomic<bool> mCompletedListEmpty;
BOOL mReadOnly; BOOL mReadOnly;
......
...@@ -2569,8 +2569,9 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image ...@@ -2569,8 +2569,9 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mTextureCache(cache), mTextureCache(cache),
mImageDecodeThread(imagedecodethread), mImageDecodeThread(imagedecodethread),
mTextureBandwidth(0), mTextureBandwidth(0),
mHTTPTextureBits(0), mHTTPTextureBits((U32Bits)0),
mTotalHTTPRequests(0), mTotalHTTPRequests(0),
mCommandsSize(0),
mQAMode(qa_mode), mQAMode(qa_mode),
mHttpRequest(NULL), mHttpRequest(NULL),
mHttpOptions(), mHttpOptions(),
...@@ -2632,6 +2633,7 @@ LLTextureFetch::~LLTextureFetch() ...@@ -2632,6 +2633,7 @@ LLTextureFetch::~LLTextureFetch()
mCommands.erase(mCommands.begin()); mCommands.erase(mCommands.begin());
delete req; delete req;
} }
mCommandsSize = 0;
mHttpWaitResource.clear(); mHttpWaitResource.clear();
...@@ -2814,7 +2816,7 @@ void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32Bytes received_siz ...@@ -2814,7 +2816,7 @@ void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32Bytes received_siz
{ {
LLMutexLock lock(&mNetworkQueueMutex); // +Mfnq LLMutexLock lock(&mNetworkQueueMutex); // +Mfnq
mHTTPTextureQueue.erase(id); mHTTPTextureQueue.erase(id);
mHTTPTextureBits += received_size; // Approximate - does not include header bits mHTTPTextureBits = U32Bits(mHTTPTextureBits) + received_size;
} // -Mfnq } // -Mfnq
// NB: If you change deleteRequest() you should probably make // NB: If you change deleteRequest() you should probably make
...@@ -3013,54 +3015,12 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) ...@@ -3013,54 +3015,12 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
return res; return res;
} }
// Replicates and expands upon the base class's
// getPending() implementation. getPending() and
// runCondition() replicate one another's logic to
// an extent and are sometimes used for the same
// function (deciding whether or not to sleep/pause
// a thread). So the implementations need to stay
// in step, at least until this can be refactored and
// the redundancy eliminated.
//
// Threads: T*
//virtual
S32 LLTextureFetch::getPending()
{
S32 res;
lockData(); // +Ct
{
LLMutexLock lock(&mQueueMutex); // +Mfq
res = mRequestQueue.size();
res += mCommands.size();
} // -Mfq
unlockData(); // -Ct
return res;
}
// Locks: Ct // Locks: Ct
// virtual // virtual
bool LLTextureFetch::runCondition() bool LLTextureFetch::runCondition()
{ {
// Caller is holding the lock on LLThread's condition variable. return ! ( !mCommandsSize && (!mRequestQueueSize && mIdleThread) ); // From base class
// LLQueuedThread, unlike its base class LLThread, makes this a
// private method which is unfortunate. I want to use it directly
// but I'm going to have to re-implement the logic here (or change
// declarations, which I don't want to do right now).
//
// Changes here may need to be reflected in getPending().
bool have_no_commands(false);
{
LLMutexLock lock(&mQueueMutex); // +Mfq
have_no_commands = mCommands.empty();
} // -Mfq
return ! (have_no_commands
&& (mRequestQueue.empty() && mIdleThread)); // From base class
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
...@@ -3104,16 +3064,12 @@ void LLTextureFetch::commonUpdate() ...@@ -3104,16 +3064,12 @@ void LLTextureFetch::commonUpdate()
//virtual //virtual
S32 LLTextureFetch::update(F32 max_time_ms) S32 LLTextureFetch::update(F32 max_time_ms)
{ {
static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS", 3000.0); static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS", 3000.0f);
{ {
mNetworkQueueMutex.lock(); // +Mfnq
mMaxBandwidth = band_width(); mMaxBandwidth = band_width();
add(LLStatViewer::TEXTURE_NETWORK_DATA_RECEIVED, mHTTPTextureBits); add(LLStatViewer::TEXTURE_NETWORK_DATA_RECEIVED, mHTTPTextureBits.exchange((U32Bits)0));
mHTTPTextureBits = (U32Bits)0;
mNetworkQueueMutex.unlock(); // -Mfnq
} }
S32 res = LLWorkerThread::update(max_time_ms); S32 res = LLWorkerThread::update(max_time_ms);
...@@ -3288,10 +3244,9 @@ void LLTextureFetch::sendRequestListToSimulators() ...@@ -3288,10 +3244,9 @@ void LLTextureFetch::sendRequestListToSimulators()
} }
} // -Mfnq } // -Mfnq
for (work_request_map_t::iterator iter1 = requests.begin(); for (auto& request : requests)
iter1 != requests.end(); ++iter1) {
{ LLHost host = request.first;
LLHost host = iter1->first;
// invalid host = use agent host // invalid host = use agent host
if (host.isInvalid()) if (host.isInvalid())
{ {
...@@ -3300,10 +3255,8 @@ void LLTextureFetch::sendRequestListToSimulators() ...@@ -3300,10 +3255,8 @@ void LLTextureFetch::sendRequestListToSimulators()
S32 sim_request_count = 0; S32 sim_request_count = 0;
for (request_list_t::iterator iter2 = iter1->second.begin(); for (LLTextureFetchWorker* req : request.second)
iter2 != iter1->second.end(); ++iter2) {
{
LLTextureFetchWorker* req = *iter2;
if (gMessageSystem) if (gMessageSystem)
{ {
if (req->mSentRequest != LLTextureFetchWorker::SENT_SIM) if (req->mSentRequest != LLTextureFetchWorker::SENT_SIM)
...@@ -3932,6 +3885,7 @@ void LLTextureFetch::cmdEnqueue(TFRequest * req) ...@@ -3932,6 +3885,7 @@ void LLTextureFetch::cmdEnqueue(TFRequest * req)
{ {
lockQueue(); // +Mfq lockQueue(); // +Mfq
mCommands.push_back(req); mCommands.push_back(req);
mCommandsSize = mCommands.size();
unlockQueue(); // -Mfq unlockQueue(); // -Mfq
unpause(); unpause();
...@@ -3948,6 +3902,7 @@ LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue() ...@@ -3948,6 +3902,7 @@ LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue()
ret = mCommands.front(); ret = mCommands.front();
mCommands.pop_front(); mCommands.pop_front();
} }
mCommandsSize = mCommands.size();
unlockQueue(); // -Mfq unlockQueue(); // -Mfq
return ret; return ret;
......
...@@ -135,7 +135,7 @@ class LLTextureFetch : public LLWorkerThread ...@@ -135,7 +135,7 @@ class LLTextureFetch : public LLWorkerThread
U32 getTotalNumHTTPRequests(); U32 getTotalNumHTTPRequests();
// Threads: T* // Threads: T*
S32 getPending(); S32 getPending() const override { return mCommandsSize + mRequestQueueSize; }
// Threads: T* // Threads: T*
void lockQueue() { mQueueMutex.lock(); } void lockQueue() { mQueueMutex.lock(); }
...@@ -332,12 +332,12 @@ class LLTextureFetch : public LLWorkerThread ...@@ -332,12 +332,12 @@ class LLTextureFetch : public LLWorkerThread
typedef std::map<LLHost,std::set<LLUUID> > cancel_queue_t; typedef std::map<LLHost,std::set<LLUUID> > cancel_queue_t;
cancel_queue_t mCancelQueue; // Mfnq cancel_queue_t mCancelQueue; // Mfnq
F32 mTextureBandwidth; // <none> F32 mTextureBandwidth; // <none>
F32 mMaxBandwidth; // Mfnq std::atomic<F32> mMaxBandwidth;
LLTextureInfo mTextureInfo; LLTextureInfo mTextureInfo;
LLTextureInfo mTextureInfoMainThread; LLTextureInfo mTextureInfoMainThread;
// XXX possible delete // XXX possible delete
U32Bits mHTTPTextureBits; // Mfnq std::atomic<U32Bits> mHTTPTextureBits;
// XXX possible delete // XXX possible delete
//debug use //debug use
...@@ -349,6 +349,7 @@ class LLTextureFetch : public LLWorkerThread ...@@ -349,6 +349,7 @@ class LLTextureFetch : public LLWorkerThread
// same locks. // same locks.
typedef std::deque<TFRequest *> command_queue_t; typedef std::deque<TFRequest *> command_queue_t;
command_queue_t mCommands; // Mfq command_queue_t mCommands; // Mfq
std::atomic<S32> mCommandsSize;
// If true, modifies some behaviors that help with QA tasks. // If true, modifies some behaviors that help with QA tasks.
const bool mQAMode; const bool mQAMode;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment