x86_64: prefix rdtsc with lfence, or use rdtscp if available
a strong monotonicity is a property of system_time(). Performance should be a bit impacted (around 10%). removed omit-frame-pointer hints as the compiler generates the same without. Change-Id: I920145d616604f32b38d9e134ce83f3e0e848bc7 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5690 Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk> Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
parent
99071c0c0b
commit
a6e9176bc5
|
@ -4,6 +4,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <x86intrin.h>
|
#include <x86intrin.h>
|
||||||
|
@ -13,26 +15,79 @@ static uint64_t cv_factor;
|
||||||
static uint64_t cv_factor_nsec;
|
static uint64_t cv_factor_nsec;
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
static int64_t
|
||||||
__x86_setup_system_time(uint64_t cv, uint64_t cv_nsec)
|
__system_time_lfence()
|
||||||
{
|
|
||||||
cv_factor = cv;
|
|
||||||
cv_factor_nsec = cv_nsec;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" [[gnu::optimize("omit-frame-pointer")]] int64_t
|
|
||||||
system_time()
|
|
||||||
{
|
{
|
||||||
|
__builtin_ia32_lfence();
|
||||||
__uint128_t time = static_cast<__uint128_t>(__rdtsc()) * cv_factor;
|
__uint128_t time = static_cast<__uint128_t>(__rdtsc()) * cv_factor;
|
||||||
return time >> 64;
|
return time >> 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" [[gnu::optimize("omit-frame-pointer")]] int64_t
|
static int64_t
|
||||||
system_time_nsecs()
|
__system_time_rdtscp()
|
||||||
{
|
{
|
||||||
|
uint32_t aux;
|
||||||
|
__uint128_t time = static_cast<__uint128_t>(__rdtscp(&aux)) * cv_factor;
|
||||||
|
return time >> 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
__system_time_nsecs_lfence()
|
||||||
|
{
|
||||||
|
__builtin_ia32_lfence();
|
||||||
__uint128_t t = static_cast<__uint128_t>(__rdtsc()) * cv_factor_nsec;
|
__uint128_t t = static_cast<__uint128_t>(__rdtsc()) * cv_factor_nsec;
|
||||||
return t >> 32;
|
return t >> 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
__system_time_nsecs_rdtscp()
|
||||||
|
{
|
||||||
|
uint32_t aux;
|
||||||
|
__uint128_t t = static_cast<__uint128_t>(__rdtscp(&aux)) * cv_factor_nsec;
|
||||||
|
return t >> 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int64_t (*sSystemTime)(void) = __system_time_lfence;
|
||||||
|
static int64_t (*sSystemTimeNsecs)(void) = __system_time_nsecs_lfence;
|
||||||
|
|
||||||
|
|
||||||
|
// from kernel/arch/x86/arch_cpu.h
|
||||||
|
#define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
__x86_setup_system_time(uint64_t cv, uint64_t cv_nsec)
|
||||||
|
{
|
||||||
|
cv_factor = cv;
|
||||||
|
cv_factor_nsec = cv_nsec;
|
||||||
|
|
||||||
|
cpuid_info cpuInfo;
|
||||||
|
get_cpuid(&cpuInfo, 0x80000000, 0);
|
||||||
|
if (cpuInfo.eax_0.max_eax >= 0x80000001) {
|
||||||
|
get_cpuid(&cpuInfo, 0x80000001, 0);
|
||||||
|
if ((cpuInfo.regs.edx & IA32_FEATURE_AMD_EXT_RDTSCP)!= 0) {
|
||||||
|
sSystemTime = __system_time_rdtscp;
|
||||||
|
sSystemTimeNsecs = __system_time_nsecs_rdtscp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int64_t
|
||||||
|
system_time()
|
||||||
|
{
|
||||||
|
return sSystemTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int64_t
|
||||||
|
system_time_nsecs()
|
||||||
|
{
|
||||||
|
return sSystemTimeNsecs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue