99 lines
2.4 KiB
C++
99 lines
2.4 KiB
C++
|
/* ========================================================================
|
||
|
|
||
|
(C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
|
||
|
|
||
|
This software is provided 'as-is', without any express or implied
|
||
|
warranty. In no event will the authors be held liable for any damages
|
||
|
arising from the use of this software.
|
||
|
|
||
|
Please see https://computerenhance.com for more information
|
||
|
|
||
|
======================================================================== */
|
||
|
|
||
|
/* ========================================================================
|
||
|
LISTING 74
|
||
|
======================================================================== */
|
||
|
|
||
|
#if _WIN32
|
||
|
|
||
|
#include <intrin.h>
|
||
|
#include <windows.h>
|
||
|
|
||
|
static u64 GetOSTimerFreq(void)
|
||
|
{
|
||
|
LARGE_INTEGER Freq;
|
||
|
QueryPerformanceFrequency(&Freq);
|
||
|
return Freq.QuadPart;
|
||
|
}
|
||
|
|
||
|
static u64 ReadOSTimer(void)
|
||
|
{
|
||
|
LARGE_INTEGER Value;
|
||
|
QueryPerformanceCounter(&Value);
|
||
|
return Value.QuadPart;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
#include <x86intrin.h>
|
||
|
#include <sys/time.h>
|
||
|
|
||
|
static u64 GetOSTimerFreq(void)
|
||
|
{
|
||
|
return 1000000;
|
||
|
}
|
||
|
|
||
|
static u64 ReadOSTimer(void)
|
||
|
{
|
||
|
// NOTE(casey): The "struct" keyword is not necessary here when compiling in C++,
|
||
|
// but just in case anyone is using this file from C, I include it.
|
||
|
struct timeval Value;
|
||
|
gettimeofday(&Value, 0);
|
||
|
|
||
|
u64 Result = GetOSTimerFreq()*(u64)Value.tv_sec + (u64)Value.tv_usec;
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
/* NOTE(casey): This does not need to be "inline", it could just be "static"
|
||
|
because compilers will inline it anyway. But compilers will warn about
|
||
|
static functions that aren't used. So "inline" is just the simplest way
|
||
|
to tell them to stop complaining about that. */
|
||
|
inline u64 ReadCPUTimer(void)
|
||
|
{
|
||
|
// NOTE(casey): If you were on ARM, you would need to replace __rdtsc
|
||
|
// with one of their performance counter read instructions, depending
|
||
|
// on which ones are available on your platform.
|
||
|
|
||
|
return __rdtsc();
|
||
|
}
|
||
|
|
||
|
static u64 EstimateCPUTimerFreq(void)
|
||
|
{
|
||
|
u64 MillisecondsToWait = 100;
|
||
|
u64 OSFreq = GetOSTimerFreq();
|
||
|
|
||
|
u64 CPUStart = ReadCPUTimer();
|
||
|
u64 OSStart = ReadOSTimer();
|
||
|
u64 OSEnd = 0;
|
||
|
u64 OSElapsed = 0;
|
||
|
u64 OSWaitTime = OSFreq * MillisecondsToWait / 1000;
|
||
|
while(OSElapsed < OSWaitTime)
|
||
|
{
|
||
|
OSEnd = ReadOSTimer();
|
||
|
OSElapsed = OSEnd - OSStart;
|
||
|
}
|
||
|
|
||
|
u64 CPUEnd = ReadCPUTimer();
|
||
|
u64 CPUElapsed = CPUEnd - CPUStart;
|
||
|
|
||
|
u64 CPUFreq = 0;
|
||
|
if(OSElapsed)
|
||
|
{
|
||
|
CPUFreq = OSFreq * CPUElapsed / OSElapsed;
|
||
|
}
|
||
|
|
||
|
return CPUFreq;
|
||
|
}
|