[Cmake-commits] CMake branch, next, updated. v3.3.0-rc1-337-g0fae1c3

Zack Galbreath zack.galbreath at kitware.com
Tue Jun 9 10:10:18 EDT 2015


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  0fae1c377fbed45b45d8a1b5a624fa6b6cb297af (commit)
       via  1a6837185a13bd10fefc22e73930c7623a845ad7 (commit)
       via  a9376c9020332fd687d8c3a9e35373fd6d0d8e3b (commit)
       via  b50e351fde72e4054607a0b248361abf59c15364 (commit)
       via  03c32aad6839bce09cb8398b16e8bb9ae0758390 (commit)
       via  07a71c9e7f2e11c5b87bd7f4f4eb8b8042fd7aad (commit)
       via  3c593df0194efff4e9b83a179af8fe1e71f2aef3 (commit)
       via  b315ab28ceabbf3735b54fce6cb0d894d2adc773 (commit)
       via  599eeb0057688f32a1f4ee26993d85627af6c52b (commit)
       via  856b08211b9d112f4992e4939782eb8ed0ded094 (commit)
       via  ba5c785567b3af2c3221f5550d5561e4c96f6366 (commit)
       via  44e1fd0af4defe80e903a18d72e5ff8488b0bc42 (commit)
       via  646eb9b2a5504e4114b87cfb60cec292a306ddb2 (commit)
       via  28c028e5fb5d0f542a74df738b4658d112c49b95 (commit)
      from  5dc6ebb7cb65e01efe4d8ee9c3b6ed7e5c81e5a0 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0fae1c377fbed45b45d8a1b5a624fa6b6cb297af
commit 0fae1c377fbed45b45d8a1b5a624fa6b6cb297af
Merge: 5dc6ebb 1a68371
Author:     Zack Galbreath <zack.galbreath at kitware.com>
AuthorDate: Tue Jun 9 10:10:16 2015 -0400
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Tue Jun 9 10:10:16 2015 -0400

    Merge topic 'ctest-test-load' into next
    
    1a683718 Use cmSystemTools::RandomSeed() instead of rand()
    a9376c90 Make --test-load test pass more reliably
    b50e351f new test of ctest --test-load
    03c32aad update documentation for CTEST_TEST_LOAD
    07a71c9e Add TEST_LOAD option to ctest_test
    3c593df0 rename max-load to test-load
    b315ab28 create CTEST_MAX_LOAD cache variable
    599eeb00 change how RUN_SERIAL is implemented
    856b0821 More improvements to max-load check
    ba5c7855 Improvements to max-load monitoring
    44e1fd0a Added debug output to determine why tests hang before completion
    646eb9b2 Added document with release notes.
    28c028e5 Added "--max-load" option to CTest


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1a6837185a13bd10fefc22e73930c7623a845ad7
commit 1a6837185a13bd10fefc22e73930c7623a845ad7
Author:     Zack Galbreath <zack.galbreath at kitware.com>
AuthorDate: Tue Jun 9 08:50:44 2015 -0400
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Tue Jun 9 08:50:44 2015 -0400

    Use cmSystemTools::RandomSeed() instead of rand()

diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 5176715..f9357d6 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -431,8 +431,9 @@ void cmCTestMultiProcessHandler::StartNextTests()
       }
     else
       {
-      // Wait between 1 and 5 seconds before trying again...
-      cmCTestScriptHandler::SleepInSeconds(rand() % 5 + 1);
+      // Wait between 1 and 5 seconds before trying again.
+      cmCTestScriptHandler::SleepInSeconds(
+        cmSystemTools::RandomSeed() % 5 + 1);
       }
     }
 }

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a9376c9020332fd687d8c3a9e35373fd6d0d8e3b
commit a9376c9020332fd687d8c3a9e35373fd6d0d8e3b
Author:     Zack Galbreath <zack.galbreath at kitware.com>
AuthorDate: Mon Jun 8 16:11:03 2015 -0400
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Mon Jun 8 16:11:03 2015 -0400

    Make --test-load test pass more reliably
    
    More gracefully handle race condition caused by parallel testing

diff --git a/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
index 418f2e0..7ee3dae 100644
--- a/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
+++ b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
@@ -1,7 +1,7 @@
 ^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad
     Start 1: TestLoad1
     Start 2: TestLoad2
-1/2 Test #2: TestLoad2 ........................   Passed +[0-9.]+ sec
-2/2 Test #1: TestLoad1 ........................   Passed +[0-9.]+ sec
+1/2 Test #[1-2]: TestLoad[1-2] ........................   Passed +[0-9.]+ sec
+2/2 Test #[1-2]: TestLoad[1-2] ........................   Passed +[0-9.]+ sec
 +
 100% tests passed, 0 tests failed out of 2

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b50e351fde72e4054607a0b248361abf59c15364
commit b50e351fde72e4054607a0b248361abf59c15364
Author:     Zack Galbreath <zack.galbreath at kitware.com>
AuthorDate: Mon Jun 8 15:52:30 2015 -0400
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Mon Jun 8 15:53:18 2015 -0400

    new test of ctest --test-load

diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 2ea088b..5176715 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -276,6 +276,7 @@ void cmCTestMultiProcessHandler::StartNextTests()
     }
 
   bool allTestsFailedTestLoadCheck = false;
+  bool testingThisFeature = false;
   size_t minProcessorsRequired = this->ParallelLevel;
   std::string testWithMinProcessors = "";
 
@@ -297,6 +298,8 @@ void cmCTestMultiProcessHandler::StartNextTests()
     }
   cmFileLock testLoadLock;
 
+  double systemLoad = 0.0;
+
   TestList copy = this->SortedTests;
   for(TestList::iterator test = copy.begin(); test != copy.end(); ++test)
     {
@@ -322,7 +325,19 @@ void cmCTestMultiProcessHandler::StartNextTests()
         cmFileLockResult result = testLoadLock.Lock(lockFile, 1);
         if (result.IsOk())
           {
-          const double systemLoad = info.GetLoadAverage();
+          // Check for a fake load average value used in testing.
+          const char* fake_load_value =
+            getenv("__FAKE_LOAD_AVERAGE_FOR_CTEST_TESTING");
+          if (fake_load_value)
+            {
+            testingThisFeature = true;
+            systemLoad = atoi(fake_load_value);
+            }
+          // If it's not set, look up the true load average.
+          else
+            {
+            systemLoad = info.GetLoadAverage();
+            }
 
           // Don't start more tests than your max load can support.
           if (numToStart > (this->TestLoad - systemLoad))
@@ -333,7 +348,7 @@ void cmCTestMultiProcessHandler::StartNextTests()
           testLoadOk = processors <= (this->TestLoad - systemLoad);
           if (testLoadOk)
             {
-            cmCTestLog(this->CTest, HANDLER_OUTPUT, "OK to run " << GetName(*test) << ", it requires " << processors << " procs & system load is: " << info.GetLoadAverage() << std::endl);
+            cmCTestLog(this->CTest, DEBUG, "OK to run " << GetName(*test) << ", it requires " << processors << " procs & system load is: " << systemLoad << std::endl);
             }
           }
         else
@@ -383,13 +398,13 @@ void cmCTestMultiProcessHandler::StartNextTests()
 
   if (allTestsFailedTestLoadCheck)
     {
-    cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING,");
+    cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, ");
     time_t currenttime = time(0);
     struct tm* t = localtime(&currenttime);
     char current_time[1024];
     strftime(current_time, 1000, "%s", t);
     cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Time: "
-      << current_time << ",");
+      << current_time << ", ");
 
     if (this->SerialTestRunning)
       {
@@ -400,16 +415,25 @@ void cmCTestMultiProcessHandler::StartNextTests()
     else
       {
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Load: "
-        << info.GetLoadAverage() << ",");
+        << systemLoad << ", ");
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "Max Allowed Load: "
-        << this->TestLoad << ",");
+        << this->TestLoad << ", ");
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "Smallest test "
         << testWithMinProcessors << " requires " << minProcessorsRequired);
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
       }
 
-    // Wait between 1 and 60 seconds before trying again...
-    cmCTestScriptHandler::SleepInSeconds(rand() % 60 + 1);
+    if (testingThisFeature)
+      {
+      // Break out of the infinite loop of waiting for our fake load
+      // to come down.
+      this->StopTimePassed = true;
+      }
+    else
+      {
+      // Wait between 1 and 5 seconds before trying again...
+      cmCTestScriptHandler::SleepInSeconds(rand() % 5 + 1);
+      }
     }
 }
 
diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
index a3ce139..dc13c9f 100644
--- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
@@ -52,3 +52,31 @@ add_test(MergeOutput \"${CMAKE_COMMAND}\" -P \"${RunCMake_SOURCE_DIR}/MergeOutpu
   run_cmake_command(MergeOutput ${CMAKE_CTEST_COMMAND} -V)
 endfunction()
 run_MergeOutput()
+
+
+function(run_TestLoad name load)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TestLoad)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+  file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+  add_test(TestLoad1 \"${CMAKE_COMMAND}\" -E echo \"test of --test-load\")
+  add_test(TestLoad2 \"${CMAKE_COMMAND}\" -E echo \"test of --test-load\")
+")
+  run_cmake_command(${name} ${CMAKE_CTEST_COMMAND} -j2 --test-load ${load} --test-timeout 5)
+endfunction()
+
+# Tests for the --test-load feature of ctest
+#
+# Spoof a load average value to make these tests more reliable.
+set(ENV{__FAKE_LOAD_AVERAGE_FOR_CTEST_TESTING} 5)
+
+# Verify that new tests are not started when the load average exceeds
+# our threshold.
+run_TestLoad(test-load-fail 2)
+
+# Verify that new tests are started when the load average falls below
+# our threshold.
+run_TestLoad(test-load-pass 10)
+
+unset(ENV{__FAKE_LOAD_AVERAGE_FOR_CTEST_TESTING})
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-fail-stderr.txt b/Tests/RunCMake/CTestCommandLine/test-load-fail-stderr.txt
new file mode 100644
index 0000000..eafba1c
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/test-load-fail-stderr.txt
@@ -0,0 +1 @@
+No tests were found!!!
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-fail-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-fail-stdout.txt
new file mode 100644
index 0000000..fb36bb1
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/test-load-fail-stdout.txt
@@ -0,0 +1,2 @@
+^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad
+\*\*\*\*\* WAITING, System Time: [0-9]+, System Load: 5, Max Allowed Load: 2, Smallest test TestLoad2 requires 1\*\*\*\*\*
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-pass-stderr.txt b/Tests/RunCMake/CTestCommandLine/test-load-pass-stderr.txt
new file mode 100644
index 0000000..10f3293
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/test-load-pass-stderr.txt
@@ -0,0 +1 @@
+^$
diff --git a/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
new file mode 100644
index 0000000..418f2e0
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt
@@ -0,0 +1,7 @@
+^Test project .*/Tests/RunCMake/CTestCommandLine/TestLoad
+    Start 1: TestLoad1
+    Start 2: TestLoad2
+1/2 Test #2: TestLoad2 ........................   Passed +[0-9.]+ sec
+2/2 Test #1: TestLoad1 ........................   Passed +[0-9.]+ sec
++
+100% tests passed, 0 tests failed out of 2

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=03c32aad6839bce09cb8398b16e8bb9ae0758390
commit 03c32aad6839bce09cb8398b16e8bb9ae0758390
Author:     Zack Galbreath <zack.galbreath at kitware.com>
AuthorDate: Mon Jun 8 10:50:25 2015 -0400
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Mon Jun 8 15:53:18 2015 -0400

    update documentation for CTEST_TEST_LOAD

diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst
index 8cbb9ec..189093d 100644
--- a/Help/command/ctest_test.rst
+++ b/Help/command/ctest_test.rst
@@ -14,6 +14,7 @@ Perform the :ref:`CTest Test Step` as a :ref:`Dashboard Client`.
              [EXCLUDE_LABEL <label-exclude-regex>]
              [INCLUDE_LABEL <label-include-regex>]
              [PARALLEL_LEVEL <level>]
+             [TEST_LOAD <threshold>]
              [SCHEDULE_RANDOM <ON|OFF>]
              [STOP_TIME <time-of-day>]
              [RETURN_VALUE <result-var>]
@@ -41,7 +42,7 @@ The options are:
   Specify the end of a range of test numbers.
 
 ``STRIDE <stride-number>``
-  Specify the stride by which to step acorss a range of test numbers.
+  Specify the stride by which to step across a range of test numbers.
 
 ``EXCLUDE <exclude-regex>``
   Specify a regular expression matching test names to exclude.
@@ -61,6 +62,10 @@ The options are:
   Specify a positive number representing the number of tests to
   be run in parallel.
 
+``TEST_LOAD <threshold>``
+  Specify a CPU load threshold that CTest should attempt to
+  not cross.  See :variable:`CTEST_TEST_LOAD` for more details.
+
 ``SCHEDULE_RANDOM <ON|OFF>``
   Launch tests in a random order.  This may be useful for detecting
   implicit test dependencies.
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index bd02f8b..6ab7f3d 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -152,6 +152,7 @@ Variables that Change Behavior
    /variable/CMAKE_SYSTEM_LIBRARY_PATH
    /variable/CMAKE_SYSTEM_PREFIX_PATH
    /variable/CMAKE_SYSTEM_PROGRAM_PATH
+   /variable/CMAKE_TEST_LOAD
    /variable/CMAKE_USER_MAKE_RULES_OVERRIDE
    /variable/CMAKE_WARN_DEPRECATED
    /variable/CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
@@ -381,6 +382,7 @@ Variables for CTest
    /variable/CTEST_SVN_COMMAND
    /variable/CTEST_SVN_OPTIONS
    /variable/CTEST_SVN_UPDATE_OPTIONS
+   /variable/CTEST_TEST_LOAD
    /variable/CTEST_TEST_TIMEOUT
    /variable/CTEST_TRIGGER_SITE
    /variable/CTEST_UPDATE_COMMAND
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index c76bf95..6dd7330 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -67,10 +67,8 @@ Options
  environment variable ``CTEST_PARALLEL_LEVEL``.
 
 ``--test-load <level>``
- Limit machine load during parallel testing.
-
- This option tells ctest not to start new tests if doing so would be
- likely to raise the machine load above the given level.
+ Limit CPU load during parallel testing.
+ See :variable:`CTEST_TEST_LOAD` for more details.
 
 ``-Q,--quiet``
  Make ctest quiet.
diff --git a/Help/release/dev/ctest-test-load-option.rst b/Help/release/dev/ctest-test-load-option.rst
index ec31788..25efc26 100644
--- a/Help/release/dev/ctest-test-load-option.rst
+++ b/Help/release/dev/ctest-test-load-option.rst
@@ -2,5 +2,5 @@ ctest-test-load-option
 ----------------------
 
 * It is now possible to set the 'test-load' option in CTest.
-  If set, then CTest will not run any tests that would be projected
-  to increase the machine load above this level.
+  If set, then CTest will not start any new tests that would be
+  projected to increase the CPU load above this level.
diff --git a/Help/variable/CMAKE_TEST_LOAD.rst b/Help/variable/CMAKE_TEST_LOAD.rst
new file mode 100644
index 0000000..7baf6dd
--- /dev/null
+++ b/Help/variable/CMAKE_TEST_LOAD.rst
@@ -0,0 +1,9 @@
+CMAKE_TEST_LOAD
+------------------
+
+CMake variable to specify the CTest ``TestLoad`` setting.
+See :variable:`CTEST_TEST_LOAD` for more details.
+
+Note that this variable is not honored during script mode.
+If you intend to drive your tests with ``ctest -S``, please set
+:variable:`CTEST_TEST_LOAD` in your dashboard script instead.
diff --git a/Help/variable/CTEST_TEST_LOAD.rst b/Help/variable/CTEST_TEST_LOAD.rst
new file mode 100644
index 0000000..6d7aea6
--- /dev/null
+++ b/Help/variable/CTEST_TEST_LOAD.rst
@@ -0,0 +1,24 @@
+CTEST_TEST_LOAD
+------------------
+
+Specify the ``TestLoad`` setting
+in a :manual:`ctest(1)` dashboard client script.
+
+This creates a CPU load threshold that CTest will attempt to
+not cross.  CTest will not start a new test if doing so
+would be likely to raise the CPU load above this threshold.
+Please note that this variable is only honored during parallel testing
+(``ctest -j`` or similar).
+
+Here are the various ways that you can set this threshold:
+
+* The ``TEST_LOAD`` option to :command:`ctest_test`.
+* :variable:`CTEST_TEST_LOAD` in a dashboard script.
+* Passing the ``--ctest-load`` command-line argument to :manual:`ctest(1)`.
+* Setting the :variable:`CMAKE_TEST_LOAD` variable in your CMake project.
+
+These are listed here in descending priority order, ie
+``ctest_test(TEST_LOAD ...)`` will override any of the other
+methods of setting this threshold.  Also note that
+:variable:`CMAKE_TEST_LOAD` is not honored when running ctest
+in script (``-S``) mode.
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index e784759..afcbd61 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -98,6 +98,7 @@ static const char * cmDocumentationOptions[][2] =
 
   {"--test-command", "The test to run with the --build-and-test option."},
   {"--test-timeout", "The time limit in seconds, internal use only."},
+  {"--test-load", "CPU load threshold for starting new parallel tests."},
   {"--tomorrow-tag", "Nightly or experimental starts with next day tag."},
   {"--ctest-config", "The configuration file used to initialize CTest state "
    "when submitting dashboards."},

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=07a71c9e7f2e11c5b87bd7f4f4eb8b8042fd7aad
commit 07a71c9e7f2e11c5b87bd7f4f4eb8b8042fd7aad
Author:     Zack Galbreath <zack.galbreath at kitware.com>
AuthorDate: Thu Jun 4 13:38:37 2015 -0400
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Mon Jun 8 15:53:13 2015 -0400

    Add TEST_LOAD option to ctest_test
    
    This allows us to specify the value for TEST_LOAD within a call
    to ctest_test()

diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index a7dd658..2f8016f 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -26,6 +26,7 @@ cmCTestTestCommand::cmCTestTestCommand()
   this->Arguments[ctt_PARALLEL_LEVEL] = "PARALLEL_LEVEL";
   this->Arguments[ctt_SCHEDULE_RANDOM] = "SCHEDULE_RANDOM";
   this->Arguments[ctt_STOP_TIME] = "STOP_TIME";
+  this->Arguments[ctt_TEST_LOAD] = "TEST_LOAD";
   this->Arguments[ctt_LAST] = 0;
   this->Last = ctt_LAST;
 }
@@ -114,6 +115,14 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
     {
     this->CTest->SetStopTime(this->Values[ctt_STOP_TIME]);
     }
+  if(this->Values[ctt_TEST_LOAD])
+    {
+    int testLoad = atoi(this->Values[ctt_TEST_LOAD]);
+    if (testLoad > 0)
+      {
+      this->CTest->SetTestLoad(testLoad);
+      }
+    }
   handler->SetQuiet(this->Quiet);
   return handler;
 }
diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h
index a1e5f36..0dfca97 100644
--- a/Source/CTest/cmCTestTestCommand.h
+++ b/Source/CTest/cmCTestTestCommand.h
@@ -60,6 +60,7 @@ protected:
     ctt_PARALLEL_LEVEL,
     ctt_SCHEDULE_RANDOM,
     ctt_STOP_TIME,
+    ctt_TEST_LOAD,
     ctt_LAST
   };
 };
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index e66e069..17dfafc 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -826,7 +826,10 @@ bool cmCTest::UpdateCTestConfiguration()
     cmSystemTools::ChangeDirectory(this->BinaryDir);
     }
   this->TimeOut = atoi(this->GetCTestConfiguration("TimeOut").c_str());
-  this->SetTestLoad(atoi(this->GetCTestConfiguration("TestLoad").c_str()));
+  if ( !this->GetCTestConfiguration("TestLoad").empty() )
+    {
+    this->SetTestLoad(atoi(this->GetCTestConfiguration("TestLoad").c_str()));
+    }
   if ( this->ProduceXML )
     {
     this->CompressXMLFiles = cmSystemTools::IsOn(

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3c593df0194efff4e9b83a179af8fe1e71f2aef3
commit 3c593df0194efff4e9b83a179af8fe1e71f2aef3
Author:     Zack Galbreath <zack.galbreath at kitware.com>
AuthorDate: Thu Jun 4 13:15:14 2015 -0400
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Mon Jun 8 10:59:49 2015 -0400

    rename max-load to test-load

diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index 4589f32..c76bf95 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -66,11 +66,11 @@ Options
  number of jobs.  This option can also be set by setting the
  environment variable ``CTEST_PARALLEL_LEVEL``.
 
-``--max-load <level>``
- Set maximum allowed machine load.
+``--test-load <level>``
+ Limit machine load during parallel testing.
 
- This option tells ctest to only start tests that will not increase
- the machine load above the given level.
+ This option tells ctest not to start new tests if doing so would be
+ likely to raise the machine load above the given level.
 
 ``-Q,--quiet``
  Make ctest quiet.
diff --git a/Help/release/dev/ctest-max-load-option.rst b/Help/release/dev/ctest-test-load-option.rst
similarity index 52%
rename from Help/release/dev/ctest-max-load-option.rst
rename to Help/release/dev/ctest-test-load-option.rst
index 037c61f..ec31788 100644
--- a/Help/release/dev/ctest-max-load-option.rst
+++ b/Help/release/dev/ctest-test-load-option.rst
@@ -1,6 +1,6 @@
-ctest-max-load-option
---------------
+ctest-test-load-option
+----------------------
 
-* It is now possible to set the 'max-load' option in CTest.
+* It is now possible to set the 'test-load' option in CTest.
   If set, then CTest will not run any tests that would be projected
   to increase the machine load above this level.
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 96c3d4f..2ea088b 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -44,7 +44,7 @@ private:
 cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
 {
   this->ParallelLevel = 1;
-  this->MaxLoad = 0;
+  this->TestLoad = 0;
   this->Completed = 0;
   this->RunningCount = 0;
   this->StopTimePassed = false;
@@ -89,9 +89,9 @@ void cmCTestMultiProcessHandler::SetParallelLevel(size_t level)
   this->ParallelLevel = level < 1 ? 1 : level;
 }
 
-void cmCTestMultiProcessHandler::SetMaxLoad(size_t max)
+void cmCTestMultiProcessHandler::SetTestLoad(size_t load)
 {
-  this->MaxLoad = max < 1 ? 0 : max;
+  this->TestLoad = load < 1 ? 0 : load;
 }
 
 //---------------------------------------------------------
@@ -280,8 +280,8 @@ void cmCTestMultiProcessHandler::StartNextTests()
   std::string testWithMinProcessors = "";
 
   cmsys::SystemInformation info;
-  const std::string lockFile = "/tmp/.cmake_maxload.lock"; // TODO: Filename
-  if (this->MaxLoad > 0)
+  const std::string lockFile = "/tmp/.cmake_testload.lock"; // TODO: Filename
+  if (this->TestLoad > 0)
     {
     allTestsFailedTestLoadCheck = true;
 
@@ -295,7 +295,7 @@ void cmCTestMultiProcessHandler::StartNextTests()
       fclose(file);
       }
     }
-  cmFileLock maxLoadLock;
+  cmFileLock testLoadLock;
 
   TestList copy = this->SortedTests;
   for(TestList::iterator test = copy.begin(); test != copy.end(); ++test)
@@ -303,7 +303,7 @@ void cmCTestMultiProcessHandler::StartNextTests()
     // Take a nap if we're currently performing a RUN_SERIAL test.
     if (this->SerialTestRunning)
       {
-      allTestsFailedMaxLoadCheck = true;
+      allTestsFailedTestLoadCheck = true;
       break;
       }
     // We can only start a RUN_SERIAL test if no other tests are also running.
@@ -313,44 +313,44 @@ void cmCTestMultiProcessHandler::StartNextTests()
       }
 
     size_t processors = GetProcessorsUsed(*test);
-    bool maxLoadOk;
-    if (this->MaxLoad > 0)
+    bool testLoadOk;
+    if (this->TestLoad > 0)
       {
       // First, try to get file lock..
-      if (!maxLoadLock.IsLocked(lockFile))
+      if (!testLoadLock.IsLocked(lockFile))
         {
-        cmFileLockResult result = maxLoadLock.Lock(lockFile, 1);
+        cmFileLockResult result = testLoadLock.Lock(lockFile, 1);
         if (result.IsOk())
           {
           const double systemLoad = info.GetLoadAverage();
 
           // Don't start more tests than your max load can support.
-          if (numToStart > (this->MaxLoad - systemLoad))
+          if (numToStart > (this->TestLoad - systemLoad))
             {
-            numToStart = this->MaxLoad - systemLoad;
+            numToStart = this->TestLoad - systemLoad;
             }
 
-          maxLoadOk = processors <= (this->MaxLoad - systemLoad);
-          if (maxLoadOk)
+          testLoadOk = processors <= (this->TestLoad - systemLoad);
+          if (testLoadOk)
             {
             cmCTestLog(this->CTest, HANDLER_OUTPUT, "OK to run " << GetName(*test) << ", it requires " << processors << " procs & system load is: " << info.GetLoadAverage() << std::endl);
             }
           }
         else
           {
-          maxLoadOk = false;
+          testLoadOk = false;
           }
         }
       else
         {
-        maxLoadOk = false;
+        testLoadOk = false;
         }
 
-      allTestsFailedMaxLoadCheck &= !maxLoadOk;
+      allTestsFailedTestLoadCheck &= !testLoadOk;
       }
     else
       {
-      maxLoadOk = true;
+      testLoadOk = true;
       }
 
     if (processors <= minProcessorsRequired)
@@ -359,9 +359,9 @@ void cmCTestMultiProcessHandler::StartNextTests()
       testWithMinProcessors = GetName(*test);
       }
 
-    if(maxLoadOk && processors <= numToStart && this->StartTest(*test))
+    if(testLoadOk && processors <= numToStart && this->StartTest(*test))
       {
-      maxLoadLock.Release();
+      testLoadLock.Release();
 
       if(this->StopTimePassed)
         {
@@ -372,16 +372,16 @@ void cmCTestMultiProcessHandler::StartNextTests()
       }
     else if(numToStart == 0)
       {
-      maxLoadLock.Release();
+      testLoadLock.Release();
       return;
       }
     else
       {
-      maxLoadLock.Release();
+      testLoadLock.Release();
       }
     }   // for
 
-  if (allTestsFailedMaxLoadCheck)
+  if (allTestsFailedTestLoadCheck)
     {
     cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING,");
     time_t currenttime = time(0);
@@ -402,7 +402,7 @@ void cmCTestMultiProcessHandler::StartNextTests()
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Load: "
         << info.GetLoadAverage() << ",");
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "Max Allowed Load: "
-        << this->MaxLoad << ",");
+        << this->TestLoad << ",");
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "Smallest test "
         << testWithMinProcessors << " requires " << minProcessorsRequired);
       cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index 461c728..1ca7e7c 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -37,7 +37,7 @@ public:
   void SetTests(TestMap& tests, PropertiesMap& properties);
   // Set the max number of tests that can be run at the same time.
   void SetParallelLevel(size_t);
-  void SetMaxLoad(size_t max);
+  void SetTestLoad(size_t max);
   virtual void RunTests();
   void PrintTestList();
   void PrintLabels();
@@ -118,7 +118,7 @@ protected:
   std::set<std::string> LockedResources;
   std::vector<cmCTestTestHandler::cmCTestTestResult>* TestResults;
   size_t ParallelLevel; // max number of process that can be run at once
-  size_t MaxLoad;
+  size_t TestLoad;
   std::set<cmCTestRunTest*> RunningTests;  // current running tests
   cmCTestTestHandler * TestHandler;
   cmCTest* CTest;
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index f0e1c99..a7dd658 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -50,13 +50,13 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
     }
   this->CTest->SetTimeOut(timeout);
 
-  if(const char* ctestMaxLoad =
-     this->Makefile->GetDefinition("CTEST_MAX_LOAD"))
+  if(const char* ctestTestLoad =
+     this->Makefile->GetDefinition("CTEST_TEST_LOAD"))
     {
-    int maxLoad = atoi(ctestMaxLoad);
-    if (maxLoad > 0)
+    int testLoad = atoi(ctestTestLoad);
+    if (testLoad > 0)
       {
-      this->CTest->SetMaxLoad(maxLoad);
+      this->CTest->SetTestLoad(testLoad);
       }
     }
 
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 3d6b746..3f3c650 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1060,7 +1060,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string> &passed,
     new cmCTestBatchTestHandler : new cmCTestMultiProcessHandler;
   parallel->SetCTest(this->CTest);
   parallel->SetParallelLevel(this->CTest->GetParallelLevel());
-  parallel->SetMaxLoad(this->CTest->GetMaxLoad());
+  parallel->SetTestLoad(this->CTest->GetTestLoad());
   parallel->SetTestHandler(this);
   parallel->SetQuiet(this->Quiet);
 
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 73f282e..e66e069 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -294,7 +294,7 @@ cmCTest::cmCTest()
   this->LabelSummary           = true;
   this->ParallelLevel          = 1;
   this->ParallelLevelSetInCli  = false;
-  this->MaxLoad                = 0;
+  this->TestLoad               = 0;
   this->SubmitIndex            = 0;
   this->Failover               = false;
   this->BatchJobs              = false;
@@ -394,9 +394,9 @@ void cmCTest::SetParallelLevel(int level)
   this->ParallelLevel = level < 1 ? 1 : level;
 }
 
-void cmCTest::SetMaxLoad(int max)
+void cmCTest::SetTestLoad(int max)
 {
-  this->MaxLoad = max < 1 ? 0 : max;
+  this->TestLoad = max < 1 ? 0 : max;
 }
 
 //----------------------------------------------------------------------------
@@ -826,7 +826,7 @@ bool cmCTest::UpdateCTestConfiguration()
     cmSystemTools::ChangeDirectory(this->BinaryDir);
     }
   this->TimeOut = atoi(this->GetCTestConfiguration("TimeOut").c_str());
-  this->SetMaxLoad(atoi(this->GetCTestConfiguration("MaxLoad").c_str()));
+  this->SetTestLoad(atoi(this->GetCTestConfiguration("TestLoad").c_str()));
   if ( this->ProduceXML )
     {
     this->CompressXMLFiles = cmSystemTools::IsOn(
@@ -2058,11 +2058,11 @@ bool cmCTest::HandleCommandLineArguments(size_t &i,
       }
     }
 
-  if(this->CheckArgument(arg, "--max-load") && i < args.size() - 1)
+  if(this->CheckArgument(arg, "--test-load") && i < args.size() - 1)
     {
     i++;
     int max = atoi(args[i].c_str());
-    this->SetMaxLoad(max);
+    this->SetTestLoad(max);
     }
 
   if(this->CheckArgument(arg, "--no-compress-output"))
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 4fbfbff..c47c786 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -161,8 +161,8 @@ public:
   int GetParallelLevel() { return this->ParallelLevel; }
   void SetParallelLevel(int);
 
-  int GetMaxLoad() { return this->MaxLoad; }
-  void SetMaxLoad(int);
+  int GetTestLoad() { return this->TestLoad; }
+  void SetTestLoad(int);
 
   /**
    * Check if CTest file exists
@@ -502,7 +502,7 @@ private:
   int                     ParallelLevel;
   bool                    ParallelLevelSetInCli;
 
-  int                     MaxLoad;
+  int                     TestLoad;
 
   int                     CompatibilityMode;
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b315ab28ceabbf3735b54fce6cb0d894d2adc773
commit b315ab28ceabbf3735b54fce6cb0d894d2adc773
Author:     Zack Galbreath <zack.galbreath at kitware.com>
AuthorDate: Mon Jun 1 10:21:14 2015 -0400
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Mon Jun 8 10:58:55 2015 -0400

    create CTEST_MAX_LOAD cache variable
    
    This allows users to set a max load for CTest at configure time
    or within a CTest driver script.

diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake
index 8278c5c..0b34fcd 100644
--- a/Modules/CTest.cmake
+++ b/Modules/CTest.cmake
@@ -173,6 +173,9 @@ if(BUILD_TESTING)
   set(DART_TESTING_TIMEOUT 1500 CACHE STRING
     "Maximum time allowed before CTest will kill the test.")
 
+  set(CTEST_MAX_LOAD 0 CACHE STRING
+    "Maximum system load that CTest should not exceed during parallel testing.  Specify 0 for no maximum.")
+
   set(CTEST_SUBMIT_RETRY_DELAY 5 CACHE STRING
     "How long to wait between timed-out CTest submissions.")
   set(CTEST_SUBMIT_RETRY_COUNT 3 CACHE STRING
diff --git a/Modules/DartConfiguration.tcl.in b/Modules/DartConfiguration.tcl.in
index 37a0a40..d8ec84a 100644
--- a/Modules/DartConfiguration.tcl.in
+++ b/Modules/DartConfiguration.tcl.in
@@ -95,6 +95,10 @@ SlurmRunCommand: @SLURM_SRUN_COMMAND@
 # Currently set to 25 minutes
 TimeOut: @DART_TESTING_TIMEOUT@
 
+# During parallel testing CTest will not start a new test if doing
+# so would cause the system load to exceed this value.
+TestLoad: @CMAKE_TEST_LOAD@
+
 UseLaunchers: @CTEST_USE_LAUNCHERS@
 CurlOptions: @CTEST_CURL_OPTIONS@
 # warning, if you add new options here that have to do with submit,
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index 8b357ac..f0e1c99 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -49,6 +49,17 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
       }
     }
   this->CTest->SetTimeOut(timeout);
+
+  if(const char* ctestMaxLoad =
+     this->Makefile->GetDefinition("CTEST_MAX_LOAD"))
+    {
+    int maxLoad = atoi(ctestMaxLoad);
+    if (maxLoad > 0)
+      {
+      this->CTest->SetMaxLoad(maxLoad);
+      }
+    }
+
   cmCTestGenericHandler* handler = this->InitializeActualHandler();
   if ( this->Values[ctt_START] || this->Values[ctt_END] ||
     this->Values[ctt_STRIDE] )
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index fc36b62..73f282e 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -826,6 +826,7 @@ bool cmCTest::UpdateCTestConfiguration()
     cmSystemTools::ChangeDirectory(this->BinaryDir);
     }
   this->TimeOut = atoi(this->GetCTestConfiguration("TimeOut").c_str());
+  this->SetMaxLoad(atoi(this->GetCTestConfiguration("MaxLoad").c_str()));
   if ( this->ProduceXML )
     {
     this->CompressXMLFiles = cmSystemTools::IsOn(

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=599eeb0057688f32a1f4ee26993d85627af6c52b
commit 599eeb0057688f32a1f4ee26993d85627af6c52b
Author:     Zack Galbreath <zack.galbreath at kitware.com>
AuthorDate: Mon Jun 1 09:42:44 2015 -0400
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Mon Jun 8 10:58:20 2015 -0400

    change how RUN_SERIAL is implemented
    
    The original implementation of the RUN_SERIAL test property
    worked by having such a test consume all available processors.
    This strategy causes unnecessary timeouts and delays when used
    in conjunction with the new --max-load feature.
    
    So instead of artificially inflating the number of processors
    that a RUN_SERIAL test requires, we now use a boolean ivar to ensure
    that such a test is not run in parallel with any other tests.

diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index bfcd74d..96c3d4f 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -49,6 +49,7 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
   this->RunningCount = 0;
   this->StopTimePassed = false;
   this->HasCycles = false;
+  this->SerialTestRunning = false;
 }
 
 cmCTestMultiProcessHandler::~cmCTestMultiProcessHandler()
@@ -182,6 +183,11 @@ void cmCTestMultiProcessHandler::LockResources(int index)
   this->LockedResources.insert(
       this->Properties[index]->LockedResources.begin(),
       this->Properties[index]->LockedResources.end());
+
+  if (this->Properties[index]->RunSerial)
+    {
+    this->SerialTestRunning = true;
+    }
 }
 
 //---------------------------------------------------------
@@ -208,11 +214,9 @@ inline size_t cmCTestMultiProcessHandler::GetProcessorsUsed(int test)
 {
   size_t processors =
     static_cast<int>(this->Properties[test]->Processors);
-  //If this is set to run serially, it must run alone.
-  //Also, if processors setting is set higher than the -j
+  //If processors setting is set higher than the -j
   //setting, we default to using all of the process slots.
-  if(this->Properties[test]->RunSerial
-     || processors > this->ParallelLevel)
+  if (processors > this->ParallelLevel)
     {
     processors = this->ParallelLevel;
     }
@@ -264,7 +268,14 @@ void cmCTestMultiProcessHandler::StartNextTests()
     return;
     }
 
-  bool allTestsFailedMaxLoadCheck = true;
+  // Don't start any new tests if one with the RUN_SERIAL property
+  // is already running.
+  if (this->SerialTestRunning)
+    {
+    return;
+    }
+
+  bool allTestsFailedTestLoadCheck = false;
   size_t minProcessorsRequired = this->ParallelLevel;
   std::string testWithMinProcessors = "";
 
@@ -272,6 +283,8 @@ void cmCTestMultiProcessHandler::StartNextTests()
   const std::string lockFile = "/tmp/.cmake_maxload.lock"; // TODO: Filename
   if (this->MaxLoad > 0)
     {
+    allTestsFailedTestLoadCheck = true;
+
     if (!cmSystemTools::FileExists(lockFile))
       {
       FILE *file = cmsys::SystemTools::Fopen(lockFile, "w");
@@ -287,6 +300,18 @@ void cmCTestMultiProcessHandler::StartNextTests()
   TestList copy = this->SortedTests;
   for(TestList::iterator test = copy.begin(); test != copy.end(); ++test)
     {
+    // Take a nap if we're currently performing a RUN_SERIAL test.
+    if (this->SerialTestRunning)
+      {
+      allTestsFailedMaxLoadCheck = true;
+      break;
+      }
+    // We can only start a RUN_SERIAL test if no other tests are also running.
+    if (this->Properties[*test]->RunSerial && this->RunningCount > 0)
+      {
+      continue;
+      }
+
     size_t processors = GetProcessorsUsed(*test);
     bool maxLoadOk;
     if (this->MaxLoad > 0)
@@ -298,7 +323,18 @@ void cmCTestMultiProcessHandler::StartNextTests()
         if (result.IsOk())
           {
           const double systemLoad = info.GetLoadAverage();
+
+          // Don't start more tests than your max load can support.
+          if (numToStart > (this->MaxLoad - systemLoad))
+            {
+            numToStart = this->MaxLoad - systemLoad;
+            }
+
           maxLoadOk = processors <= (this->MaxLoad - systemLoad);
+          if (maxLoadOk)
+            {
+            cmCTestLog(this->CTest, HANDLER_OUTPUT, "OK to run " << GetName(*test) << ", it requires " << processors << " procs & system load is: " << info.GetLoadAverage() << std::endl);
+            }
           }
         else
           {
@@ -354,13 +390,23 @@ void cmCTestMultiProcessHandler::StartNextTests()
     strftime(current_time, 1000, "%s", t);
     cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Time: "
       << current_time << ",");
-    cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Load: "
-      << info.GetLoadAverage() << ",");
-    cmCTestLog(this->CTest, HANDLER_OUTPUT, "Max Allowed Load: "
-      << this->MaxLoad << ",");
-    cmCTestLog(this->CTest, HANDLER_OUTPUT, "Smallest test "
-      << testWithMinProcessors << " requries " << minProcessorsRequired);
-    cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
+
+    if (this->SerialTestRunning)
+      {
+      cmCTestLog(this->CTest, HANDLER_OUTPUT,
+        "Waiting for RUN_SERIAL test to finish." << std::endl);
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
+      }
+    else
+      {
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Load: "
+        << info.GetLoadAverage() << ",");
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "Max Allowed Load: "
+        << this->MaxLoad << ",");
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "Smallest test "
+        << testWithMinProcessors << " requires " << minProcessorsRequired);
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
+      }
 
     // Wait between 1 and 60 seconds before trying again...
     cmCTestScriptHandler::SleepInSeconds(rand() % 60 + 1);
@@ -418,6 +464,11 @@ bool cmCTestMultiProcessHandler::CheckOutput()
     this->WriteCheckpoint(test);
     this->UnlockResources(test);
     this->RunningCount -= GetProcessorsUsed(test);
+    if (this->Properties[test]->RunSerial)
+      {
+      this->SerialTestRunning = false;
+      }
+
     delete p;
     }
   return true;
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index e60aef0..461c728 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -124,6 +124,7 @@ protected:
   cmCTest* CTest;
   bool HasCycles;
   bool Quiet;
+  bool SerialTestRunning;
 };
 
 #endif

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=856b08211b9d112f4992e4939782eb8ed0ded094
commit 856b08211b9d112f4992e4939782eb8ed0ded094
Author:     Betsy McPhail <betsy.mcphail at kitware.com>
AuthorDate: Wed Apr 1 13:05:55 2015 -0400
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Fri Jun 5 16:15:32 2015 -0400

    More improvements to max-load check
    
    * Get the system load after the lock.
    * If fail to start any tests, wait a variable amount of time (1 - 60 seconds).

diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index d5a135e..bfcd74d 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -288,8 +288,6 @@ void cmCTestMultiProcessHandler::StartNextTests()
   for(TestList::iterator test = copy.begin(); test != copy.end(); ++test)
     {
     size_t processors = GetProcessorsUsed(*test);
-    const double systemLoad = info.GetLoadAverage();
-
     bool maxLoadOk;
     if (this->MaxLoad > 0)
       {
@@ -299,6 +297,7 @@ void cmCTestMultiProcessHandler::StartNextTests()
         cmFileLockResult result = maxLoadLock.Lock(lockFile, 1);
         if (result.IsOk())
           {
+          const double systemLoad = info.GetLoadAverage();
           maxLoadOk = processors <= (this->MaxLoad - systemLoad);
           }
         else
@@ -363,8 +362,8 @@ void cmCTestMultiProcessHandler::StartNextTests()
       << testWithMinProcessors << " requries " << minProcessorsRequired);
     cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
 
-    // Wait before trying again...
-    cmCTestScriptHandler::SleepInSeconds(1);
+    // Wait between 1 and 60 seconds before trying again...
+    cmCTestScriptHandler::SleepInSeconds(rand() % 60 + 1);
     }
 }
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ba5c785567b3af2c3221f5550d5561e4c96f6366
commit ba5c785567b3af2c3221f5550d5561e4c96f6366
Author:     Betsy McPhail <betsy.mcphail at kitware.com>
AuthorDate: Tue Mar 24 17:32:42 2015 -0400
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Fri Jun 5 16:15:32 2015 -0400

    Improvements to max-load monitoring
    
    Each process is required to hold a common file lock before checking
    the system load.

diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index c91321b..4589f32 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -66,6 +66,12 @@ Options
  number of jobs.  This option can also be set by setting the
  environment variable ``CTEST_PARALLEL_LEVEL``.
 
+``--max-load <level>``
+ Set maximum allowed machine load.
+
+ This option tells ctest to only start tests that will not increase
+ the machine load above the given level.
+
 ``-Q,--quiet``
  Make ctest quiet.
 
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index fcfa6fa..d5a135e 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -15,6 +15,8 @@
 #include "cmCTest.h"
 #include "cmCTestScriptHandler.h"
 #include "cmSystemTools.h"
+#include "cmFileLock.h"
+#include "cmFileLockResult.h"
 #include <stdlib.h>
 #include <stack>
 #include <list>
@@ -267,16 +269,55 @@ void cmCTestMultiProcessHandler::StartNextTests()
   std::string testWithMinProcessors = "";
 
   cmsys::SystemInformation info;
+  const std::string lockFile = "/tmp/.cmake_maxload.lock"; // TODO: Filename
+  if (this->MaxLoad > 0)
+    {
+    if (!cmSystemTools::FileExists(lockFile))
+      {
+      FILE *file = cmsys::SystemTools::Fopen(lockFile, "w");
+      if (!file)
+        {
+        // TODO: ?
+        }
+      fclose(file);
+      }
+    }
+  cmFileLock maxLoadLock;
 
   TestList copy = this->SortedTests;
   for(TestList::iterator test = copy.begin(); test != copy.end(); ++test)
     {
     size_t processors = GetProcessorsUsed(*test);
     const double systemLoad = info.GetLoadAverage();
-    const bool maxLoadOk = (this->MaxLoad > 0) ?
-      processors <= (this->MaxLoad - systemLoad) : true;
 
-    allTestsFailedMaxLoadCheck &= !maxLoadOk;
+    bool maxLoadOk;
+    if (this->MaxLoad > 0)
+      {
+      // First, try to get file lock..
+      if (!maxLoadLock.IsLocked(lockFile))
+        {
+        cmFileLockResult result = maxLoadLock.Lock(lockFile, 1);
+        if (result.IsOk())
+          {
+          maxLoadOk = processors <= (this->MaxLoad - systemLoad);
+          }
+        else
+          {
+          maxLoadOk = false;
+          }
+        }
+      else
+        {
+        maxLoadOk = false;
+        }
+
+      allTestsFailedMaxLoadCheck &= !maxLoadOk;
+      }
+    else
+      {
+      maxLoadOk = true;
+      }
+
     if (processors <= minProcessorsRequired)
       {
       minProcessorsRequired = processors;
@@ -285,34 +326,25 @@ void cmCTestMultiProcessHandler::StartNextTests()
 
     if(maxLoadOk && processors <= numToStart && this->StartTest(*test))
       {
+      maxLoadLock.Release();
+
       if(this->StopTimePassed)
         {
         return;
         }
 
-      cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** STARTED TEST : "
-        << GetName(*test)  << ",");
-      time_t currenttime = time(0);
-      struct tm* t = localtime(&currenttime);
-      char current_time[1024];
-      strftime(current_time, 1000, "%s", t);
-      cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Time: "
-        << current_time << ",");
-      cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Load: "
-        << systemLoad << ",");
-      cmCTestLog(this->CTest, HANDLER_OUTPUT, "Max Allowed Load: "
-        << this->MaxLoad << ",");
-      cmCTestLog(this->CTest, HANDLER_OUTPUT, "Test Processors: "
-        << processors);
-      cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
-
       numToStart -= processors;
       }
     else if(numToStart == 0)
       {
+      maxLoadLock.Release();
       return;
       }
-    }
+    else
+      {
+      maxLoadLock.Release();
+      }
+    }   // for
 
   if (allTestsFailedMaxLoadCheck)
     {

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=44e1fd0af4defe80e903a18d72e5ff8488b0bc42
commit 44e1fd0af4defe80e903a18d72e5ff8488b0bc42
Author:     Betsy McPhail <betsy.mcphail at kitware.com>
AuthorDate: Thu Feb 26 09:21:44 2015 -0500
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Fri Jun 5 16:15:31 2015 -0400

    Added debug output to determine why tests hang before completion
    
    Also, moved system load functions from cmSystemTools to kwsys/SystemInformation.

diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 7a401cb..fcfa6fa 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -20,6 +20,7 @@
 #include <list>
 #include <float.h>
 #include <cmsys/FStream.hxx>
+#include <cmsys/SystemInformation.hxx>
 
 class TestComparator
 {
@@ -265,13 +266,15 @@ void cmCTestMultiProcessHandler::StartNextTests()
   size_t minProcessorsRequired = this->ParallelLevel;
   std::string testWithMinProcessors = "";
 
+  cmsys::SystemInformation info;
+
   TestList copy = this->SortedTests;
   for(TestList::iterator test = copy.begin(); test != copy.end(); ++test)
     {
     size_t processors = GetProcessorsUsed(*test);
-
+    const double systemLoad = info.GetLoadAverage();
     const bool maxLoadOk = (this->MaxLoad > 0) ?
-      processors <= (this->MaxLoad - cmSystemTools::GetLoadAverage()) : true;
+      processors <= (this->MaxLoad - systemLoad) : true;
 
     allTestsFailedMaxLoadCheck &= !maxLoadOk;
     if (processors <= minProcessorsRequired)
@@ -286,6 +289,23 @@ void cmCTestMultiProcessHandler::StartNextTests()
         {
         return;
         }
+
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** STARTED TEST : "
+        << GetName(*test)  << ",");
+      time_t currenttime = time(0);
+      struct tm* t = localtime(&currenttime);
+      char current_time[1024];
+      strftime(current_time, 1000, "%s", t);
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Time: "
+        << current_time << ",");
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Load: "
+        << systemLoad << ",");
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "Max Allowed Load: "
+        << this->MaxLoad << ",");
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "Test Processors: "
+        << processors);
+      cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
+
       numToStart -= processors;
       }
     else if(numToStart == 0)
@@ -296,15 +316,20 @@ void cmCTestMultiProcessHandler::StartNextTests()
 
   if (allTestsFailedMaxLoadCheck)
     {
-    cmCTestLog(this->CTest, DEBUG, "Time: " << this->CTest->CurrentTime()
-      << std::endl);
-    cmCTestLog(this->CTest, DEBUG, "Current Load: "
-      << cmSystemTools::GetLoadAverage() << std::endl);
-    cmCTestLog(this->CTest, DEBUG, "Max Load: " << this->MaxLoad << std::endl);
-    cmCTestLog(this->CTest, DEBUG, " Smallest test " << testWithMinProcessors
-      << " requries " << minProcessorsRequired
-      << " cores/processes and can't be run without violating the max load."
-      << std::endl);
+    cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING,");
+    time_t currenttime = time(0);
+    struct tm* t = localtime(&currenttime);
+    char current_time[1024];
+    strftime(current_time, 1000, "%s", t);
+    cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Time: "
+      << current_time << ",");
+    cmCTestLog(this->CTest, HANDLER_OUTPUT, "System Load: "
+      << info.GetLoadAverage() << ",");
+    cmCTestLog(this->CTest, HANDLER_OUTPUT, "Max Allowed Load: "
+      << this->MaxLoad << ",");
+    cmCTestLog(this->CTest, HANDLER_OUTPUT, "Smallest test "
+      << testWithMinProcessors << " requries " << minProcessorsRequired);
+    cmCTestLog(this->CTest, HANDLER_OUTPUT, "*****" << std::endl);
 
     // Wait before trying again...
     cmCTestScriptHandler::SleepInSeconds(1);
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 16382da..e2adabe 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -2955,107 +2955,3 @@ bool cmSystemTools::StringToLong(const char* str, long* value)
   *value = strtol(str, &endp, 10);
   return (*endp == '\0') && (endp != str) && (errno == 0);
 }
-
-//----------------------------------------------------------------------------
-namespace{
-int get_processor_count()
-{
-#ifdef _WIN32
-  SYSTEM_INFO info;
-  GetSystemInfo(&info);
-  return info.dwNumberOfProcessors;
-#else
-  return sysconf(_SC_NPROCESSORS_ONLN);
-#endif
-}
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-double calculate_processor_load(uint64_t idleTicks, uint64_t totalTicks)
-{
-  static uint64_t previousIdleTicks = 0;
-  static uint64_t previousTotalTicks = 0;
-  static double previousLoad = -0.0;
-
-  uint64_t idleTicksSinceLastTime = idleTicks - previousIdleTicks;
-  uint64_t totalTicksSinceLastTime = totalTicks - previousTotalTicks;
-
-  bool firstCall = (previousTotalTicks == 0);
-  bool ticksNotUpdatedSinceLastCall = (totalTicksSinceLastTime == 0);
-
-  double load;
-  if (firstCall || ticksNotUpdatedSinceLastCall)
-    {
-    load = previousLoad;
-    }
-  else
-    {
-    // Calculate load.
-    double idleToTotalRatio =
-      ((double)idleTicksSinceLastTime) / totalTicksSinceLastTime;
-    double loadSinceLastCall = 1.0 - idleToTotalRatio;
-
-    // Filter/smooth result when possible.
-    if (previousLoad > 0)
-      {
-      load = 0.9 * previousLoad + 0.1 * loadSinceLastCall;
-      }
-    else
-      {
-      load = loadSinceLastCall;
-      }
-    }
-
-  previousLoad = load;
-  previousTotalTicks = totalTicks;
-  previousIdleTicks = idleTicks;
-
-  return load;
-}
-
-uint64_t file_time_to_tick_count(const FILETIME & ft)
-{
-  uint64_t high = (((uint64_t)(ft.dwHighDateTime)) << 32);
-  uint64_t low = ft.dwLowDateTime;
-  return (high | low);
-}
-#endif
-
-}  // namespace
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-double cmSystemTools::GetLoadAverage()
-{
-  FILETIME idleTime, kernelTime, userTime;
-  BOOL getSystemTimeSucceeded =
-    GetSystemTimes(&idleTime, &kernelTime, &userTime);
-
-  double posixCompatibleLoad;
-  if (getSystemTimeSucceeded)
-    {
-    uint64_t idleTicks = file_time_to_tick_count(idleTime);
-
-    // kernelTime from GetSystemTimes already includes idleTime.
-    uint64_t totalTicks = file_time_to_tick_count(kernelTime) +
-                            file_time_to_tick_count(userTime);
-
-    double processorLoad = calculate_processor_load(idleTicks, totalTicks);
-    posixCompatibleLoad = processorLoad * get_processor_count();
-    }
-  else
-    {
-    posixCompatibleLoad = -0.0;
-    }
-  return posixCompatibleLoad;
-}
-#else
-double cmSystemTools::GetLoadAverage()
-{
-  double loadavg[3] = { 0.0f, 0.0f, 0.0f };
-  if (getloadavg(loadavg, 3) < 0)
-    {
-    // Return error here instead?
-    return -0.0f;
-    }
-  return loadavg[0];
-}
-#endif
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 30ec449..6feb6c5 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -470,10 +470,6 @@ public:
   /** Convert string to long. Expected that the whole string is an integer */
   static bool StringToLong(const char* str, long* value);
 
-  /** Return the load average of the machine. A negative value is returned on
-      error.  */
-  static double GetLoadAverage();
-
 #ifdef _WIN32
   struct WindowsFileRetry
   {

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=646eb9b2a5504e4114b87cfb60cec292a306ddb2
commit 646eb9b2a5504e4114b87cfb60cec292a306ddb2
Author:     Betsy McPhail <betsy.mcphail at kitware.com>
AuthorDate: Tue Feb 17 16:06:01 2015 -0500
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Fri Jun 5 16:14:41 2015 -0400

    Added document with release notes.

diff --git a/Help/release/dev/ctest-max-load-option.rst b/Help/release/dev/ctest-max-load-option.rst
new file mode 100644
index 0000000..037c61f
--- /dev/null
+++ b/Help/release/dev/ctest-max-load-option.rst
@@ -0,0 +1,6 @@
+ctest-max-load-option
+--------------
+
+* It is now possible to set the 'max-load' option in CTest.
+  If set, then CTest will not run any tests that would be projected
+  to increase the machine load above this level.

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=28c028e5fb5d0f542a74df738b4658d112c49b95
commit 28c028e5fb5d0f542a74df738b4658d112c49b95
Author:     Betsy McPhail <betsy.mcphail at kitware.com>
AuthorDate: Tue Feb 17 15:54:42 2015 -0500
Commit:     Zack Galbreath <zack.galbreath at kitware.com>
CommitDate: Fri Jun 5 16:14:41 2015 -0400

    Added "--max-load" option to CTest
    
    When max-load is set, only run tests such that:
     <current_load> + <test_processors> <= <max-load>
    
    If no tests meet this criteria, wait for 1 second and try again.
    
    The debug option will show more information.

diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index bd090db..7a401cb 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -13,6 +13,7 @@
 #include "cmProcess.h"
 #include "cmStandardIncludes.h"
 #include "cmCTest.h"
+#include "cmCTestScriptHandler.h"
 #include "cmSystemTools.h"
 #include <stdlib.h>
 #include <stack>
@@ -40,6 +41,7 @@ private:
 cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
 {
   this->ParallelLevel = 1;
+  this->MaxLoad = 0;
   this->Completed = 0;
   this->RunningCount = 0;
   this->StopTimePassed = false;
@@ -83,6 +85,11 @@ void cmCTestMultiProcessHandler::SetParallelLevel(size_t level)
   this->ParallelLevel = level < 1 ? 1 : level;
 }
 
+void cmCTestMultiProcessHandler::SetMaxLoad(size_t max)
+{
+  this->MaxLoad = max < 1 ? 0 : max;
+}
+
 //---------------------------------------------------------
 void cmCTestMultiProcessHandler::RunTests()
 {
@@ -209,6 +216,12 @@ inline size_t cmCTestMultiProcessHandler::GetProcessorsUsed(int test)
   return processors;
 }
 
+std::string cmCTestMultiProcessHandler::GetName(int test)
+{
+  return this->Properties[test]->Name;
+}
+
+
 //---------------------------------------------------------
 bool cmCTestMultiProcessHandler::StartTest(int test)
 {
@@ -248,24 +261,54 @@ void cmCTestMultiProcessHandler::StartNextTests()
     return;
     }
 
+  bool allTestsFailedMaxLoadCheck = true;
+  size_t minProcessorsRequired = this->ParallelLevel;
+  std::string testWithMinProcessors = "";
+
   TestList copy = this->SortedTests;
   for(TestList::iterator test = copy.begin(); test != copy.end(); ++test)
     {
     size_t processors = GetProcessorsUsed(*test);
 
-    if(processors <= numToStart && this->StartTest(*test))
+    const bool maxLoadOk = (this->MaxLoad > 0) ?
+      processors <= (this->MaxLoad - cmSystemTools::GetLoadAverage()) : true;
+
+    allTestsFailedMaxLoadCheck &= !maxLoadOk;
+    if (processors <= minProcessorsRequired)
       {
-        if(this->StopTimePassed)
-          {
-          return;
-          }
-        numToStart -= processors;
+      minProcessorsRequired = processors;
+      testWithMinProcessors = GetName(*test);
+      }
+
+    if(maxLoadOk && processors <= numToStart && this->StartTest(*test))
+      {
+      if(this->StopTimePassed)
+        {
+        return;
+        }
+      numToStart -= processors;
       }
     else if(numToStart == 0)
       {
       return;
       }
     }
+
+  if (allTestsFailedMaxLoadCheck)
+    {
+    cmCTestLog(this->CTest, DEBUG, "Time: " << this->CTest->CurrentTime()
+      << std::endl);
+    cmCTestLog(this->CTest, DEBUG, "Current Load: "
+      << cmSystemTools::GetLoadAverage() << std::endl);
+    cmCTestLog(this->CTest, DEBUG, "Max Load: " << this->MaxLoad << std::endl);
+    cmCTestLog(this->CTest, DEBUG, " Smallest test " << testWithMinProcessors
+      << " requries " << minProcessorsRequired
+      << " cores/processes and can't be run without violating the max load."
+      << std::endl);
+
+    // Wait before trying again...
+    cmCTestScriptHandler::SleepInSeconds(1);
+    }
 }
 
 //---------------------------------------------------------
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index 6440fbc..e60aef0 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -37,6 +37,7 @@ public:
   void SetTests(TestMap& tests, PropertiesMap& properties);
   // Set the max number of tests that can be run at the same time.
   void SetParallelLevel(size_t);
+  void SetMaxLoad(size_t max);
   virtual void RunTests();
   void PrintTestList();
   void PrintLabels();
@@ -93,6 +94,7 @@ protected:
   bool CheckCycles();
   int FindMaxIndex();
   inline size_t GetProcessorsUsed(int index);
+  std::string GetName(int index);
 
   void LockResources(int index);
   void UnlockResources(int index);
@@ -116,6 +118,7 @@ protected:
   std::set<std::string> LockedResources;
   std::vector<cmCTestTestHandler::cmCTestTestResult>* TestResults;
   size_t ParallelLevel; // max number of process that can be run at once
+  size_t MaxLoad;
   std::set<cmCTestRunTest*> RunningTests;  // current running tests
   cmCTestTestHandler * TestHandler;
   cmCTest* CTest;
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 70b7f5c..3d6b746 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1060,6 +1060,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string> &passed,
     new cmCTestBatchTestHandler : new cmCTestMultiProcessHandler;
   parallel->SetCTest(this->CTest);
   parallel->SetParallelLevel(this->CTest->GetParallelLevel());
+  parallel->SetMaxLoad(this->CTest->GetMaxLoad());
   parallel->SetTestHandler(this);
   parallel->SetQuiet(this->Quiet);
 
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index e3b7a2b..fc36b62 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -294,6 +294,7 @@ cmCTest::cmCTest()
   this->LabelSummary           = true;
   this->ParallelLevel          = 1;
   this->ParallelLevelSetInCli  = false;
+  this->MaxLoad                = 0;
   this->SubmitIndex            = 0;
   this->Failover               = false;
   this->BatchJobs              = false;
@@ -393,6 +394,11 @@ void cmCTest::SetParallelLevel(int level)
   this->ParallelLevel = level < 1 ? 1 : level;
 }
 
+void cmCTest::SetMaxLoad(int max)
+{
+  this->MaxLoad = max < 1 ? 0 : max;
+}
+
 //----------------------------------------------------------------------------
 bool cmCTest::ShouldCompressTestOutput()
 {
@@ -2051,6 +2057,13 @@ bool cmCTest::HandleCommandLineArguments(size_t &i,
       }
     }
 
+  if(this->CheckArgument(arg, "--max-load") && i < args.size() - 1)
+    {
+    i++;
+    int max = atoi(args[i].c_str());
+    this->SetMaxLoad(max);
+    }
+
   if(this->CheckArgument(arg, "--no-compress-output"))
     {
     this->CompressTestOutput = false;
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index db3ea10..4fbfbff 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -161,6 +161,9 @@ public:
   int GetParallelLevel() { return this->ParallelLevel; }
   void SetParallelLevel(int);
 
+  int GetMaxLoad() { return this->MaxLoad; }
+  void SetMaxLoad(int);
+
   /**
    * Check if CTest file exists
    */
@@ -499,6 +502,8 @@ private:
   int                     ParallelLevel;
   bool                    ParallelLevelSetInCli;
 
+  int                     MaxLoad;
+
   int                     CompatibilityMode;
 
   // information for the --build-and-test options
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index e2adabe..16382da 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -2955,3 +2955,107 @@ bool cmSystemTools::StringToLong(const char* str, long* value)
   *value = strtol(str, &endp, 10);
   return (*endp == '\0') && (endp != str) && (errno == 0);
 }
+
+//----------------------------------------------------------------------------
+namespace{
+int get_processor_count()
+{
+#ifdef _WIN32
+  SYSTEM_INFO info;
+  GetSystemInfo(&info);
+  return info.dwNumberOfProcessors;
+#else
+  return sysconf(_SC_NPROCESSORS_ONLN);
+#endif
+}
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+double calculate_processor_load(uint64_t idleTicks, uint64_t totalTicks)
+{
+  static uint64_t previousIdleTicks = 0;
+  static uint64_t previousTotalTicks = 0;
+  static double previousLoad = -0.0;
+
+  uint64_t idleTicksSinceLastTime = idleTicks - previousIdleTicks;
+  uint64_t totalTicksSinceLastTime = totalTicks - previousTotalTicks;
+
+  bool firstCall = (previousTotalTicks == 0);
+  bool ticksNotUpdatedSinceLastCall = (totalTicksSinceLastTime == 0);
+
+  double load;
+  if (firstCall || ticksNotUpdatedSinceLastCall)
+    {
+    load = previousLoad;
+    }
+  else
+    {
+    // Calculate load.
+    double idleToTotalRatio =
+      ((double)idleTicksSinceLastTime) / totalTicksSinceLastTime;
+    double loadSinceLastCall = 1.0 - idleToTotalRatio;
+
+    // Filter/smooth result when possible.
+    if (previousLoad > 0)
+      {
+      load = 0.9 * previousLoad + 0.1 * loadSinceLastCall;
+      }
+    else
+      {
+      load = loadSinceLastCall;
+      }
+    }
+
+  previousLoad = load;
+  previousTotalTicks = totalTicks;
+  previousIdleTicks = idleTicks;
+
+  return load;
+}
+
+uint64_t file_time_to_tick_count(const FILETIME & ft)
+{
+  uint64_t high = (((uint64_t)(ft.dwHighDateTime)) << 32);
+  uint64_t low = ft.dwLowDateTime;
+  return (high | low);
+}
+#endif
+
+}  // namespace
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+double cmSystemTools::GetLoadAverage()
+{
+  FILETIME idleTime, kernelTime, userTime;
+  BOOL getSystemTimeSucceeded =
+    GetSystemTimes(&idleTime, &kernelTime, &userTime);
+
+  double posixCompatibleLoad;
+  if (getSystemTimeSucceeded)
+    {
+    uint64_t idleTicks = file_time_to_tick_count(idleTime);
+
+    // kernelTime from GetSystemTimes already includes idleTime.
+    uint64_t totalTicks = file_time_to_tick_count(kernelTime) +
+                            file_time_to_tick_count(userTime);
+
+    double processorLoad = calculate_processor_load(idleTicks, totalTicks);
+    posixCompatibleLoad = processorLoad * get_processor_count();
+    }
+  else
+    {
+    posixCompatibleLoad = -0.0;
+    }
+  return posixCompatibleLoad;
+}
+#else
+double cmSystemTools::GetLoadAverage()
+{
+  double loadavg[3] = { 0.0f, 0.0f, 0.0f };
+  if (getloadavg(loadavg, 3) < 0)
+    {
+    // Return error here instead?
+    return -0.0f;
+    }
+  return loadavg[0];
+}
+#endif
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 6feb6c5..30ec449 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -470,6 +470,10 @@ public:
   /** Convert string to long. Expected that the whole string is an integer */
   static bool StringToLong(const char* str, long* value);
 
+  /** Return the load average of the machine. A negative value is returned on
+      error.  */
+  static double GetLoadAverage();
+
 #ifdef _WIN32
   struct WindowsFileRetry
   {

-----------------------------------------------------------------------

Summary of changes:
 Help/command/ctest_test.rst                        |    7 +-
 Help/manual/cmake-variables.7.rst                  |    2 +
 Help/manual/ctest.1.rst                            |    4 +
 Help/release/dev/ctest-test-load-option.rst        |    6 +
 Help/variable/CMAKE_TEST_LOAD.rst                  |    9 +
 Help/variable/CTEST_TEST_LOAD.rst                  |   24 +++
 Modules/CTest.cmake                                |    3 +
 Modules/DartConfiguration.tcl.in                   |    4 +
 Source/CTest/cmCTestMultiProcessHandler.cxx        |  193 +++++++++++++++++++-
 Source/CTest/cmCTestMultiProcessHandler.h          |    4 +
 Source/CTest/cmCTestTestCommand.cxx                |   20 ++
 Source/CTest/cmCTestTestCommand.h                  |    1 +
 Source/CTest/cmCTestTestHandler.cxx                |    1 +
 Source/cmCTest.cxx                                 |   17 ++
 Source/cmCTest.h                                   |    5 +
 Source/ctest.cxx                                   |    1 +
 Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake |   28 +++
 .../CTestCommandLine/test-load-fail-stderr.txt     |    1 +
 .../CTestCommandLine/test-load-fail-stdout.txt     |    2 +
 .../test-load-pass-stderr.txt}                     |    0
 .../CTestCommandLine/test-load-pass-stdout.txt     |    7 +
 21 files changed, 329 insertions(+), 10 deletions(-)
 create mode 100644 Help/release/dev/ctest-test-load-option.rst
 create mode 100644 Help/variable/CMAKE_TEST_LOAD.rst
 create mode 100644 Help/variable/CTEST_TEST_LOAD.rst
 create mode 100644 Tests/RunCMake/CTestCommandLine/test-load-fail-stderr.txt
 create mode 100644 Tests/RunCMake/CTestCommandLine/test-load-fail-stdout.txt
 copy Tests/RunCMake/{ctest_start/StartQuiet-stdout.txt => CTestCommandLine/test-load-pass-stderr.txt} (100%)
 create mode 100644 Tests/RunCMake/CTestCommandLine/test-load-pass-stdout.txt


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list