From d633fd201dfa3c3e7d3581e70e7492dc34063f67 Mon Sep 17 00:00:00 2001 From: janwas Date: Tue, 22 Jun 2004 17:20:38 +0000 Subject: [PATCH] add code to check if system is SMP (needed for wtime; not trivial, since hyperthreading may be in play) This was SVN commit r588. --- source/lib/cpu.h | 7 +++++++ source/lib/sysdep/ia32.cpp | 36 +++++++++++++++++++++++++++------ source/lib/sysdep/win/wcpu.cpp | 10 +++++++-- source/lib/sysdep/win/wtime.cpp | 2 +- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/source/lib/cpu.h b/source/lib/cpu.h index fc274746ea..f778433fca 100755 --- a/source/lib/cpu.h +++ b/source/lib/cpu.h @@ -13,6 +13,13 @@ extern int cpu_smp; // are there actually multiple physical processors, // not only logical hyperthreaded CPUs? relevant for wtime. + +// set cpu_smp if there's more than 1 physical CPU - +// need to know this for wtime's TSC safety check. +// call on each processor (via on_each_cpu). +extern void cpu_check_smp(); + + #ifdef __cplusplus } #endif diff --git a/source/lib/sysdep/ia32.cpp b/source/lib/sysdep/ia32.cpp index d14f4c5690..05c96b9e95 100755 --- a/source/lib/sysdep/ia32.cpp +++ b/source/lib/sysdep/ia32.cpp @@ -399,20 +399,36 @@ int get_cur_processor_id() } -static void check_hyperthread() +// set cpu_smp if there's more than 1 physical CPU - +// need to know this for wtime's TSC safety check. +// call on each processor (via on_each_cpu). +void cpu_check_smp() { assert(cpus > 0 && "must know # CPUs (call OS-specific detect first)"); - cpu_smp = 0; - // we don't check if it's Intel and P4 or above - HT may be supported // on other CPUs in future. haven't come across a processor that // incorrectly sets the HT feature bit. - if(!ia32_cap(HT)) + { + // no HT supported, just check number of CPUs as reported by OS. + cpu_smp = (cpus > 1); return; + } + + // first call. we set cpu_smp below if more than 1 physical CPU is found, + // so clear it until then. + if(cpu_smp == -1) + cpu_smp = 0; + + + // + // still need to check if HT is actually enabled (BIOS and OS); + // there might be 2 CPUs with HT supported but disabled. + // // get number of logical CPUs per package + // (the same for all packages on this system) int log_cpus_per_package; __asm { push 1 @@ -423,7 +439,16 @@ static void check_hyperthread() mov log_cpus_per_package, ebx ; ebx[23:16] } - cpu_smp = 1; + // logical CPUs are initialized after one another => + // they have the same physical ID. + const int id = get_cur_processor_id(); + const int phys_shift = log2(log_cpus_per_package); + const int phys_id = id >> phys_shift; + + // more than 1 physical CPU found + static int last_phys_id = -1; + if(last_phys_id != phys_id) + cpu_smp = 1; } @@ -448,7 +473,6 @@ void ia32_get_cpu_info() get_cpu_type(); measure_cpu_freq(); - check_hyperthread(); check_speedstep(); } diff --git a/source/lib/sysdep/win/wcpu.cpp b/source/lib/sysdep/win/wcpu.cpp index 4529b30b44..daafb87471 100755 --- a/source/lib/sysdep/win/wcpu.cpp +++ b/source/lib/sysdep/win/wcpu.cpp @@ -6,9 +6,8 @@ #include "cpu.h" -// helper routine, called by ia32.cpp check_hyperthread // not possible with POSIX calls. -int on_each_cpu(void(*cb)()) +static int on_each_cpu(void(*cb)()) { const HANDLE hProcess = GetCurrentProcess(); @@ -46,6 +45,12 @@ int on_each_cpu(void(*cb)()) } +static void check_smp() +{ + on_each_cpu(cpu_check_smp); +} + + static void check_speedstep() { // CallNtPowerInformation @@ -130,6 +135,7 @@ int win_get_cpu_info() } check_speedstep(); + check_smp(); return 0; } diff --git a/source/lib/sysdep/win/wtime.cpp b/source/lib/sysdep/win/wtime.cpp index 0f963fb13a..482534f0ef 100755 --- a/source/lib/sysdep/win/wtime.cpp +++ b/source/lib/sysdep/win/wtime.cpp @@ -144,7 +144,7 @@ static int choose_impl() // => unsafe. if(ia32_cap(TSC) && cpu_freq > 0.0) { - safe = (cpus == 1 && !cpu_speedstep); + safe = (cpu_smp == 0 && cpu_speedstep == 0); SAFETY_OVERRIDE(HRT_TSC); if(safe) {