winPlatformCPUCount.cpp 3.8 KB

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