[clangd] Use llvm::set_thread_priority in background-index

Reviewers: gribozavr

Subscribers: krytarowski, ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, jfb, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D60865

llvm-svn: 358664
This commit is contained in:
Kadir Cetinkaya 2019-04-18 13:46:40 +00:00
parent 196a440411
commit f8537b3c69
6 changed files with 32 additions and 54 deletions

View File

@ -113,33 +113,5 @@ void wait(std::unique_lock<std::mutex> &Lock, std::condition_variable &CV,
CV.wait_until(Lock, D.time());
}
static std::atomic<bool> 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

View File

@ -117,16 +117,6 @@ private:
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

View File

@ -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 <atomic>
#include <chrono>
#include <memory>
#include <numeric>
@ -38,6 +40,9 @@
namespace clang {
namespace clangd {
namespace {
static std::atomic<bool> PreventStarvation = {false};
// Resolves URI to file paths with cache.
class URIToFileCache {
public:
@ -172,7 +177,7 @@ void BackgroundIndex::run() {
WithContext Background(BackgroundContext.clone());
while (true) {
llvm::Optional<Task> Task;
ThreadPriority Priority;
llvm::ThreadPriority Priority;
{
std::unique_lock<std::mutex> Lock(QueueMu);
QueueCV.wait(Lock, [&] { return ShouldStop || !Queue.empty(); });
@ -186,11 +191,11 @@ void BackgroundIndex::run() {
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<std::mutex> Lock(QueueMu);
@ -223,7 +228,7 @@ void BackgroundIndex::enqueue(const std::vector<std::string> &ChangedFiles) {
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 @@ void BackgroundIndex::enqueue(tooling::CompileCommand Cmd,
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<std::mutex> Lock(QueueMu);
auto I = Queue.end();
@ -249,9 +254,10 @@ void BackgroundIndex::enqueueTask(Task T, ThreadPriority Priority) {
// 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<Task, ThreadPriority> &Elem) {
return Elem.second == ThreadPriority::Low;
if (Priority == llvm::ThreadPriority::Default) {
I = llvm::find_if(
Queue, [](const std::pair<Task, llvm::ThreadPriority> &Elem) {
return Elem.second == llvm::ThreadPriority::Background;
});
}
Queue.insert(I, {std::move(T), Priority});
@ -611,5 +617,9 @@ BackgroundIndex::loadShards(std::vector<std::string> ChangedFiles) {
return NeedsReIndexing;
}
void BackgroundIndex::preventThreadStarvationInTests() {
PreventStarvation.store(true);
}
} // namespace clangd
} // namespace clang

View File

@ -88,6 +88,10 @@ public:
LLVM_NODISCARD bool
blockUntilIdleForTest(llvm::Optional<double> 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 @@ private:
// queue management
using Task = std::function<void()>;
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<std::pair<Task, ThreadPriority>> Queue;
std::deque<std::pair<Task, llvm::ThreadPriority>> Queue;
std::vector<std::thread> ThreadPool; // FIXME: Abstract this away.
GlobalCompilationDatabase::CommandChanged::Subscription CommandsChanged;
};

View File

@ -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 @@ int main(int argc, char *argv[]) {
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<TestScheme> X(

View File

@ -70,7 +70,7 @@ public:
class BackgroundIndexTest : public ::testing::Test {
protected:
BackgroundIndexTest() { preventThreadStarvationInTests(); }
BackgroundIndexTest() { BackgroundIndex::preventThreadStarvationInTests(); }
};
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile) {