winPlatformCPUCount.cpp
Engine/source/platformWin32/winPlatformCPUCount.cpp
Detailed Description
1 2// Original code is: 3// Copyright (c) 2005 Intel Corporation 4// All Rights Reserved 5// 6// CPUCount.cpp : Detects three forms of hardware multi-threading support across IA-32 platform 7// The three forms of HW multithreading are: Multi-processor, Multi-core, and 8// HyperThreading Technology. 9// This application enumerates all the logical processors enabled by OS and BIOS, 10// determine the HW topology of these enabled logical processors in the system 11// using information provided by CPUID instruction. 12// A multi-processing system can support any combination of the three forms of HW 13// multi-threading support. The relevant topology can be identified using a 14// three level decomposition of the "initial APIC ID" into 15// Package_id, core_id, and SMT_id. Such decomposition provides a three-level map of 16// the topology of hardware resources and 17// allow multi-threaded software to manage shared hardware resources in 18// the platform to reduce resource contention 19 20// Multicore detection algorithm for processor and cache topology requires 21// all leaf functions of CPUID instructions be available. System administrator 22// must ensure BIOS settings is not configured to restrict CPUID functionalities. 23//------------------------------------------------------------------------------------------------- 24 25#include "platform/platform.h" 26 27#if defined( TORQUE_OS_WIN ) 28 29#include "platform/platformCPUCount.h" 30#include <windows.h> 31#include <intrin.h> 32#include <stdio.h> 33#include <assert.h> 34 35namespace CPUInfo { 36 37 // based on http://msdn.microsoft.com/en-us/library/ms683194.aspx 38 39 // Helper function to count set bits in the processor mask. 40 DWORD CountSetBits( ULONG_PTR bitMask ) 41 { 42 DWORD LSHIFT = sizeof( ULONG_PTR ) * 8 - 1; 43 DWORD bitSetCount = 0; 44 ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT; 45 DWORD i; 46 47 for( i = 0; i <= LSHIFT; ++i ) 48 { 49 bitSetCount += ((bitMask & bitTest) ? 1 : 0); 50 bitTest /= 2; 51 } 52 53 return bitSetCount; 54 } 55 56 EConfig CPUCount( U32& TotAvailLogical, U32& TotAvailCore, U32& PhysicalNum ) 57 { 58 EConfig StatusFlag = CONFIG_UserConfigIssue; 59 TotAvailLogical = 0; 60 TotAvailCore = 0; 61 PhysicalNum = 0; 62 63 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; 64 DWORD returnLength = 0; 65 66 // get buffer length 67 DWORD rc = GetLogicalProcessorInformation( buffer, &returnLength ); 68 buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc( returnLength ); 69 70 rc = GetLogicalProcessorInformation( buffer, &returnLength ); 71 72 if( FALSE == rc ) 73 { 74 free( buffer ); 75 return StatusFlag; 76 } 77 78 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer; 79 80 DWORD byteOffset = 0; 81 while( byteOffset + sizeof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION ) <= returnLength ) 82 { 83 switch( ptr->Relationship ) 84 { 85 86 case RelationProcessorCore: 87 TotAvailCore++; 88 89 // A hyperthreaded core supplies more than one logical processor. 90 TotAvailLogical += CountSetBits( ptr->ProcessorMask ); 91 break; 92 93 case RelationProcessorPackage: 94 // Logical processors share a physical package. 95 PhysicalNum++; 96 break; 97 98 default: 99 break; 100 } 101 byteOffset += sizeof( SYSTEM_LOGICAL_PROCESSOR_INFORMATION ); 102 ptr++; 103 } 104 105 free( buffer ); 106 107 StatusFlag = CONFIG_SingleCoreAndHTNotCapable; 108 109 if( TotAvailCore == 1 && TotAvailLogical > TotAvailCore ) 110 StatusFlag = CONFIG_SingleCoreHTEnabled; 111 else if( TotAvailCore > 1 && TotAvailLogical == TotAvailCore ) 112 StatusFlag = CONFIG_MultiCoreAndHTNotCapable; 113 else if( TotAvailCore > 1 && TotAvailLogical > TotAvailCore ) 114 StatusFlag = CONFIG_MultiCoreAndHTEnabled; 115 116 return StatusFlag; 117 } 118 119} // namespace CPUInfo 120#endif 121