[clangd] Prevent thread starvation in tests on loaded systems.
authorSam McCall <sam.mccall@gmail.com>
Tue, 27 Nov 2018 12:09:13 +0000 (12:09 +0000)
committerSam McCall <sam.mccall@gmail.com>
Tue, 27 Nov 2018 12:09:13 +0000 (12:09 +0000)
Summary:
Background index deliberately runs low-priority, but for tests this may stop
them making progress.

Reviewers: kadircet

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

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

llvm-svn: 347655

clang-tools-extra/clangd/Threading.cpp
clang-tools-extra/clangd/Threading.h
clang-tools-extra/clangd/tool/ClangdMain.cpp
clang-tools-extra/unittests/clangd/BackgroundIndexTests.cpp

index e0c90f3..b427ce3 100644 (file)
@@ -3,6 +3,7 @@
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Threading.h"
+#include <atomic>
 #include <thread>
 #ifdef __USE_POSIX
 #include <pthread.h>
@@ -100,6 +101,8 @@ 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 setThreadPriority(std::thread &T, ThreadPriority Priority) {
   // Some *really* old glibcs are missing SCHED_IDLE.
 #if defined(__linux__) && defined(SCHED_IDLE)
@@ -107,9 +110,13 @@ void setThreadPriority(std::thread &T, ThreadPriority Priority) {
   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 71becf6..1b34831 100644 (file)
@@ -122,6 +122,10 @@ enum class ThreadPriority {
   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 e349ee0..ea542c1 100644 (file)
@@ -254,6 +254,7 @@ int main(int argc, char *argv[]) {
     RunSynchronously = true;
     InputStyle = JSONStreamStyle::Delimited;
     PrettyPrint = true;
+    preventThreadStarvationInTests(); // Ensure background index makes progress.
   }
   if (Test || EnableTestScheme) {
     static URISchemeRegistry::Add<TestScheme> X(
index 2294add..0beaf6a 100644 (file)
@@ -56,7 +56,12 @@ public:
   }
 };
 
-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 @@ TEST(BackgroundIndexTest, IndexTwoFiles) {
                        FileURI("unittest:///root/B.cc")}));
 }
 
-TEST(BackgroundIndexTest, ShardStorageWriteTest) {
+TEST_F(BackgroundIndexTest, ShardStorageWriteTest) {
   MockFSProvider FS;
   FS.Files[testPath("root/A.h")] = R"cpp(
       void common();