diff options
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/llqueuedthread.cpp | 9 | ||||
-rw-r--r-- | indra/llcommon/llthread.cpp | 10 | ||||
-rw-r--r-- | indra/llcommon/lltimer.cpp | 4 | ||||
-rw-r--r-- | indra/llcommon/threadpool.cpp | 42 |
4 files changed, 63 insertions, 2 deletions
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index e5060a1076..9b1de2e9a5 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -477,9 +477,14 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req) mRequestQueue.post([=] { LL_PROFILE_ZONE_NAMED("processRequest - retry"); - while (LL::WorkQueue::TimePoint::clock::now() < retry_time) + if (LL::WorkQueue::TimePoint::clock::now() < retry_time) { - std::this_thread::yield(); //note: don't use LLThread::yield here to avoid + auto sleep_time = std::chrono::duration_cast<std::chrono::milliseconds>(retry_time - LL::WorkQueue::TimePoint::clock::now()); + + if (sleep_time.count() > 0) + { + ms_sleep(sleep_time.count()); + } } processRequest(req); }); diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index a807acc56e..4eaa05c335 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -42,6 +42,7 @@ #ifdef LL_WINDOWS + const DWORD MS_VC_EXCEPTION=0x406D1388; #pragma pack(push,8) @@ -133,6 +134,15 @@ void LLThread::threadRun() { #ifdef LL_WINDOWS set_thread_name(-1, mName.c_str()); + +#if 0 // probably a bad idea, see usage of SetThreadIdealProcessor in LLWindowWin32) + HANDLE hThread = GetCurrentThread(); + if (hThread) + { + SetThreadAffinityMask(hThread, (DWORD_PTR) 0xFFFFFFFFFFFFFFFE); + } +#endif + #endif LL_PROFILER_SET_THREAD_NAME( mName.c_str() ); diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 8739eeef00..24eaa4c1a9 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -92,6 +92,7 @@ U32 micro_sleep(U64 us, U32 max_yields) U32 micro_sleep(U64 us, U32 max_yields) { LL_PROFILE_ZONE_SCOPED +#if 0 LARGE_INTEGER ft; ft.QuadPart = -static_cast<S64>(us * 10); // '-' using relative time @@ -99,6 +100,9 @@ U32 micro_sleep(U64 us, U32 max_yields) SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); WaitForSingleObject(timer, INFINITE); CloseHandle(timer); +#else + Sleep(us / 1000); +#endif return 0; } diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index 856306d8f4..3a9a5a2062 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -23,6 +23,43 @@ #include "llsd.h" #include "stringize.h" +#include <boost/fiber/algo/round_robin.hpp> + +/***************************************************************************** +* Custom fiber scheduler for worker threads +*****************************************************************************/ +// As of 2022-12-06, each of our worker threads only runs a single (default) +// fiber: we don't launch explicit fibers within worker threads, nor do we +// anticipate doing so. So a worker thread that's simply waiting for incoming +// tasks should really sleep a little. Override the default fiber scheduler to +// implement that. +struct sleepy_robin: public boost::fibers::algo::round_robin +{ + virtual void suspend_until( std::chrono::steady_clock::time_point const&) noexcept + { +#if LL_WINDOWS + // round_robin holds a std::condition_variable, and + // round_robin::suspend_until() calls + // std::condition_variable::wait_until(). On Windows, that call seems + // busier than it ought to be. Try just sleeping. + Sleep(1); +#else + // currently unused other than windows, but might as well have something here + // different units than Sleep(), but we actually just want to sleep for any de-minimis duration + usleep(1); +#endif + } + + virtual void notify() noexcept + { + // Since our Sleep() call above will wake up on its own, we need not + // take any special action to wake it. + } +}; + +/***************************************************************************** +* ThreadPoolBase +*****************************************************************************/ LL::ThreadPoolBase::ThreadPoolBase(const std::string& name, size_t threads, WorkQueueBase* queue): super(name), @@ -81,6 +118,11 @@ void LL::ThreadPoolBase::close() void LL::ThreadPoolBase::run(const std::string& name) { +#if LL_WINDOWS + // Try using sleepy_robin fiber scheduler. + boost::fibers::use_scheduling_algorithm<sleepy_robin>(); +#endif // LL_WINDOWS + LL_DEBUGS("ThreadPool") << name << " starting" << LL_ENDL; run(); LL_DEBUGS("ThreadPool") << name << " stopping" << LL_ENDL; |