📄 resourcemanager.cpp
字号:
}
pfnGetLogicalProcessorInformationEx((LOGICAL_PROCESSOR_RELATIONSHIP) RelationAll, NULL, &s_logicalProcessorInformationLength);
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
}
ASSERT(s_logicalProcessorInformationLength > 0);
s_pSysInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION) malloc(s_logicalProcessorInformationLength);
if (s_pSysInfo == NULL)
{
throw std::bad_alloc();
}
if ( !pfnGetLogicalProcessorInformationEx((LOGICAL_PROCESSOR_RELATIONSHIP) RelationAll,
(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) s_pSysInfo, &s_logicalProcessorInformationLength))
{
throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
}
// Cast this buffer as a PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, which is needed for GetLogicalProcessorInformationEx
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX pSysInfoEx = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) s_pSysInfo;
DWORD byteOffset = 0;
s_packageCount = 0;
s_nodeCount = 0;
s_physicalProcessorCount = 0;
// Traverse the processor information buffer to find s_nodeCount, s_packageCount and s_physicalProcessorCount.
// It's possible for a package to contain multiple NUMA nodes. In the case were we have more NUMA nodes than
// packages, we will create one scheduling node pre NUMA node. Otherwise, we create one scheduling node per
// package
while (byteOffset < s_logicalProcessorInformationLength)
{
if (pSysInfoEx->Relationship == RelationProcessorPackage)
{
++s_packageCount;
}
if (pSysInfoEx->Relationship == RelationNumaNode)
{
++s_nodeCount;
}
if (pSysInfoEx->Relationship == RelationProcessorCore)
{
s_physicalProcessorCount += NumberOfBitsSet(pSysInfoEx->Processor.GroupMask[0].Mask);
}
byteOffset += pSysInfoEx->Size;
pSysInfoEx = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) ((PBYTE)pSysInfoEx + pSysInfoEx->Size);
}
ASSERT(s_logicalProcessorInformationLength > 0);
ASSERT(s_packageCount > 0);
ASSERT(s_nodeCount > 0);
if (!fSaveTopologyInfo)
{
free(s_pSysInfo);
s_pSysInfo = NULL;
s_logicalProcessorInformationLength = 0;
}
// Initialize function pointers to APIs that are only present on these operating systems and higher.
InitializeSystemFunctionPointers();
}
else
{
#ifdef _M_IX86
typedef BOOL (WINAPI *PFnGetLogicalProcessorInformation)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
PFnGetLogicalProcessorInformation pfnGetLogicalProcessorInformation
= (PFnGetLogicalProcessorInformation) GetProcAddress(GetModuleHandleW(L"kernel32.dll"),
"GetLogicalProcessorInformation");
if (pfnGetLogicalProcessorInformation == NULL)
{
throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
}
pfnGetLogicalProcessorInformation(NULL, &s_logicalProcessorInformationLength);
#else
GetLogicalProcessorInformation(NULL, &s_logicalProcessorInformationLength);
#endif
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
}
ASSERT(s_logicalProcessorInformationLength > 0);
s_pSysInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION) malloc(s_logicalProcessorInformationLength);
if (s_pSysInfo == NULL)
{
throw std::bad_alloc();
}
#ifdef _M_IX86
if (!pfnGetLogicalProcessorInformation(s_pSysInfo, &s_logicalProcessorInformationLength))
#else
if (!GetLogicalProcessorInformation(s_pSysInfo, &s_logicalProcessorInformationLength))
#endif
{
throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
}
// Traverse the processor information buffer to find s_nodeCount and s_packageCount.
// It's possible for a package to contain multiple NUMA nodes. In the case were we have more NUMA nodes than
// packages, we will create one scheduling node pre NUMA node. Otherwise, we create one scheduling node per
// package
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pSysInfo = s_pSysInfo;
DWORD byteOffset = 0;
s_packageCount = 0;
s_nodeCount = 0;
s_physicalProcessorCount = info.dwNumberOfProcessors;
while (byteOffset < s_logicalProcessorInformationLength)
{
if (pSysInfo->Relationship == RelationProcessorPackage)
{
++s_packageCount;
}
if (pSysInfo->Relationship == RelationNumaNode)
{
++s_nodeCount;
}
byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
++pSysInfo;
}
ASSERT(s_logicalProcessorInformationLength > 0);
ASSERT(s_packageCount > 0);
ASSERT(s_nodeCount > 0);
if (!fSaveTopologyInfo)
{
free(s_pSysInfo);
s_pSysInfo = NULL;
s_logicalProcessorInformationLength = 0;
}
}
if (s_version == ::Concurrency::IResourceManager::UmsThreadAwareOS)
{
UMS::Initialize();
}
ASSERT(s_physicalProcessorCount > 0 && s_physicalProcessorCount <= USHORT_MAX);
}
/// <summary>
/// Creates a structure of nodes and cores based on the machine topology.
/// </summary>
void ResourceManager::DetermineTopology()
{
ASSERT(m_pGlobalNodes == NULL);
ASSERT(s_nodeCount > 0 && s_nodeCount <= INT_MAX);
m_nodeCount = (s_nodeCount >= s_packageCount) ? s_nodeCount : s_packageCount;
// There is some ambiguity around the behavior of this API for OSs < Vista. Set node count to
// 1 for these OSs, as other areas of the implementation make assumptions around this.
if (s_pSysInfo == NULL)
{
ASSERT(s_version == ::Concurrency::IResourceManager::XP || s_version == ::Concurrency::IResourceManager::Win2k3);
ASSERT(m_nodeCount == 1);
m_pGlobalNodes = new GlobalNode[m_nodeCount];
memset(m_pGlobalNodes, 0, sizeof(GlobalNode));
m_pSortedNodeOrder= new unsigned int[m_nodeCount];
*m_pSortedNodeOrder = 0;
m_pGlobalNodes->m_pCores = new GlobalCore[s_physicalProcessorCount];
m_pGlobalNodes->m_coreCount = s_physicalProcessorCount;
ULONG_PTR processAffinityMask = 0;
ULONG_PTR systemAffinityMask = 0;
BOOL retVal = GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask);
ASSERT(retVal == TRUE);
m_pGlobalNodes->m_nodeAffinity = processAffinityMask;
memset(m_pGlobalNodes->m_pCores, 0, m_pGlobalNodes->m_coreCount * sizeof(GlobalCore));
m_pGlobalNodes->m_processorGroup = 0;
m_pGlobalNodes->m_pSortedCoreOrder = new unsigned int[m_pGlobalNodes->m_coreCount];
for (unsigned int i = 0; i < m_pGlobalNodes->m_coreCount; ++i)
{
m_pGlobalNodes->m_pCores[i].m_processorNumber = (BYTE) i;
m_pGlobalNodes->m_pSortedCoreOrder[i] = i;
}
}
else
{
m_pGlobalNodes = new GlobalNode[m_nodeCount];
memset(m_pGlobalNodes, 0, m_nodeCount * sizeof(GlobalNode));
m_pSortedNodeOrder = new unsigned int[m_nodeCount];
for (unsigned int i = 0; i < m_nodeCount; ++i)
{
m_pSortedNodeOrder[i] = i;
}
// Win7 or higher has a PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX structure to support > 64 cores
if (s_version == ::Concurrency::IResourceManager::Win7OrLater || s_version == ::Concurrency::IResourceManager::UmsThreadAwareOS)
{
// Traverse the processor information buffer for a second time to populate the node structures.
DWORD byteOffset = 0;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX pSysInfoEx = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) s_pSysInfo;
unsigned int index = 0;
while (byteOffset < s_logicalProcessorInformationLength)
{
switch (pSysInfoEx->Relationship)
{
case RelationProcessorCore:
break;
case RelationProcessorPackage:
{
// If this machine had more packages than NUMA nodes, we should create one scheduling node per package.
if (s_packageCount > s_nodeCount)
{
ASSERT(pSysInfoEx->Processor.GroupCount == 1);
m_pGlobalNodes[index].Initialize(index, pSysInfoEx->Processor.GroupMask[0].Group, pSysInfoEx->Processor.GroupMask[0].Mask);
++index;
}
}
break;
case RelationNumaNode:
{
// If this machine had more NUMA nodes than packages, we should create one scheduling node per NUMA node.
if (s_packageCount <= s_nodeCount)
{
m_pGlobalNodes[index].Initialize(index, pSysInfoEx->NumaNode.GroupMask.Group, pSysInfoEx->NumaNode.GroupMask.Mask);
++index;
}
}
break;
}
byteOffset += pSysInfoEx->Size;
pSysInfoEx = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) ((PBYTE)pSysInfoEx + pSysInfoEx->Size);
}
ASSERT(index == m_nodeCount);
free(s_pSysInfo);
s_pSysInfo = NULL;
s_logicalProcessorInformationLength = 0;
}
else
{
// Traverse the processor information buffer for a second time to populate the node structures.
DWORD byteOffset = 0;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pSysInfo = s_pSysInfo;
unsigned int index = 0;
while (byteOffset < s_logicalProcessorInformationLength)
{
switch (pSysInfo->Relationship)
{
case RelationProcessorCore:
break;
case RelationProcessorPackage:
{
// If this machine had more packages than NUMA nodes, we should create one scheduling node per package.
if (s_packageCount > s_nodeCount)
{
m_pGlobalNodes[index].Initialize(index, 0, pSysInfo->ProcessorMask);
++index;
}
}
break;
case RelationNumaNode:
{
// If this machine had more NUMA nodes than packages, we should create one scheduling node per NUMA node.
if (s_packageCount <= s_nodeCount)
{
m_pGlobalNodes[index].Initialize(index, 0, pSysInfo->ProcessorMask);
++index;
}
}
break;
}
byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
++pSysInfo;
}
ASSERT(index == m_nodeCount);
free(s_pSysInfo);
s_pSysInfo = NULL;
s_logicalProcessorInformationLength = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -