mirror of
https://github.com/anrieff/libcpuid
synced 2024-11-10 22:59:13 +00:00
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
This commit is contained in:
parent
b0092bd84e
commit
519f984578
2 changed files with 41 additions and 12 deletions
|
@ -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);
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
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 <sys/time.h>
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue