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:
Jérôme Duval 2022-09-23 18:55:15 +02:00
parent 99071c0c0b
commit a6e9176bc5
1 changed files with 67 additions and 12 deletions

View File

@ -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();
}