// Configure //-------------------------------------------------------------------------------------------------
//
// Copyright? 2001, Intel Corporation. Other brands and names may be claimed as the property of others.
//
//
// CPU counting Utility
// Date: 10/30/2001
// Version 1.4
//
//
//
// File name: cpucount. cpp
//
// Note: 1) logicalnum = number of logical processors per physical processor. If you want to count
// The total number of logical processors, multiply this number with the total number
// Physical processors (physicalnum)
//
// 2) to detect whether hyper-threading is enabled or not is to see how your logical ID exist
// Per single physical ID in APIC
//
// 3) for systems that don't support hyper-threading like AMD or piII and below. The variable
// Logicalnum will be set to 1 (which means number of logical processors equals to number
// Physical processors .)
//
// 4) hyper-threading cannot be detected when application cannot access all processors in
// The system. The number of physical processors will be set to 255. Make sure to enable all
// Physical processors at startup of windows, and applications calling this function, cpucount,
// Are not restricted to run on any participant logical or physical processors (can run on all
// Processors .)
//
// 5) Windows currently can handle up to 32 processors.
//
//
// Configure //-------------------------------------------------------------------------------------------------
# Define ht_bit 0x10000000 // edX [28] bit 28 is set if HT is supported
# Define family_id 0x0f00 // eax [11: 8] bit 8-11 contains family processor ID.
# Define pentium4_id 0x0f00
# Define ext_family_id 0x0f00000 // eax [23:20] bit 20-23 contains extended family processor ID
# Define num_logical_bits 0x00ff0000 // EBX [23:16] bit 16-23 in EBX contains the number of logical
// Processors per physical processor when execute cpuid
// Eax set to 1
# define initial_apic_id_bits 0xff000000 // EBX [31: 24] bits 24-31 (8 bits) return the 8-bit unique
// initial apic id for the processor this code is running on.
// default value = 0xff if HT is not supported
// Status flag
# Define ht_not_capable 0
# Define ht_enabled 1
# Define ht_disabled 2
# Define ht_supported_not_enabled 3
# Define ht_cannot_detect 4
Unsigned int htsupported (void );
Unsigned char logicalprocperphysicalproc (void );
Unsigned char getapic_id (void );
Unsigned char cpucount (unsigned char *,
Unsigned char *);
# Include <windows. h>
# Include <stdio. h>
Void main (void)
{
Unsigned char logicalnum = 0, // Number of logical CPU per one physical CPU
Physicalnum = 0, // total number of physical Processor
Htstatusflag = 0;
Printf ("CPU counting utility \ n ");
Printf ("version 1.4 \ n ");
Printf ("Copyright (c) 2001 Intel Corporation. All Rights Reserved \ n ");
Htstatusflag = cpucount (& logicalnum, & physicalnum );
Switch (htstatusflag)
{
Case ht_not_capable:
Printf ("hyper-Threading Technology not capable \ n ");
Break;
Case ht_disabled:
Printf ("hyper-Threading Technology disabled \ n ");
Break;
Case ht_enabled:
Printf ("hyper-Threading Technology Enabled \ n ");
Break;
Case ht_supported_not_enabled:
Printf ("hyper-Threading Technology capable but not enabled \ n ");
Break;
Case ht_cannot_detect:
Printf ("hyper-Threading Technology cannot be detected \ n ");
Break;
}
Printf ("Number of logical processors per physical processor: % d \ n", logicalnum );
If (physicalnum! = (Unsigned char)-1)
Printf ("number of physical processors: % d \ n", physicalnum );
Else
{
Printf ("can't determine number of physical processors \ n ");
Printf ("make sure to enable all processors \ n ");
}
Printf ("\ n \ npress enter to continue \ n ");
Getchar ();
}
Unsigned int htsupported (void)
{
Unsigned int regedx = 0,
Regeax = 0,
Vendorid [3] = {0, 0, 0 };
_ Try // verify cpuid instruction is supported
{
_ ASM
{
XOR eax, eax // call cpuid with eax = 0
Cpuid // get vendor ID string
MoV vendorid, EBX
MoV vendorid + 4, EDX
MoV vendorid + 8, ECx
MoV eax, 1 // call cpuid with eax = 1
Cpuid
MoV regeax, eax // eax contains family Processor type
MoV regedx, EDX // edX has info about the availability of hyper-threading
}
}
_ Handler T (exception_execute_handler)
{
Return (0); // cpuid is unavailable
}
If (regeax & family_id) = pentium4_id) |
(Regeax & ext_family_id ))
If (vendorid [0] = 'uneg ')
If (vendorid [1] = 'ieni ')
If (vendorid [2] = 'letn ')
Return (regedx & ht_bit); // genuine intel with hyper-Threading Technology
Return 0; // not genuine intel processor
}
Unsigned char logicalprocperphysicalproc (void)
{
Unsigned int regebx = 0;
If (! Htsupported () Return (unsigned char) 1; // HT not supported
// Logical processor = 1
_ ASM
{
MoV eax, 1
Cpuid
MoV regebx, EBX
}
Return (unsigned char) (regebx & num_logical_bits)> 16 );
}
Unsigned char getapic_id (void)
{
Unsigned int regebx = 0;
If (! Htsupported () Return (unsigned char)-1; // HT not supported
// Logical processor = 1
_ ASM
{
MoV eax, 1
Cpuid
MoV regebx, EBX
}
Return (unsigned char) (regebx & initial_apic_id_bits)> 24 );
}
Unsigned char cpucount (unsigned char * logicalnum,
Unsigned char * physicalnum)
{
Unsigned char statusflag = 0;
System_info Info;
* Physicalnum = 0;
* Logicalnum = 0;
Info. dwnumberofprocessors = 0;
Getsysteminfo (& info );
// Number of physical processors in a non-Intel System
// Or in a 32-bit Intel System with hyper-Threading Technology disabled
* Physicalnum = (unsigned char) info. dwnumberofprocessors;
If (htsupported ())
{
Unsigned char ht_enabled = 0;
* Logicalnum = logicalprocperphysicalproc ();
If (* logicalnum> = 1) //> 1 doesn't mean HT is enabled in the BIOS
//
{
Handle hcurrentprocesshandle;
DWORD dwprocessaffinity;
DWORD dwsystemaffinity;
DWORD dwaffinitymask;
// Calculate the appropriate shifts and mask based on
// Number of logical processors.
Unsigned char I = 1,
Phy_id_mask = 0xff,
Phy_id_shift = 0;
While (I <* logicalnum)
{
I * = 2;
Phy_id_mask <= 1;
Phy_id_shift ++;
}
Hcurrentprocesshandle = getcurrentprocess ();
Getprocessaffinitymask (hcurrentprocesshandle, & dwprocessaffinity,
& Dwsystemaffinity );
// Check if available process affinity mask is equal to
// Available system affinity mask
If (dwprocessaffinity! = Dwsystemaffinity)
{
Statusflag = ht_cannot_detect;
* Physicalnum = (unsigned char)-1;
Return statusflag;
}
Dwaffinitymask = 1;
While (dwaffinitymask! = 0 & dwaffinitymask <= dwprocessaffinity)
{
// Check if this CPU is available
If (dwaffinitymask & dwprocessaffinity)
{
If (setprocessaffinitymask (hcurrentprocesshandle,
Dwaffinitymask ))
{
Unsigned char apic_id,
Log_id,
Phy_id;
Sleep (0); // give OS time to switch CPU
Apic_id = getapic_id ();
Log_id = apic_id &~ Phy_id_mask;
Phy_id = apic_id> phy_id_shift;
If (log_id! = 0) ht_enabled = 1;
}
}
Dwaffinitymask = dwaffinitymask <1;
}
// Reset the processor affinity
Setprocessaffinitymask (hcurrentprocesshandle, dwprocessaffinity );
If (* logicalnum = 1) // normal P4: HT is disabled in hardware
Statusflag = ht_disabled;
Else
If (ht_enabled)
{
// Total physical processors in a hyper-threading enabled system.
* Physicalnum/= (* logicalnum );
Statusflag = ht_enabled;
}
Else statusflag = ht_supported_not_enabled;
}
}
Else
{
// Processors do not have hyper-Threading Technology
Statusflag = ht_not_capable;
* Logicalnum = 1;
}
Return statusflag;
}