diff --git a/configure.ac b/configure.ac index fd3b86a..7859991 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([libcpuid CPU Identification library], [0.1.1], [libcpuid-devel@lists.sourceforge.net], [libcpuid]) +AC_INIT([libcpuid CPU Identification library], [0.1.3], [libcpuid-devel@lists.sourceforge.net], [libcpuid]) AC_CONFIG_SRCDIR([libcpuid/libcpuid.h]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([-Wall dist-bzip2 dist-zip foreign]) @@ -12,9 +12,11 @@ dnl When you make a change that adds features, increment AGE, and set REVISION t dnl C:A:R dnl 10:0:0 Version 0.1.0 dnl 11:0:0 Version 0.1.1: four more fields to cpu_raw_data_t +dnl 11:0:1 Version 0.1.2: added cpu_msr* functions +dnl 11:0:2 Version 0.1.3: added cpu_clock_by_ic() function LIBCPUID_CURRENT=11 LIBCPUID_AGE=0 -LIBCPUID_REVISION=0 +LIBCPUID_REVISION=2 AC_SUBST([LIBCPUID_AGE]) AC_SUBST([LIBCPUID_REVISION]) AC_SUBST([LIBCPUID_CURRENT]) diff --git a/cpuid_tool/cpuid_tool.c b/cpuid_tool/cpuid_tool.c index 16c51e6..0af0425 100644 --- a/cpuid_tool/cpuid_tool.c +++ b/cpuid_tool/cpuid_tool.c @@ -83,6 +83,7 @@ typedef enum { NEED_CLOCK, NEED_CLOCK_OS, NEED_CLOCK_RDTSC, + NEED_CLOCK_IC, NEED_RDMSR, } output_data_switch; @@ -133,6 +134,7 @@ matchtable[] = { { NEED_CLOCK , "--clock" , 0}, { NEED_CLOCK_OS , "--clock-os" , 0}, { NEED_CLOCK_RDTSC , "--clock-rdtsc" , 1}, + { NEED_CLOCK_IC , "--clock-ic" , 1}, { NEED_RDMSR , "--rdmsr" , 0}, }; @@ -404,6 +406,9 @@ static void print_info(output_data_switch query, struct cpu_raw_data_t* raw, case NEED_CLOCK_RDTSC: fprintf(fout, "%d\n", cpu_clock_measure(400, 1)); break; + case NEED_CLOCK_IC: + fprintf(fout, "%d\n", cpu_clock_by_ic(25, 16)); + break; case NEED_RDMSR: { if ((handle = cpu_msr_driver_open()) == NULL) { diff --git a/libcpuid/Makefile.am b/libcpuid/Makefile.am index df0b7f9..38e8926 100644 --- a/libcpuid/Makefile.am +++ b/libcpuid/Makefile.am @@ -28,6 +28,7 @@ noinst_HEADERS = \ asm-bits.h \ libcpuid_util.h \ recog_intel.h \ - recog_amd.h + recog_amd.h \ + rdtsc.h EXTRA_DIST += libcpuid.sym libcpuid.vcproj diff --git a/libcpuid/Makefile.x64 b/libcpuid/Makefile.x64 index 1c64660..80bb7e4 100644 --- a/libcpuid/Makefile.x64 +++ b/libcpuid/Makefile.x64 @@ -5,7 +5,7 @@ all: libcpuid.lib ASM = ml64 /nologo CC = cl.exe /nologo /TC OPTFLAGS = /MT -DEFINES = /D "VERSION=\"0.1.1\"" +DEFINES = /D "VERSION=\"0.1.3\"" OBJECTS = masm-x64.obj asm-bits.obj cpuid_main.obj libcpuid_util.obj recog_amd.obj recog_intel.obj rdtsc.obj libcpuid.lib: $(OBJECTS) diff --git a/libcpuid/Makefile.x86 b/libcpuid/Makefile.x86 index 6385d0e..1f3e0cf 100644 --- a/libcpuid/Makefile.x86 +++ b/libcpuid/Makefile.x86 @@ -12,7 +12,7 @@ all: libcpuid.lib CC = cl.exe /nologo /TC OPTFLAGS = /MT -DEFINES = /D "VERSION=\"0.1.1\"" +DEFINES = /D "VERSION=\"0.1.3\"" OBJECTS = asm-bits.obj cpuid_main.obj libcpuid_util.obj recog_amd.obj recog_intel.obj rdtsc.obj libcpuid.lib: $(OBJECTS) diff --git a/libcpuid/asm-bits.c b/libcpuid/asm-bits.c index b22d1e0..8dcab26 100644 --- a/libcpuid/asm-bits.c +++ b/libcpuid/asm-bits.c @@ -197,3 +197,316 @@ void cpu_rdtsc(uint64_t* result) *result = (uint64_t)low_part + (((uint64_t) hi_part) << 32); } #endif /* INLINE_ASM_SUPPORTED */ + +#ifdef INLINE_ASM_SUPPORTED +void busy_sse_loop(int cycles) +{ +#ifdef COMPILER_GCC +#ifndef __APPLE__ +# define XALIGN ".balign 16\n" +#else +# define XALIGN ".align 4\n" +#endif + __asm __volatile ( + " xorps %%xmm0, %%xmm0\n" + " xorps %%xmm1, %%xmm1\n" + " xorps %%xmm2, %%xmm2\n" + " xorps %%xmm3, %%xmm3\n" + " xorps %%xmm4, %%xmm4\n" + " xorps %%xmm5, %%xmm5\n" + " xorps %%xmm6, %%xmm6\n" + " xorps %%xmm7, %%xmm7\n" + XALIGN + ".bsLoop:\n" + // 0: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 2: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 3: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 4: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 5: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 6: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 7: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 8: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + // 9: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //10: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //11: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //12: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //13: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //14: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //15: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //16: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //17: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //18: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //19: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //20: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //21: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //22: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //23: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //24: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //25: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //26: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //27: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //28: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //29: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //30: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + //31: + " addps %%xmm1, %%xmm0\n" + " addps %%xmm2, %%xmm1\n" + " addps %%xmm3, %%xmm2\n" + " addps %%xmm4, %%xmm3\n" + " addps %%xmm5, %%xmm4\n" + " addps %%xmm6, %%xmm5\n" + " addps %%xmm7, %%xmm6\n" + " addps %%xmm0, %%xmm7\n" + + " dec %%eax\n" + " jnz .bsLoop\n" + ::"eax"(cycles) + ); +#else +# ifdef COMPILER_MICROSOFT +# else +# error "Unsupported compiler" +# endif /* COMPILER_MICROSOFT */ +#endif /* COMPILER_GCC */ +} +#endif /* INLINE_ASSEMBLY_SUPPORTED */ \ No newline at end of file diff --git a/libcpuid/asm-bits.h b/libcpuid/asm-bits.h index be2b30c..c04a0b0 100644 --- a/libcpuid/asm-bits.h +++ b/libcpuid/asm-bits.h @@ -48,5 +48,6 @@ int cpuid_exists_by_eflags(void); void exec_cpuid(uint32_t *regs); +void busy_sse_loop(int cycles); #endif /* __ASM_BITS_H__ */ diff --git a/libcpuid/exports.def b/libcpuid/exports.def index 5739cbd..b2200ea 100644 --- a/libcpuid/exports.def +++ b/libcpuid/exports.def @@ -1,24 +1,29 @@ LIBRARY LIBCPUID EXPORTS -cpuid_present @1 -cpu_exec_cpuid @2 -cpu_exec_cpuid_ext @3 -cpuid_get_raw_data @4 -cpuid_serialize_raw_data @5 -cpuid_deserialize_raw_data @6 -cpu_identify @7 -cpu_feature_str @8 -cpuid_error @9 -cpu_rdtsc @10 -cpu_tsc_mark @11 -cpu_tsc_unmark @12 -cpu_clock_by_mark @13 -cpu_clock_by_os @14 -cpu_clock_measure @15 -cpu_clock @16 -cpuid_lib_version @17 -cpuid_set_warn_function @18 -cpuid_set_verbosiness_level @19 -cpuid_get_cpu_list @20 -cpuid_free_cpu_list @21 +cpuid_present @1 +cpu_exec_cpuid @2 +cpu_exec_cpuid_ext @3 +cpuid_get_raw_data @4 +cpuid_serialize_raw_data @5 +cpuid_deserialize_raw_data @6 +cpu_identify @7 +cpu_feature_str @8 +cpuid_error @9 +cpu_rdtsc @10 +cpu_tsc_mark @11 +cpu_tsc_unmark @12 +cpu_clock_by_mark @13 +cpu_clock_by_os @14 +cpu_clock_measure @15 +cpu_clock @16 +cpuid_lib_version @17 +cpuid_set_warn_function @18 +cpuid_set_verbosiness_level @19 +cpuid_get_cpu_list @20 +cpuid_free_cpu_list @21 +cpu_msr_driver_open @22 +cpu_rdmsr @23 +cpu_msrinfo @24 +cpu_msr_driver_close @25 +cpu_clock_by_ic @26 diff --git a/libcpuid/libcpuid.h b/libcpuid/libcpuid.h index 0791bc3..b8ec82c 100644 --- a/libcpuid/libcpuid.h +++ b/libcpuid/libcpuid.h @@ -29,7 +29,7 @@ * @File libcpuid.h * @Author Veselin Georgiev * @Date Oct 2008 - * @Version 0.1.2 + * @Version 0.1.3 * * Version history: * @@ -38,6 +38,8 @@ * new processor topology enumeration required on Core i7 * 0.1.2 (2009-09-26): Added support for MSR reading through self-extracting * kernel driver on Win32. + * 0.1.3 (2010-04-20): Added support for greater more accurate CPU clock measurements + * with cpu_clock_by_ic() */ /** @mainpage A simple libcpuid introduction @@ -615,6 +617,38 @@ int cpu_clock_by_os(void); */ int cpu_clock_measure(int millis, int quad_check); +/** + * @brief Measure the CPU clock frequency using instruction-counting + * + * @param millis - how much time to allocate for each run, in milliseconds + * @param runs - how many runs to perform + * + * The function performs a busy-wait cycle using a known number of "heavy" (SSE) + * instructions. These instructions run at (more or less guaranteed) 1 IPC rate, + * so by running a busy loop for a fixed amount of time, and measuring the + * amount of instructions done, the CPU clock is accurately measured. + * + * Of course, this function is still affected by the power-saving schemes, so + * the warnings as of cpu_clock_measure() still apply. However, this function is + * immune to problems with detection, related to the Intel Nehalem's "Turbo" + * mode, where the internal clock is raised, but the RDTSC rate is unaffected. + * + * The function will run for about (millis * runs) milliseconds. + * You can make only a single busy-wait run (runs == 1); however, this can + * be affected by task scheduling (which will break the counting), so allowing + * more than one run is recommended. As run length is not imperative for + * accurate readings (e.g., 50ms is sufficient), you can afford a lot of short + * runs, e.g. 10 runs of 50ms or 20 runs of 25ms. + * + * Recommended values - millis = 50, runs = 4. For more robustness, + * increase the number of runs. + * + * @returns the CPU clock frequency in MHz (within some measurement error + * margin). If SSE is not supported, the result is -1. If the input parameters + * are incorrect, or some other internal fault is detected, the result is -2. + */ +int cpu_clock_by_ic(int millis, int runs); + /** * @brief Get the CPU clock frequency (all-in-one method) * diff --git a/libcpuid/libcpuid.sym b/libcpuid/libcpuid.sym index 7375ba4..8356c72 100644 --- a/libcpuid/libcpuid.sym +++ b/libcpuid/libcpuid.sym @@ -23,3 +23,4 @@ cpu_msr_driver_open cpu_rdmsr cpu_msrinfo cpu_msr_driver_close +cpu_clock_by_ic diff --git a/libcpuid/libcpuid_vc71.vcproj b/libcpuid/libcpuid_vc71.vcproj index 543ad72..d7e8a32 100644 --- a/libcpuid/libcpuid_vc71.vcproj +++ b/libcpuid/libcpuid_vc71.vcproj @@ -19,7 +19,7 @@ + + + + #include #include "libcpuid.h" +#include "libcpuid_util.h" +#include "asm-bits.h" +#include "rdtsc.h" #ifdef _WIN32 #include @@ -223,6 +226,45 @@ int cpu_clock_measure(int millis, int quad_check) return (results[bi] + results[bj] + _zero) / 2; } +int cpu_clock_by_ic(int millis, int runs) +{ + int max_value = 0, cur_value, i, ri, cycles_inner, cycles_outer, c; + struct cpu_id_t* id; + uint64_t t0, t1, tl, hz; + if (millis <= 0 || runs <= 0) return -2; + id = get_cached_cpuid(); + if (!id || !id->flags[CPU_FEATURE_SSE]) return -1; + // + tl = millis * 125; // (*1000 / 8) + cycles_inner = 128; + cycles_outer = 1; + do { + if (cycles_inner < 1000000000) cycles_inner *= 2; + else cycles_outer *= 2; + sys_precise_clock(&t0); + for (i = 0; i < cycles_outer; i++) + busy_sse_loop(cycles_inner); + sys_precise_clock(&t1); + } while (t1 - t0 < tl); + debugf(2, "inner: %d, outer: %d\n", cycles_inner, cycles_outer); + for (ri = 0; ri < runs; ri++) { + sys_precise_clock(&t0); + c = 0; + do { + c++; + for (i = 0; i < cycles_outer; i++) + busy_sse_loop(cycles_inner); + sys_precise_clock(&t1); + } while (t1 - t0 < tl * (uint64_t) 8); + // cpu_Hz = cycles_inner * cycles_outer * 256 / (t1 - t0) * 1000000 + debugf(2, "c = %d, td = %llu\n", c, t1 - t0); + hz = (uint64_t) cycles_inner * (uint64_t) cycles_outer * (uint64_t) c * (uint64_t) 256000000 / (t1 - t0); + cur_value = (int) (hz / 1000000); + if (cur_value > max_value) max_value = cur_value; + } + return max_value; +} + int cpu_clock(void) { int result;