From 519f9845783bcbdbaace8d3d7f98e203d26bc411 Mon Sep 17 00:00:00 2001 From: Veselin Georgiev Date: Mon, 5 Oct 2009 01:08:36 +0000 Subject: [PATCH] Added MPERF and APERF MSR incrementation speed calculation using a 10ms delay loop git-svn-id: https://svn.code.sf.net/p/libcpuid/code/HEAD/libcpuid@75 3b4be424-7ac5-41d7-8526-f4ddcb85d872 --- libcpuid/rdmsr.c | 30 ++++++++++++++++++++---------- libcpuid/rdtsc.c | 23 +++++++++++++++++++++-- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/libcpuid/rdmsr.c b/libcpuid/rdmsr.c index 2ea1790..3e823b3 100644 --- a/libcpuid/rdmsr.c +++ b/libcpuid/rdmsr.c @@ -358,6 +358,9 @@ int cpu_msr_driver_close(struct msr_driver_t* drv) #endif /* _WIN32 */ + /* from rdtsc.c: */ +void sys_precise_clock(uint64_t *result); +int busy_loop_delay(int milliseconds); static int rdmsr_supported(void) { @@ -365,6 +368,21 @@ static int rdmsr_supported(void) return id->flags[CPU_FEATURE_MSR]; } +static int perfmsr_measure(struct msr_driver_t* handle, int msr) +{ + int err; + uint64_t a, b; + uint64_t x, y; + err = cpu_rdmsr(handle, msr, &x); + if (err) return CPU_INVALID_VALUE; + sys_precise_clock(&a); + busy_loop_delay(10); + cpu_rdmsr(handle, msr, &y); + sys_precise_clock(&b); + if (a >= b || x > y) return CPU_INVALID_VALUE; + return (y - x) / (b - a); +} + int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which) { uint64_t r; @@ -374,17 +392,9 @@ int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which) return set_error(ERR_HANDLE); switch (which) { case INFO_MPERF: - { - err = cpu_rdmsr(handle, 0xe7, &r); - if (err) return CPU_INVALID_VALUE; - return (int) (r & 0x7fffffff); - } + return perfmsr_measure(handle, 0xe7); case INFO_APERF: - { - err = cpu_rdmsr(handle, 0xe8, &r); - if (err) return CPU_INVALID_VALUE; - return (int) (r & 0x7fffffff); - } + return perfmsr_measure(handle, 0xe8); case INFO_CUR_MULTIPLIER: { err = cpu_rdmsr(handle, 0x2a, &r); diff --git a/libcpuid/rdtsc.c b/libcpuid/rdtsc.c index 2819a8e..2b098dd 100644 --- a/libcpuid/rdtsc.c +++ b/libcpuid/rdtsc.c @@ -29,7 +29,7 @@ #ifdef _WIN32 #include -static void sys_precise_clock(uint64_t *result) +void sys_precise_clock(uint64_t *result) { double c, f; LARGE_INTEGER freq, counter; @@ -42,7 +42,7 @@ static void sys_precise_clock(uint64_t *result) #else /* assuming Linux, Mac OS or other POSIX */ #include -static void sys_precise_clock(uint64_t *result) +void sys_precise_clock(uint64_t *result) { struct timeval tv; gettimeofday(&tv, NULL); @@ -157,6 +157,25 @@ static int busy_loop(int amount) return s; } +int busy_loop_delay(int milliseconds) +{ + int cycles = 0, r = 0, first = 1; + uint64_t a, b, c; + sys_precise_clock(&a); + while (1) { + sys_precise_clock(&c); + if ((c - a) / 1000 > milliseconds) return r; + r += busy_loop(cycles); + if (first) { + first = 0; + } else { + if (c - b < 1000) cycles *= 2; + if (c - b > 10000) cycles /= 2; + } + b = c; + } +} + int cpu_clock_measure(int millis, int quad_check) { struct cpu_mark_t begin[4], end[4], temp, temp2;