Index: clangd/Threading.h =================================================================== --- clangd/Threading.h +++ clangd/Threading.h @@ -122,6 +122,10 @@ Normal = 1, }; void setThreadPriority(std::thread &T, ThreadPriority Priority); +// Avoid the use of scheduler policies that may starve low-priority threads. +// This prevents tests from timing out on loaded systems. +// Affects subsequent setThreadPriority() calls. +void preventThreadStarvationInTests(); } // namespace clangd } // namespace clang Index: clangd/Threading.cpp =================================================================== --- clangd/Threading.cpp +++ clangd/Threading.cpp @@ -3,6 +3,7 @@ #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Threading.h" +#include #include #ifdef __USE_POSIX #include @@ -100,6 +101,8 @@ CV.wait_until(Lock, D.time()); } +static std::atomic AvoidThreadStarvation = {false}; + void setThreadPriority(std::thread &T, ThreadPriority Priority) { // Some *really* old glibcs are missing SCHED_IDLE. #if defined(__linux__) && defined(SCHED_IDLE) @@ -107,9 +110,13 @@ priority.sched_priority = 0; pthread_setschedparam( T.native_handle(), - Priority == ThreadPriority::Low ? SCHED_IDLE : SCHED_OTHER, &priority); + Priority == ThreadPriority::Low && !AvoidThreadStarvation ? SCHED_IDLE + : SCHED_OTHER, + &priority); #endif } +void preventThreadStarvationInTests() { AvoidThreadStarvation = true; } + } // namespace clangd } // namespace clang Index: clangd/tool/ClangdMain.cpp =================================================================== --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -351,6 +351,9 @@ Opts.BuildDynamicSymbolIndex = EnableIndex; Opts.HeavyweightDynamicSymbolIndex = UseDex; Opts.BackgroundIndex = EnableBackgroundIndex; + // When testing, prevent starvation of the background index to avoid timeout. + if (Test) + preventThreadStarvationInTests(); std::unique_ptr StaticIdx; std::future AsyncIndexLoad; // Block exit while loading the index. if (EnableIndex && !IndexFile.empty()) { Index: unittests/clangd/BackgroundIndexTests.cpp =================================================================== --- unittests/clangd/BackgroundIndexTests.cpp +++ unittests/clangd/BackgroundIndexTests.cpp @@ -56,7 +56,12 @@ } }; -TEST(BackgroundIndexTest, IndexTwoFiles) { +class BackgroundIndexTest : public ::testing::Test { +protected: + BackgroundIndexTest() { preventThreadStarvationInTests(); } +}; + +TEST_F(BackgroundIndexTest, IndexTwoFiles) { MockFSProvider FS; // a.h yields different symbols when included by A.cc vs B.cc. FS.Files[testPath("root/A.h")] = R"cpp( @@ -115,7 +120,7 @@ FileURI("unittest:///root/B.cc")})); } -TEST(BackgroundIndexTest, ShardStorageWriteTest) { +TEST_F(BackgroundIndexTest, ShardStorageWriteTest) { MockFSProvider FS; FS.Files[testPath("root/A.h")] = R"cpp( void common();