2014-09-14 19:39:56 +00:00
|
|
|
// Original code is:
|
2024-03-14 15:14:01 +00:00
|
|
|
// Copyright (c) 2005 Intel Corporation
|
2014-09-14 19:39:56 +00:00
|
|
|
// All Rights Reserved
|
|
|
|
|
//
|
|
|
|
|
// CPUCount.cpp : Detects three forms of hardware multi-threading support across IA-32 platform
|
2024-03-14 15:14:01 +00:00
|
|
|
// The three forms of HW multithreading are: Multi-processor, Multi-core, and
|
2014-09-14 19:39:56 +00:00
|
|
|
// HyperThreading Technology.
|
|
|
|
|
// This application enumerates all the logical processors enabled by OS and BIOS,
|
2024-03-14 15:14:01 +00:00
|
|
|
// determine the HW topology of these enabled logical processors in the system
|
2014-09-14 19:39:56 +00:00
|
|
|
// using information provided by CPUID instruction.
|
|
|
|
|
// A multi-processing system can support any combination of the three forms of HW
|
2024-03-14 15:14:01 +00:00
|
|
|
// multi-threading support. The relevant topology can be identified using a
|
|
|
|
|
// three level decomposition of the "initial APIC ID" into
|
|
|
|
|
// Package_id, core_id, and SMT_id. Such decomposition provides a three-level map of
|
2014-09-14 19:39:56 +00:00
|
|
|
// the topology of hardware resources and
|
2024-03-14 15:14:01 +00:00
|
|
|
// allow multi-threaded software to manage shared hardware resources in
|
2014-09-14 19:39:56 +00:00
|
|
|
// the platform to reduce resource contention
|
|
|
|
|
|
|
|
|
|
// Multicore detection algorithm for processor and cache topology requires
|
|
|
|
|
// all leaf functions of CPUID instructions be available. System administrator
|
|
|
|
|
// must ensure BIOS settings is not configured to restrict CPUID functionalities.
|
|
|
|
|
//-------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#include "platform/platform.h"
|
|
|
|
|
|
|
|
|
|
#if defined( TORQUE_OS_WIN )
|
|
|
|
|
|
|
|
|
|
#include "platform/platformCPUCount.h"
|
2021-09-27 03:43:06 +00:00
|
|
|
#include "console/console.h"
|
2014-09-14 19:39:56 +00:00
|
|
|
#include <windows.h>
|
|
|
|
|
#include <intrin.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
namespace CPUInfo {
|
|
|
|
|
|
|
|
|
|
// based on http://msdn.microsoft.com/en-us/library/ms683194.aspx
|
|
|
|
|
|
|
|
|
|
// Helper function to count set bits in the processor mask.
|
|
|
|
|
DWORD CountSetBits( ULONG_PTR bitMask )
|
|
|
|
|
{
|
|
|
|
|
DWORD LSHIFT = sizeof( ULONG_PTR ) * 8 - 1;
|
|
|
|
|
DWORD bitSetCount = 0;
|
|
|
|
|
ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;
|
|
|
|
|
DWORD i;
|
|
|
|
|
|
|
|
|
|
for( i = 0; i <= LSHIFT; ++i )
|
|
|
|
|
{
|
|
|
|
|
bitSetCount += ((bitMask & bitTest) ? 1 : 0);
|
|
|
|
|
bitTest /= 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bitSetCount;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-27 03:43:06 +00:00
|
|
|
EConfig CPUCount( U32& TotAvailLogical, U32& TotAvailCore )
|
2014-09-14 19:39:56 +00:00
|
|
|
{
|
|
|
|
|
TotAvailLogical = 0;
|
|
|
|
|
TotAvailCore = 0;
|
|
|
|
|
|
|
|
|
|
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
|
|
|
|
|
DWORD returnLength = 0;
|
2024-03-14 15:14:01 +00:00
|
|
|
|
2014-09-14 19:39:56 +00:00
|
|
|
// get buffer length
|
|
|
|
|
DWORD rc = GetLogicalProcessorInformation( buffer, &returnLength );
|
|
|
|
|
buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc( returnLength );
|
|
|
|
|
|
2024-03-14 15:14:01 +00:00
|
|
|
rc = GetLogicalProcessorInformation( buffer, &returnLength );
|
2014-09-14 19:39:56 +00:00
|
|
|
|
2021-09-27 03:43:06 +00:00
|
|
|
// if we fail, assume single threaded
|
2014-09-14 19:39:56 +00:00
|
|
|
if( FALSE == rc )
|
2024-03-14 15:14:01 +00:00
|
|
|
{
|
2014-09-14 19:39:56 +00:00
|
|
|
free( buffer );
|
2021-09-27 03:43:06 +00:00
|
|
|
Con::errorf("Unable to determine CPU Count, assuming 1 core");
|
|
|
|
|
TotAvailCore = 1;
|
|
|
|
|
TotAvailLogical = 1;
|
|
|
|
|
return CONFIG_SingleCoreAndHTNotCapable;
|
2024-03-14 15:14:01 +00:00
|
|
|
}
|
2014-09-14 19:39:56 +00:00
|
|
|
|
2024-03-14 15:14:01 +00:00
|
|
|
#pragma warning( push )
|
|
|
|
|
#pragma warning( disable: 6011 )
|
2014-09-14 19:39:56 +00:00
|
|
|
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer;
|
|
|
|
|
|
|
|
|
|
DWORD byteOffset = 0;
|
|
|
|
|
while( byteOffset + sizeof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION ) <= returnLength )
|
|
|
|
|
{
|
2021-09-27 03:43:06 +00:00
|
|
|
if (ptr->Relationship == RelationProcessorCore)
|
|
|
|
|
{
|
2014-09-14 19:39:56 +00:00
|
|
|
TotAvailCore++;
|
2021-09-27 03:43:06 +00:00
|
|
|
TotAvailLogical += CountSetBits(ptr->ProcessorMask);
|
2014-09-14 19:39:56 +00:00
|
|
|
}
|
2021-09-27 03:43:06 +00:00
|
|
|
|
2014-09-14 19:39:56 +00:00
|
|
|
byteOffset += sizeof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION );
|
|
|
|
|
ptr++;
|
2021-09-27 03:43:06 +00:00
|
|
|
}
|
2014-09-14 19:39:56 +00:00
|
|
|
|
|
|
|
|
free( buffer );
|
2024-03-14 15:14:01 +00:00
|
|
|
#pragma warning( pop )
|
2014-09-14 19:39:56 +00:00
|
|
|
|
2021-09-27 03:43:06 +00:00
|
|
|
EConfig StatusFlag = CONFIG_SingleCoreAndHTNotCapable;
|
2014-09-14 19:39:56 +00:00
|
|
|
|
|
|
|
|
if( TotAvailCore == 1 && TotAvailLogical > TotAvailCore )
|
|
|
|
|
StatusFlag = CONFIG_SingleCoreHTEnabled;
|
|
|
|
|
else if( TotAvailCore > 1 && TotAvailLogical == TotAvailCore )
|
|
|
|
|
StatusFlag = CONFIG_MultiCoreAndHTNotCapable;
|
|
|
|
|
else if( TotAvailCore > 1 && TotAvailLogical > TotAvailCore )
|
|
|
|
|
StatusFlag = CONFIG_MultiCoreAndHTEnabled;
|
|
|
|
|
|
|
|
|
|
return StatusFlag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace CPUInfo
|
|
|
|
|
#endif
|