Index: clangd/Threading.h =================================================================== --- clangd/Threading.h +++ clangd/Threading.h @@ -117,16 +117,6 @@ std::size_t InFlightTasks = 0; }; -enum class ThreadPriority { - Low = 0, - Normal = 1, -}; -void setCurrentThreadPriority(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 #endif Index: clangd/Threading.cpp =================================================================== --- clangd/Threading.cpp +++ clangd/Threading.cpp @@ -113,33 +113,5 @@ CV.wait_until(Lock, D.time()); } -static std::atomic AvoidThreadStarvation = {false}; - -void setCurrentThreadPriority(ThreadPriority Priority) { - // Some *really* old glibcs are missing SCHED_IDLE. -#if defined(__linux__) && defined(SCHED_IDLE) - sched_param priority; - priority.sched_priority = 0; - pthread_setschedparam( - pthread_self(), - Priority == ThreadPriority::Low && !AvoidThreadStarvation ? SCHED_IDLE - : SCHED_OTHER, - &priority); -#elif defined(__APPLE__) - // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getpriority.2.html - setpriority(PRIO_DARWIN_THREAD, 0, - Priority == ThreadPriority::Low && !AvoidThreadStarvation - ? PRIO_DARWIN_BG - : 0); -#elif defined(_WIN32) - SetThreadPriority(GetCurrentThread(), - Priority == ThreadPriority::Low && !AvoidThreadStarvation - ? THREAD_MODE_BACKGROUND_BEGIN - : THREAD_MODE_BACKGROUND_END); -#endif -} - -void preventThreadStarvationInTests() { AvoidThreadStarvation = true; } - } // namespace clangd } // namespace clang Index: clangd/index/Background.h =================================================================== --- clangd/index/Background.h +++ clangd/index/Background.h @@ -88,6 +88,10 @@ LLVM_NODISCARD bool blockUntilIdleForTest(llvm::Optional TimeoutSeconds = 10); + // Disables thread priority lowering in background index to make sure it can + // progress on loaded systems. Only affects tasks that run after the call. + static void preventThreadStarvationInTests(); + private: /// Given index results from a TU, only update symbols coming from files with /// different digests than \p DigestsSnapshot. Also stores new index @@ -134,14 +138,14 @@ // queue management using Task = std::function; void run(); // Main loop executed by Thread. Runs tasks from Queue. - void enqueueTask(Task T, ThreadPriority Prioirty); + void enqueueTask(Task T, llvm::ThreadPriority Prioirty); void enqueueLocked(tooling::CompileCommand Cmd, BackgroundIndexStorage *IndexStorage); std::mutex QueueMu; unsigned NumActiveTasks = 0; // Only idle when queue is empty *and* no tasks. std::condition_variable QueueCV; bool ShouldStop = false; - std::deque> Queue; + std::deque> Queue; std::vector ThreadPool; // FIXME: Abstract this away. GlobalCompilationDatabase::CommandChanged::Subscription CommandsChanged; }; Index: clangd/index/Background.cpp =================================================================== --- clangd/index/Background.cpp +++ clangd/index/Background.cpp @@ -26,7 +26,9 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/SHA1.h" +#include "llvm/Support/Threading.h" +#include #include #include #include @@ -38,6 +40,9 @@ namespace clang { namespace clangd { namespace { + +static std::atomic PreventStarvation = {false}; + // Resolves URI to file paths with cache. class URIToFileCache { public: @@ -172,7 +177,7 @@ WithContext Background(BackgroundContext.clone()); while (true) { llvm::Optional Task; - ThreadPriority Priority; + llvm::ThreadPriority Priority; { std::unique_lock Lock(QueueMu); QueueCV.wait(Lock, [&] { return ShouldStop || !Queue.empty(); }); @@ -186,11 +191,11 @@ Queue.pop_front(); } - if (Priority != ThreadPriority::Normal) - setCurrentThreadPriority(Priority); + if (Priority != llvm::ThreadPriority::Default && !PreventStarvation.load()) + llvm::set_thread_priority(Priority); (*Task)(); - if (Priority != ThreadPriority::Normal) - setCurrentThreadPriority(ThreadPriority::Normal); + if (Priority != llvm::ThreadPriority::Default) + llvm::set_thread_priority(llvm::ThreadPriority::Default); { std::unique_lock Lock(QueueMu); @@ -223,7 +228,7 @@ for (auto &Elem : NeedsReIndexing) enqueue(std::move(Elem.first), Elem.second); }, - ThreadPriority::Normal); + llvm::ThreadPriority::Default); } void BackgroundIndex::enqueue(tooling::CompileCommand Cmd, @@ -238,10 +243,10 @@ std::move(Error)); }, std::move(Cmd)), - ThreadPriority::Low); + llvm::ThreadPriority::Background); } -void BackgroundIndex::enqueueTask(Task T, ThreadPriority Priority) { +void BackgroundIndex::enqueueTask(Task T, llvm::ThreadPriority Priority) { { std::lock_guard Lock(QueueMu); auto I = Queue.end(); @@ -249,10 +254,11 @@ // Then we store low priority tasks. Normal priority tasks are pretty rare, // they should not grow beyond single-digit numbers, so it is OK to do // linear search and insert after that. - if (Priority == ThreadPriority::Normal) { - I = llvm::find_if(Queue, [](const std::pair &Elem) { - return Elem.second == ThreadPriority::Low; - }); + if (Priority == llvm::ThreadPriority::Default) { + I = llvm::find_if( + Queue, [](const std::pair &Elem) { + return Elem.second == llvm::ThreadPriority::Background; + }); } Queue.insert(I, {std::move(T), Priority}); } @@ -611,5 +617,9 @@ return NeedsReIndexing; } +void BackgroundIndex::preventThreadStarvationInTests() { + PreventStarvation.store(true); +} + } // namespace clangd } // namespace clang Index: clangd/tool/ClangdMain.cpp =================================================================== --- clangd/tool/ClangdMain.cpp +++ clangd/tool/ClangdMain.cpp @@ -13,6 +13,7 @@ #include "Protocol.h" #include "Trace.h" #include "Transport.h" +#include "index/Background.h" #include "index/Serialization.h" #include "clang/Basic/Version.h" #include "llvm/ADT/Optional.h" @@ -332,7 +333,8 @@ InputStyle = JSONStreamStyle::Delimited; LogLevel = Logger::Verbose; PrettyPrint = true; - preventThreadStarvationInTests(); // Ensure background index makes progress. + // Ensure background index makes progress. + BackgroundIndex::preventThreadStarvationInTests(); } if (Test || EnableTestScheme) { static URISchemeRegistry::Add X( Index: unittests/clangd/BackgroundIndexTests.cpp =================================================================== --- unittests/clangd/BackgroundIndexTests.cpp +++ unittests/clangd/BackgroundIndexTests.cpp @@ -70,7 +70,7 @@ class BackgroundIndexTest : public ::testing::Test { protected: - BackgroundIndexTest() { preventThreadStarvationInTests(); } + BackgroundIndexTest() { BackgroundIndex::preventThreadStarvationInTests(); } }; TEST_F(BackgroundIndexTest, NoCrashOnErrorFile) {