Commit 016601e5 authored by Brad King's avatar Brad King

Merge branch 'backport-ctest-resource-groups'

parents 370fe149 c1435d98
......@@ -17,7 +17,7 @@ Perform the :ref:`CTest Test Step` as a :ref:`Dashboard Client`.
[EXCLUDE_FIXTURE_SETUP <regex>]
[EXCLUDE_FIXTURE_CLEANUP <regex>]
[PARALLEL_LEVEL <level>]
[HARDWARE_SPEC_FILE <file>]
[RESOURCE_SPEC_FILE <file>]
[TEST_LOAD <threshold>]
[SCHEDULE_RANDOM <ON|OFF>]
[STOP_TIME <time-of-day>]
......@@ -83,10 +83,10 @@ The options are:
Specify a positive number representing the number of tests to
be run in parallel.
``HARDWARE_SPEC_FILE <file>``
``RESOURCE_SPEC_FILE <file>``
Specify a
:ref:`hardware specification file <ctest-hardware-specification-file>`. See
:ref:`ctest-hardware-allocation` for more information.
:ref:`resource specification file <ctest-resource-specification-file>`. See
:ref:`ctest-resource-allocation` for more information.
``TEST_LOAD <threshold>``
While running tests in parallel, try not to start tests when they
......
......@@ -415,10 +415,10 @@ Properties on Tests
/prop_test/LABELS
/prop_test/MEASUREMENT
/prop_test/PASS_REGULAR_EXPRESSION
/prop_test/PROCESSES
/prop_test/PROCESSOR_AFFINITY
/prop_test/PROCESSORS
/prop_test/REQUIRED_FILES
/prop_test/RESOURCE_GROUPS
/prop_test/RESOURCE_LOCK
/prop_test/RUN_SERIAL
/prop_test/SKIP_REGULAR_EXPRESSION
......
This diff is collapsed.
PROCESSES
----------
Set to specify the number of processes spawned by a test, and the resources
that they require. See :ref:`hardware allocation <ctest-hardware-allocation>`
for more information on how this property integrates into the CTest hardware
allocation feature.
The ``PROCESSES`` property is a :ref:`semicolon-separated list <CMake Language
Lists>` of process descriptions. Each process description consists of an
optional number of processes for the description followed by a series of
resource requirements for those processes. These requirements (and the number
of processes) are separated by commas. The resource requirements consist of the
name of a resource type, followed by a colon, followed by an unsigned integer
specifying the number of slots required on one resource of the given type.
Please note that these processes are not spawned by CTest. The ``PROCESSES``
property merely tells CTest what processes the test expects to launch. It is up
to the test itself to do this process spawning, and read the :ref:`environment
variables <ctest-hardware-environment-variables>` to determine which resources
each process has been allocated.
Consider the following example:
.. code-block:: cmake
add_test(NAME MyTest COMMAND MyExe)
set_property(TEST MyTest PROPERTY PROCESSES
"2,gpus:2"
"gpus:4,crypto_chips:2")
In this example, there are two process descriptions (implicitly separated by a
semicolon.) The content of the first description is ``2,gpus:2``. This
description spawns 2 processes, each of which requires 2 slots from a single
GPU. The content of the second description is ``gpus:4,crypto_chips:2``. This
description does not specify a process count, so a default of 1 is assumed.
This single process requires 4 slots from a single GPU and 2 slots from a
single cryptography chip. In total, 3 processes are spawned from this test,
each with their own unique requirements.
When CTest sets the :ref:`environment variables
<ctest-hardware-environment-variables>` for a test, it assigns a process number
based on the process description, starting at 0 on the left and the number of
processes minus 1 on the right. For example, in the example above, the two
processes in the first description would have IDs of 0 and 1, and the single
process in the second description would have an ID of 2.
Both the ``PROCESSES`` and :prop_test:`RESOURCE_LOCK` properties serve similar
purposes, but they are distinct and orthogonal. Resources specified by
``PROCESSES`` do not affect :prop_test:`RESOURCE_LOCK`, and vice versa. Whereas
:prop_test:`RESOURCE_LOCK` is a simpler property that is used for locking one
global resource, ``PROCESSES`` is a more advanced property that allows multiple
tests to simultaneously use multiple resources of the same type, specifying
their requirements in a fine-grained manner.
RESOURCE_GROUPS
---------------
Specify resources required by a test, grouped in a way that is meaningful to
the test. See :ref:`resource allocation <ctest-resource-allocation>`
for more information on how this property integrates into the CTest resource
allocation feature.
The ``RESOURCE_GROUPS`` property is a :ref:`semicolon-separated list <CMake
Language Lists>` of group descriptions. Each entry consists of an optional
number of groups using the description followed by a series of resource
requirements for those groups. These requirements (and the number of groups)
are separated by commas. The resource requirements consist of the name of a
resource type, followed by a colon, followed by an unsigned integer
specifying the number of slots required on one resource of the given type.
The ``RESOURCE_GROUPS`` property tells CTest what resources a test expects
to use grouped in a way meaningful to the test. The test itself must read
the :ref:`environment variables <ctest-resource-environment-variables>` to
determine which resources have been allocated to each group. For example,
each group may correspond to a process the test will spawn when executed.
Consider the following example:
.. code-block:: cmake
add_test(NAME MyTest COMMAND MyExe)
set_property(TEST MyTest PROPERTY RESOURCE_GROUPS
"2,gpus:2"
"gpus:4,crypto_chips:2")
In this example, there are two group descriptions (implicitly separated by a
semicolon.) The content of the first description is ``2,gpus:2``. This
description specifies 2 groups, each of which requires 2 slots from a single
GPU. The content of the second description is ``gpus:4,crypto_chips:2``. This
description does not specify a group count, so a default of 1 is assumed.
This single group requires 4 slots from a single GPU and 2 slots from a
single cryptography chip. In total, 3 resource groups are specified for this
test, each with its own unique requirements.
When CTest sets the :ref:`environment variables
<ctest-resource-environment-variables>` for a test, it assigns a group number
based on the group description, starting at 0 on the left and the number of
groups minus 1 on the right. For example, in the example above, the two
groups in the first description would have IDs of 0 and 1, and the single
group in the second description would have an ID of 2.
Both the ``RESOURCE_GROUPS`` and :prop_test:`RESOURCE_LOCK` properties serve
similar purposes, but they are distinct and orthogonal. Resources specified by
``RESOURCE_GROUPS`` do not affect :prop_test:`RESOURCE_LOCK`, and vice versa.
Whereas :prop_test:`RESOURCE_LOCK` is a simpler property that is used for
locking one global resource, ``RESOURCE_GROUPS`` is a more advanced property
that allows multiple tests to simultaneously use multiple resources of the
same type, specifying their requirements in a fine-grained manner.
......@@ -9,10 +9,10 @@ not to run concurrently.
See also :prop_test:`FIXTURES_REQUIRED` if the resource requires any setup or
cleanup steps.
Both the :prop_test:`PROCESSES` and ``RESOURCE_LOCK`` properties serve similar
purposes, but they are distinct and orthogonal. Resources specified by
:prop_test:`PROCESSES` do not affect ``RESOURCE_LOCK``, and vice versa. Whereas
``RESOURCE_LOCK`` is a simpler property that is used for locking one global
resource, :prop_test:`PROCESSES` is a more advanced property that allows
multiple tests to simultaneously use multiple resources of the same type,
specifying their requirements in a fine-grained manner.
Both the :prop_test:`RESOURCE_GROUPS` and ``RESOURCE_LOCK`` properties serve
similar purposes, but they are distinct and orthogonal. Resources specified by
:prop_test:`RESOURCE_GROUPS` do not affect ``RESOURCE_LOCK``, and vice versa.
Whereas ``RESOURCE_LOCK`` is a simpler property that is used for locking one
global resource, :prop_test:`RESOURCE_GROUPS` is a more advanced property
that allows multiple tests to simultaneously use multiple resources of the
same type, specifying their requirements in a fine-grained manner.
......@@ -192,8 +192,8 @@ Autogen
CTest
-----
* :manual:`ctest(1)` now has the ability to serialize tests based on hardware
requirements for each test. See :ref:`ctest-hardware-allocation` for
* :manual:`ctest(1)` now has the ability to schedule tests based on resource
requirements for each test. See :ref:`ctest-resource-allocation` for
details.
* A new test property, :prop_test:`SKIP_REGULAR_EXPRESSION`, has been added.
......
......@@ -921,14 +921,14 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestEmptyBinaryDirectoryCommand.cxx
CTest/cmCTestGenericHandler.cxx
CTest/cmCTestHandlerCommand.cxx
CTest/cmCTestHardwareAllocator.cxx
CTest/cmCTestHardwareSpec.cxx
CTest/cmCTestResourceAllocator.cxx
CTest/cmCTestResourceSpec.cxx
CTest/cmCTestLaunch.cxx
CTest/cmCTestMemCheckCommand.cxx
CTest/cmCTestMemCheckHandler.cxx
CTest/cmCTestMultiProcessHandler.cxx
CTest/cmCTestProcessesLexerHelper.cxx
CTest/cmCTestReadCustomFilesCommand.cxx
CTest/cmCTestResourceGroupsLexerHelper.cxx
CTest/cmCTestRunScriptCommand.cxx
CTest/cmCTestRunTest.cxx
CTest/cmCTestScriptHandler.cxx
......@@ -960,9 +960,9 @@ set(CTEST_SRCS cmCTest.cxx
CTest/cmCTestP4.cxx
CTest/cmCTestP4.h
LexerParser/cmCTestProcessesLexer.cxx
LexerParser/cmCTestProcessesLexer.h
LexerParser/cmCTestProcessesLexer.in.l
LexerParser/cmCTestResourceGroupsLexer.cxx
LexerParser/cmCTestResourceGroupsLexer.h
LexerParser/cmCTestResourceGroupsLexer.in.l
)
# Build CTestLib
......
......@@ -23,7 +23,7 @@ namespace {
/*
* The following algorithm is used to do two things:
*
* 1) Determine if a test's hardware requirements can fit within the hardware
* 1) Determine if a test's resource requirements can fit within the resources
* present on the system, and
* 2) Do the actual allocation
*
......@@ -34,46 +34,46 @@ namespace {
* more combinations can be tried.
*/
template <typename AllocationStrategy>
static bool AllocateCTestHardware(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
const std::vector<std::string>& hardwareSorted, std::size_t currentIndex,
static bool AllocateCTestResources(
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
const std::vector<std::string>& resourcesSorted, std::size_t currentIndex,
std::vector<cmCTestBinPackerAllocation*>& allocations)
{
// Iterate through all large enough resources until we find a solution
std::size_t hardwareIndex = 0;
while (hardwareIndex < hardwareSorted.size()) {
auto const& resource = hardware.at(hardwareSorted[hardwareIndex]);
std::size_t resourceIndex = 0;
while (resourceIndex < resourcesSorted.size()) {
auto const& resource = resources.at(resourcesSorted[resourceIndex]);
if (resource.Free() >=
static_cast<unsigned int>(allocations[currentIndex]->SlotsNeeded)) {
// Preemptively allocate the resource
allocations[currentIndex]->Id = hardwareSorted[hardwareIndex];
allocations[currentIndex]->Id = resourcesSorted[resourceIndex];
if (currentIndex + 1 >= allocations.size()) {
// We have a solution
return true;
}
// Move the resource up the list until it is sorted again
auto hardware2 = hardware;
auto hardwareSorted2 = hardwareSorted;
hardware2[hardwareSorted2[hardwareIndex]].Locked +=
auto resources2 = resources;
auto resourcesSorted2 = resourcesSorted;
resources2[resourcesSorted2[resourceIndex]].Locked +=
allocations[currentIndex]->SlotsNeeded;
AllocationStrategy::IncrementalSort(hardware2, hardwareSorted2,
hardwareIndex);
AllocationStrategy::IncrementalSort(resources2, resourcesSorted2,
resourceIndex);
// Recurse one level deeper
if (AllocateCTestHardware<AllocationStrategy>(
hardware2, hardwareSorted2, currentIndex + 1, allocations)) {
if (AllocateCTestResources<AllocationStrategy>(
resources2, resourcesSorted2, currentIndex + 1, allocations)) {
return true;
}
}
// No solution found here, deallocate the resource and try the next one
allocations[currentIndex]->Id.clear();
auto freeSlots = hardware.at(hardwareSorted.at(hardwareIndex)).Free();
auto freeSlots = resources.at(resourcesSorted.at(resourceIndex)).Free();
do {
++hardwareIndex;
} while (hardwareIndex < hardwareSorted.size() &&
hardware.at(hardwareSorted.at(hardwareIndex)).Free() ==
++resourceIndex;
} while (resourceIndex < resourcesSorted.size() &&
resources.at(resourcesSorted.at(resourceIndex)).Free() ==
freeSlots);
}
......@@ -82,8 +82,8 @@ static bool AllocateCTestHardware(
}
template <typename AllocationStrategy>
static bool AllocateCTestHardware(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
static bool AllocateCTestResources(
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<cmCTestBinPackerAllocation>& allocations)
{
// Sort the resource requirements in descending order by slots needed
......@@ -99,103 +99,105 @@ static bool AllocateCTestHardware(
});
// Sort the resources according to sort strategy
std::vector<std::string> hardwareSorted;
hardwareSorted.reserve(hardware.size());
for (auto const& hw : hardware) {
hardwareSorted.push_back(hw.first);
std::vector<std::string> resourcesSorted;
resourcesSorted.reserve(resources.size());
for (auto const& res : resources) {
resourcesSorted.push_back(res.first);
}
AllocationStrategy::InitialSort(hardware, hardwareSorted);
AllocationStrategy::InitialSort(resources, resourcesSorted);
// Do the actual allocation
return AllocateCTestHardware<AllocationStrategy>(
hardware, hardwareSorted, std::size_t(0), allocationsPtr);
return AllocateCTestResources<AllocationStrategy>(
resources, resourcesSorted, std::size_t(0), allocationsPtr);
}
class RoundRobinAllocationStrategy
{
public:
static void InitialSort(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
std::vector<std::string>& hardwareSorted);
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<std::string>& resourcesSorted);
static void IncrementalSort(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
std::vector<std::string>& hardwareSorted, std::size_t lastAllocatedIndex);
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex);
};
void RoundRobinAllocationStrategy::InitialSort(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
std::vector<std::string>& hardwareSorted)
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<std::string>& resourcesSorted)
{
std::stable_sort(
hardwareSorted.rbegin(), hardwareSorted.rend(),
[&hardware](const std::string& id1, const std::string& id2) {
return hardware.at(id1).Free() < hardware.at(id2).Free();
resourcesSorted.rbegin(), resourcesSorted.rend(),
[&resources](const std::string& id1, const std::string& id2) {
return resources.at(id1).Free() < resources.at(id2).Free();
});
}
void RoundRobinAllocationStrategy::IncrementalSort(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
std::vector<std::string>& hardwareSorted, std::size_t lastAllocatedIndex)
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex)
{
auto tmp = hardwareSorted[lastAllocatedIndex];
auto tmp = resourcesSorted[lastAllocatedIndex];
std::size_t i = lastAllocatedIndex;
while (i < hardwareSorted.size() - 1 &&
hardware.at(hardwareSorted[i + 1]).Free() > hardware.at(tmp).Free()) {
hardwareSorted[i] = hardwareSorted[i + 1];
while (i < resourcesSorted.size() - 1 &&
resources.at(resourcesSorted[i + 1]).Free() >
resources.at(tmp).Free()) {
resourcesSorted[i] = resourcesSorted[i + 1];
++i;
}
hardwareSorted[i] = tmp;
resourcesSorted[i] = tmp;
}
class BlockAllocationStrategy
{
public:
static void InitialSort(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
std::vector<std::string>& hardwareSorted);
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<std::string>& resourcesSorted);
static void IncrementalSort(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
std::vector<std::string>& hardwareSorted, std::size_t lastAllocatedIndex);
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex);
};
void BlockAllocationStrategy::InitialSort(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
std::vector<std::string>& hardwareSorted)
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<std::string>& resourcesSorted)
{
std::stable_sort(
hardwareSorted.rbegin(), hardwareSorted.rend(),
[&hardware](const std::string& id1, const std::string& id2) {
return hardware.at(id1).Free() < hardware.at(id2).Free();
resourcesSorted.rbegin(), resourcesSorted.rend(),
[&resources](const std::string& id1, const std::string& id2) {
return resources.at(id1).Free() < resources.at(id2).Free();
});
}
void BlockAllocationStrategy::IncrementalSort(
const std::map<std::string, cmCTestHardwareAllocator::Resource>&,
std::vector<std::string>& hardwareSorted, std::size_t lastAllocatedIndex)
const std::map<std::string, cmCTestResourceAllocator::Resource>&,
std::vector<std::string>& resourcesSorted, std::size_t lastAllocatedIndex)
{
auto tmp = hardwareSorted[lastAllocatedIndex];
auto tmp = resourcesSorted[lastAllocatedIndex];
std::size_t i = lastAllocatedIndex;
while (i > 0) {
hardwareSorted[i] = hardwareSorted[i - 1];
resourcesSorted[i] = resourcesSorted[i - 1];
--i;
}
hardwareSorted[i] = tmp;
resourcesSorted[i] = tmp;
}
}
bool cmAllocateCTestHardwareRoundRobin(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
bool cmAllocateCTestResourcesRoundRobin(
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<cmCTestBinPackerAllocation>& allocations)
{
return AllocateCTestHardware<RoundRobinAllocationStrategy>(hardware,
allocations);
return AllocateCTestResources<RoundRobinAllocationStrategy>(resources,
allocations);
}
bool cmAllocateCTestHardwareBlock(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
bool cmAllocateCTestResourcesBlock(
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<cmCTestBinPackerAllocation>& allocations)
{
return AllocateCTestHardware<BlockAllocationStrategy>(hardware, allocations);
return AllocateCTestResources<BlockAllocationStrategy>(resources,
allocations);
}
......@@ -8,7 +8,7 @@
#include <string>
#include <vector>
#include "cmCTestHardwareAllocator.h"
#include "cmCTestResourceAllocator.h"
struct cmCTestBinPackerAllocation
{
......@@ -20,12 +20,12 @@ struct cmCTestBinPackerAllocation
bool operator!=(const cmCTestBinPackerAllocation& other) const;
};
bool cmAllocateCTestHardwareRoundRobin(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
bool cmAllocateCTestResourcesRoundRobin(
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<cmCTestBinPackerAllocation>& allocations);
bool cmAllocateCTestHardwareBlock(
const std::map<std::string, cmCTestHardwareAllocator::Resource>& hardware,
bool cmAllocateCTestResourcesBlock(
const std::map<std::string, cmCTestResourceAllocator::Resource>& resources,
std::vector<cmCTestBinPackerAllocation>& allocations);
#endif
......@@ -140,7 +140,7 @@ void cmCTestMultiProcessHandler::RunTests()
assert(this->Completed == this->Total);
assert(this->Tests.empty());
}
assert(this->AllHardwareAvailable());
assert(this->AllResourcesAvailable());
this->MarkFinished();
this->UpdateCostData();
......@@ -177,9 +177,9 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
}
testRun->SetIndex(test);
testRun->SetTestProperties(this->Properties[test]);
if (this->TestHandler->UseHardwareSpec) {
testRun->SetUseAllocatedHardware(true);
testRun->SetAllocatedHardware(this->AllocatedHardware[test]);
if (this->TestHandler->UseResourceSpec) {
testRun->SetUseAllocatedResources(true);
testRun->SetAllocatedResources(this->AllocatedResources[test]);
}
// Find any failed dependencies for this test. We assume the more common
......@@ -192,10 +192,10 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
// Always lock the resources we'll be using, even if we fail to set the
// working directory because FinishTestProcess() will try to unlock them
this->AllocateResources(test);
this->LockResources(test);
if (!this->TestsHaveSufficientHardware[test]) {
testRun->StartFailure("Insufficient hardware");
if (!this->TestsHaveSufficientResources[test]) {
testRun->StartFailure("Insufficient resources");
this->FinishTestProcess(testRun, false);
return false;
}
......@@ -218,26 +218,26 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
return false;
}
bool cmCTestMultiProcessHandler::AllocateHardware(int index)
bool cmCTestMultiProcessHandler::AllocateResources(int index)
{
if (!this->TestHandler->UseHardwareSpec) {
if (!this->TestHandler->UseResourceSpec) {
return true;
}
std::map<std::string, std::vector<cmCTestBinPackerAllocation>> allocations;
if (!this->TryAllocateHardware(index, allocations)) {
if (!this->TryAllocateResources(index, allocations)) {
return false;
}
auto& allocatedHardware = this->AllocatedHardware[index];
allocatedHardware.resize(this->Properties[index]->Processes.size());
auto& allocatedResources = this->AllocatedResources[index];
allocatedResources.resize(this->Properties[index]->ResourceGroups.size());
for (auto const& it : allocations) {
for (auto const& alloc : it.second) {
bool result = this->HardwareAllocator.AllocateResource(
bool result = this->ResourceAllocator.AllocateResource(
it.first, alloc.Id, alloc.SlotsNeeded);
(void)result;
assert(result);
allocatedHardware[alloc.ProcessIndex][it.first].push_back(
allocatedResources[alloc.ProcessIndex][it.first].push_back(
{ alloc.Id, static_cast<unsigned int>(alloc.SlotsNeeded) });
}
}
......@@ -245,14 +245,14 @@ bool cmCTestMultiProcessHandler::AllocateHardware(int index)
return true;
}
bool cmCTestMultiProcessHandler::TryAllocateHardware(
bool cmCTestMultiProcessHandler::TryAllocateResources(
int index,
std::map<std::string, std::vector<cmCTestBinPackerAllocation>>& allocations)
{
allocations.clear();
std::size_t processIndex = 0;
for (auto const& process : this->Properties[index]->Processes) {
for (auto const& process : this->Properties[index]->ResourceGroups) {
for (auto const& requirement : process) {
for (int i = 0; i < requirement.UnitsNeeded; ++i) {
allocations[requirement.ResourceType].push_back(
......@@ -262,13 +262,13 @@ bool cmCTestMultiProcessHandler::TryAllocateHardware(
++processIndex;
}
auto const& availableHardware = this->HardwareAllocator.GetResources();
auto const& availableResources = this->ResourceAllocator.GetResources();
for (auto& it : allocations) {
if (!availableHardware.count(it.first)) {
if (!availableResources.count(it.first)) {
return false;
}
if (!cmAllocateCTestHardwareRoundRobin(availableHardware.at(it.first),
it.second)) {
if (!cmAllocateCTestResourcesRoundRobin(availableResources.at(it.first),
it.second)) {
return false;
}
}
......@@ -276,19 +276,19 @@ bool cmCTestMultiProcessHandler::TryAllocateHardware(
return true;
}
void cmCTestMultiProcessHandler::DeallocateHardware(int index)
void cmCTestMultiProcessHandler::DeallocateResources(int index)
{
if (!this->TestHandler->UseHardwareSpec) {
if (!this->TestHandler->UseResourceSpec) {
return;
}
{
auto& allocatedHardware = this->AllocatedHardware[index];
for (auto const& processAlloc : allocatedHardware) {
auto& allocatedResources = this->AllocatedResources[index];
for (auto const& processAlloc : allocatedResources) {
for (auto const& it : processAlloc) {
auto resourceType = it.first;
for (auto const& it2 : it.second) {
bool success = this->HardwareAllocator.DeallocateResource(
bool success = this->ResourceAllocator.DeallocateResource(
resourceType, it2.Id, it2.Slots);
(void)success;
assert(success);
......@@ -296,12 +296,12 @@ void cmCTestMultiProcessHandler::DeallocateHardware(int index)
}
}
}
this->AllocatedHardware.erase(index);
this->AllocatedResources.erase(index);
}
bool cmCTestMultiProcessHandler::AllHardwareAvailable()
bool cmCTestMultiProcessHandler::AllResourcesAvailable()
{
for (auto const& it : this->HardwareAllocator.GetResources()) {
for (auto const& it : this->ResourceAllocator.GetResources()) {
for (auto const& it2 : it.second) {
if (it2.second.Locked != 0) {
return false;
......@@ -312,13 +312,13 @@ bool cmCTestMultiProcessHandler::AllHardwareAvailable()
return true;
}
void cmCTestMultiProcessHandler::CheckHardwareAvailable()
void cmCTestMultiProcessHandler::CheckResourcesAvailable()
{
for (auto test : this->SortedTests) {
std::map<std::string, std::vector<cmCTestBinPackerAllocation>> allocations;
this->TestsHaveSufficientHardware[test] =
!this->TestHandler->UseHardwareSpec ||
this->TryAllocateHardware(test, allocations);
this->TestsHaveSufficientResources[test] =
!this->TestHandler->UseResourceSpec ||