From 2d697067b2021ca5369f875289415dae30340af2 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Mon, 27 Jan 2020 21:46:43 +0100 Subject: [PATCH] Further cleanup/optimization of system_time On gcc4, we can use the __rdtsc builtin. On gcc2, provide a similar inline-able version of rdtsc, and remove the rdtsc function written in assembly, saving a call/ret on every call. There has been some discussion about performance, but note that this is only bootloader code, it is not used when the system is up and running, therefore performance is not that critical. --- src/system/boot/arch/x86/cpu.cpp | 19 ++++++++++++++----- src/system/boot/platform/bios_ia32/debug.cpp | 7 +------ src/system/boot/platform/bios_ia32/support.S | 5 ----- src/system/boot/platform/efi/support.S | 8 -------- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/system/boot/arch/x86/cpu.cpp b/src/system/boot/arch/x86/cpu.cpp index 9389fe042b..91f2ae9337 100644 --- a/src/system/boot/arch/x86/cpu.cpp +++ b/src/system/boot/arch/x86/cpu.cpp @@ -23,8 +23,6 @@ #include -extern "C" uint64 rdtsc(); - uint32 gTimeConversionFactor; // PIT definitions @@ -66,6 +64,17 @@ uint32 gTimeConversionFactor; // TODO: These are arbitrary. They are here to avoid spinning indefinitely // if the TSC just isn't stable and we can't get our desired error range. +#if __GNUC__ <= 2 +// It's a builtin on later compiler versions, but not in gcc2... +static inline uint64_t __rdtsc() +{ + uint64 tsc; + + asm volatile ("rdtsc\n" : "=A"(tsc)); + + return tsc; +} +#endif struct uint128 { uint128(uint64 low, uint64 high = 0) @@ -198,7 +207,7 @@ calibration_loop(uint8 desiredHighByte, uint8 channel, uint64& tscDelta, } while (startHigh != 255); // Read in the first TSC value - uint64 startTSC = rdtsc(); + uint64 startTSC = __rdtsc(); // Wait for the PIT to count down to our desired value uint8 endLow; @@ -210,7 +219,7 @@ calibration_loop(uint8 desiredHighByte, uint8 channel, uint64& tscDelta, } while (endHigh > desiredHighByte); // And read the second TSC value - uint64 endTSC = rdtsc(); + uint64 endTSC = __rdtsc(); tscDelta = endTSC - startTSC; expired = ((startHigh << 8) | startLow) - ((endHigh << 8) | endLow); @@ -304,7 +313,7 @@ slower_sample: extern "C" bigtime_t system_time() { - uint64 tsc = rdtsc(); + uint64 tsc = __rdtsc(); uint64 lo = (uint32)tsc; uint64 hi = tsc >> 32; return ((lo * gTimeConversionFactor) >> 32) + hi * gTimeConversionFactor; diff --git a/src/system/boot/platform/bios_ia32/debug.cpp b/src/system/boot/platform/bios_ia32/debug.cpp index 9bbc6dc708..4fc67738ac 100644 --- a/src/system/boot/platform/bios_ia32/debug.cpp +++ b/src/system/boot/platform/bios_ia32/debug.cpp @@ -32,11 +32,6 @@ static ring_buffer* sDebugSyslogBuffer = NULL; static bool sPostCleanup = false; -#ifdef PRINT_TIME_STAMPS -extern "C" uint64 rdtsc(); -#endif - - static void syslog_write(const char* buffer, size_t length) { @@ -65,7 +60,7 @@ dprintf_args(const char *format, va_list args) if (sNewLine) { char timeBuffer[32]; - snprintf(timeBuffer, sizeof(timeBuffer), "[%" B_PRIu64 "] ", rdtsc()); + snprintf(timeBuffer, sizeof(timeBuffer), "[%" B_PRIu64 "] ", __rdtsc()); syslog_write(timeBuffer, strlen(timeBuffer)); serial_puts(timeBuffer, strlen(timeBuffer)); } diff --git a/src/system/boot/platform/bios_ia32/support.S b/src/system/boot/platform/bios_ia32/support.S index ce89d6d892..442b72dcb5 100644 --- a/src/system/boot/platform/bios_ia32/support.S +++ b/src/system/boot/platform/bios_ia32/support.S @@ -7,11 +7,6 @@ #define FUNCTION(x) .global x; .type x,@function; x -/* uint64 rdtsc() */ -FUNCTION(rdtsc): - rdtsc - ret - FUNCTION(execute_n_instructions): movl 4(%esp), %ecx shrl $4, %ecx diff --git a/src/system/boot/platform/efi/support.S b/src/system/boot/platform/efi/support.S index 81828472d6..4c77461fae 100644 --- a/src/system/boot/platform/efi/support.S +++ b/src/system/boot/platform/efi/support.S @@ -7,14 +7,6 @@ #define FUNCTION(x) .global x; .type x,@function; x -/* uint64 rdtsc() */ -FUNCTION(rdtsc): - rdtsc - /* Convert to 64-bit result in rax. */ - shlq $32, %rdx - orq %rdx, %rax - ret - FUNCTION(execute_n_instructions): movl %edi, %ecx shrl $4, %ecx