summaryrefslogtreecommitdiff
path: root/mysys/my_rdtsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mysys/my_rdtsc.c')
-rw-r--r--mysys/my_rdtsc.c221
1 files changed, 8 insertions, 213 deletions
diff --git a/mysys/my_rdtsc.c b/mysys/my_rdtsc.c
index afb97553dd7..dce3ca2be3b 100644
--- a/mysys/my_rdtsc.c
+++ b/mysys/my_rdtsc.c
@@ -1,4 +1,5 @@
/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -74,10 +75,6 @@
#endif
#endif
-#if defined(HAVE_ASM_MSR_H) && defined(HAVE_RDTSCLL)
-#include <asm/msr.h> /* for rdtscll */
-#endif
-
#if defined(HAVE_SYS_TIMEB_H) && defined(HAVE_FTIME)
#include <sys/timeb.h> /* for ftime */
#endif
@@ -86,190 +83,10 @@
#include <sys/times.h> /* for times */
#endif
-#if defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H)
-#include <ia64intrin.h> /* for __GetReg */
-#endif
-
#if defined(__APPLE__) && defined(__MACH__)
#include <mach/mach_time.h>
#endif
-#if defined(__SUNPRO_CC) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7)
-extern "C" ulonglong my_timer_cycles_il_sparc64();
-#elif defined(__SUNPRO_CC) && defined(_ILP32) && !defined(__SunOS_5_7)
-extern "C" ulonglong my_timer_cycles_il_sparc32();
-#elif defined(__SUNPRO_CC) && defined(__i386) && defined(_ILP32)
-extern "C" ulonglong my_timer_cycles_il_i386();
-#elif defined(__SUNPRO_CC) && defined(__x86_64) && defined(_LP64)
-extern "C" ulonglong my_timer_cycles_il_x86_64();
-#elif defined(__SUNPRO_C) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7)
-ulonglong my_timer_cycles_il_sparc64();
-#elif defined(__SUNPRO_C) && defined(_ILP32) && !defined(__SunOS_5_7)
-ulonglong my_timer_cycles_il_sparc32();
-#elif defined(__SUNPRO_C) && defined(__i386) && defined(_ILP32)
-ulonglong my_timer_cycles_il_i386();
-#elif defined(__SUNPRO_C) && defined(__x86_64) && defined(_LP64)
-ulonglong my_timer_cycles_il_x86_64();
-#endif
-
-#if defined(__INTEL_COMPILER)
-/*
- icc warning #1011 is:
- missing return statement at end of non-void function
-*/
-#pragma warning (disable:1011)
-#endif
-
-/*
- For cycles, we depend on RDTSC for x86 platforms,
- or on time buffer (which is not really a cycle count
- but a separate counter with less than nanosecond
- resolution) for most PowerPC platforms, or on
- gethrtime which is okay for hpux and solaris, or on
- clock_gettime(CLOCK_SGI_CYCLE) for Irix platforms,
- or on read_real_time for aix platforms. There is
- nothing for Alpha platforms, they would be tricky.
-
- On the platforms that do not have a CYCLE timer,
- "wait" events are initialized to use NANOSECOND instead of CYCLE
- during performance_schema initialization (at the server startup).
-
- Linux performance monitor (see "man perf_event_open") can
- provide cycle counter on the platforms that do not have
- other kinds of cycle counters. But we don't use it so far.
-
- ARM notes
- ---------
- During tests on ARMv7 Debian, perf_even_open() based cycle counter provided
- too low frequency with too high overhead:
- MariaDB [performance_schema]> SELECT * FROM performance_timers;
- +-------------+-----------------+------------------+----------------+
- | TIMER_NAME | TIMER_FREQUENCY | TIMER_RESOLUTION | TIMER_OVERHEAD |
- +-------------+-----------------+------------------+----------------+
- | CYCLE | 689368159 | 1 | 970 |
- | NANOSECOND | 1000000000 | 1 | 308 |
- | MICROSECOND | 1000000 | 1 | 417 |
- | MILLISECOND | 1000 | 1000 | 407 |
- | TICK | 127 | 1 | 612 |
- +-------------+-----------------+------------------+----------------+
- Therefore, it was decided not to use perf_even_open() on ARM
- (i.e. go without CYCLE and have "wait" events use NANOSECOND by default).
-*/
-
-ulonglong my_timer_cycles(void)
-{
-#if defined(__GNUC__) && defined(__i386__)
- /* This works much better if compiled with "gcc -O3". */
- ulonglong result;
- __asm__ __volatile__ ("rdtsc" : "=A" (result));
- return result;
-#elif defined(__SUNPRO_C) && defined(__i386)
- __asm("rdtsc");
-#elif defined(__GNUC__) && defined(__x86_64__)
- ulonglong result;
- __asm__ __volatile__ ("rdtsc\n\t" \
- "shlq $32,%%rdx\n\t" \
- "orq %%rdx,%%rax"
- : "=a" (result) :: "%edx");
- return result;
-#elif defined(HAVE_ASM_MSR_H) && defined(HAVE_RDTSCLL)
- {
- ulonglong result;
- rdtscll(result);
- return result;
- }
-#elif defined(_WIN32) && defined(_M_IX86)
- __asm {rdtsc};
-#elif defined(_WIN64) && defined(_M_X64)
- /* For 64-bit Windows: unsigned __int64 __rdtsc(); */
- return __rdtsc();
-#elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H)
- return (ulonglong) __getReg(_IA64_REG_AR_ITC); /* (3116) */
-#elif defined(__GNUC__) && defined(__ia64__)
- {
- ulonglong result;
- __asm __volatile__ ("mov %0=ar.itc" : "=r" (result));
- return result;
- }
-#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (defined(__64BIT__) || defined(_ARCH_PPC64))
- {
- ulonglong result;
- __asm __volatile__ ("mftb %0" : "=r" (result));
- return result;
- }
-#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (!defined(__64BIT__) && !defined(_ARCH_PPC64))
- {
- /*
- mftbu means "move from time-buffer-upper to result".
- The loop is saying: x1=upper, x2=lower, x3=upper,
- if x1!=x3 there was an overflow so repeat.
- */
- unsigned int x1, x2, x3;
- ulonglong result;
- for (;;)
- {
- __asm __volatile__ ( "mftbu %0" : "=r"(x1) );
- __asm __volatile__ ( "mftb %0" : "=r"(x2) );
- __asm __volatile__ ( "mftbu %0" : "=r"(x3) );
- if (x1 == x3) break;
- }
- result = x1;
- return ( result << 32 ) | x2;
- }
-#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7)
- return (my_timer_cycles_il_sparc64());
-#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(_ILP32) && !defined(__SunOS_5_7)
- return (my_timer_cycles_il_sparc32());
-#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__i386) && defined(_ILP32)
- /* This is probably redundant for __SUNPRO_C. */
- return (my_timer_cycles_il_i386());
-#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__x86_64) && defined(_LP64)
- return (my_timer_cycles_il_x86_64());
-#elif defined(__GNUC__) && defined(__sparcv9) && defined(_LP64) && (__GNUC__>2)
- {
- ulonglong result;
- __asm __volatile__ ("rd %%tick,%0" : "=r" (result));
- return result;
- }
-#elif defined(__GNUC__) && defined(__sparc__) && !defined(_LP64) && (__GNUC__>2)
- {
- union {
- ulonglong wholeresult;
- struct {
- ulong high;
- ulong low;
- } splitresult;
- } result;
- __asm __volatile__ ("rd %%tick,%1; srlx %1,32,%0" : "=r" (result.splitresult.high), "=r" (result.splitresult.low));
- return result.wholeresult;
- }
-#elif defined(__sgi) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_SGI_CYCLE)
- {
- struct timespec tp;
- clock_gettime(CLOCK_SGI_CYCLE, &tp);
- return (ulonglong) tp.tv_sec * 1000000000 + (ulonglong) tp.tv_nsec;
- }
-#elif defined(__GNUC__) && defined(__s390__)
- /* covers both s390 and s390x */
- {
- ulonglong result;
- __asm__ __volatile__ ("stck %0" : "=Q" (result) : : "cc");
- return result;
- }
-#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME)
- /* gethrtime may appear as either cycle or nanosecond counter */
- return (ulonglong) gethrtime();
-#else
- return 0;
-#endif
-}
-
-#if defined(__INTEL_COMPILER)
-/* re-enable warning#1011 which was only for my_timer_cycles() */
-/* There may be an icc bug which means we must leave disabled. */
-#pragma warning (default:1011)
-#endif
-
/*
For nanoseconds, most platforms have nothing available that
(a) doesn't require bringing in a 40-kb librt.so library
@@ -518,7 +335,7 @@ static ulonglong my_timer_init_frequency(MY_TIMER_INFO *mti)
/*
Call my_timer_init before the first call to my_timer_xxx().
If something must be initialized, it happens here.
- Set: what routine is being used e.g. "asm_x86"
+ Set: what routine is being used e.g. "rdtsc"
Set: function, overhead, actual frequency, resolution.
*/
@@ -531,40 +348,18 @@ void my_timer_init(MY_TIMER_INFO *mti)
/* cycles */
mti->cycles.frequency= 1000000000;
-#if defined(__GNUC__) && defined(__i386__)
- mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86;
-#elif defined(__SUNPRO_C) && defined(__i386)
- mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86;
-#elif defined(__GNUC__) && defined(__x86_64__)
- mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86_64;
-#elif defined(HAVE_ASM_MSR_H) && defined(HAVE_RDTSCLL)
- mti->cycles.routine= MY_TIMER_ROUTINE_RDTSCLL;
-#elif defined(_WIN32) && defined(_M_IX86)
- mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86_WIN;
-#elif defined(_WIN64) && defined(_M_X64)
+#if defined _WIN32 || defined __i386__ || defined __x86_64__
mti->cycles.routine= MY_TIMER_ROUTINE_RDTSC;
#elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H)
mti->cycles.routine= MY_TIMER_ROUTINE_ASM_IA64;
#elif defined(__GNUC__) && defined(__ia64__)
mti->cycles.routine= MY_TIMER_ROUTINE_ASM_IA64;
-#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (defined(__64BIT__) || defined(_ARCH_PPC64))
- mti->cycles.routine= MY_TIMER_ROUTINE_ASM_PPC64;
-#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (!defined(__64BIT__) && !defined(_ARCH_PPC64))
- mti->cycles.routine= MY_TIMER_ROUTINE_ASM_PPC;
-#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7)
- mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_SPARC64;
-#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(_ILP32) && !defined(__SunOS_5_7)
- mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_SPARC32;
-#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__i386) && defined(_ILP32)
- mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_I386;
-#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__x86_64) && defined(_LP64)
- mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_X86_64;
+#elif defined __GNUC__ && defined __powerpc__
+ mti->cycles.routine= MY_TIMER_ROUTINE_PPC_GET_TIMEBASE;
#elif defined(__GNUC__) && defined(__sparcv9) && defined(_LP64) && (__GNUC__>2)
mti->cycles.routine= MY_TIMER_ROUTINE_ASM_GCC_SPARC64;
#elif defined(__GNUC__) && defined(__sparc__) && !defined(_LP64) && (__GNUC__>2)
mti->cycles.routine= MY_TIMER_ROUTINE_ASM_GCC_SPARC32;
-#elif defined(__sgi) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_SGI_CYCLE)
- mti->cycles.routine= MY_TIMER_ROUTINE_SGI_CYCLE;
#elif defined(__GNUC__) && defined(__s390__)
mti->cycles.routine= MY_TIMER_ROUTINE_ASM_S390;
#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME)
@@ -931,8 +726,8 @@ void my_timer_init(MY_TIMER_INFO *mti)
"include <linux/timex.h>" or "include <asm/timex.h>"
can lead to autoconf or compile errors, depending on system.
- rdtsc, __rdtsc, rdtscll: available for x86 with Linux BSD,
- Solaris, Windows. See "possible flaws and dangers" comments.
+ __rdtsc(): available for IA-32 and AMD64.
+ See "possible flaws and dangers" comments.
times(): what we use for ticks. Should just read the last
(xtime) tick count, therefore should be fast, but usually
@@ -966,7 +761,7 @@ void my_timer_init(MY_TIMER_INFO *mti)
getclock(): documented for Alpha, but not found during tests.
mach_absolute_time() and UpTime() are recommended for Apple.
- Inititally they weren't tried, because asm_ppc seems to do the job.
+ Initially they weren't tried, because ppc_get_timebase seems to do the job.
But now we use mach_absolute_time for nanoseconds.
Any clock-based timer can be affected by NPT (ntpd program),