mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
MDEV-19845: Define my_timer_cycles() inline
On clang, use __builtin_readcyclecounter() when available. Hinted by Sergey Vojtovich. (This may lead to runtime failure on ARM systems. The hardware should be available on ARMv8 (AArch64), but access to it may require special privileges.) We remove support for the proprietary Sun Microsystems compiler, and rely on clang or the __GNUC__ assembler syntax instead. For now, we retain support for IA-64 (Itanium) and 32-bit SPARC, even though those platforms are likely no longer widely used. We remove support for clock_gettime(CLOCK_SGI_CYCLE), because Silicon Graphics ceased supporting IRIX in December 2013. This was the only cycle timer interface available for MIPS. On PowerPC, we rely on the GCC 4.8 __builtin_ppc_get_timebase() (or clang __builtin_readcyclecounter()), which should be equivalent to the old assembler code on both 64-bit and 32-bit targets.
This commit is contained in:
parent
1635ea9474
commit
5e929ee8a0
9 changed files with 124 additions and 295 deletions
|
@ -70,7 +70,7 @@ CHECK_C_SOURCE_RUNS(
|
|||
|
||||
|
||||
# Check is special processor flag needs to be set on older GCC
|
||||
#that defaults to v8 sparc . Code here is taken from my_rdtsc.c
|
||||
#that defaults to v8 sparc . Code here is taken from my_rdtsc.h
|
||||
IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_SIZEOF_VOID_P EQUAL 4
|
||||
AND CMAKE_SYSTEM_PROCESSOR MATCHES "sparc")
|
||||
SET(SOURCE
|
||||
|
|
|
@ -25,7 +25,6 @@ SET(HAVE_ACCESS 1 CACHE INTERNAL "")
|
|||
SET(HAVE_ALARM CACHE INTERNAL "")
|
||||
SET(HAVE_ALLOCA_H CACHE INTERNAL "")
|
||||
SET(HAVE_ARPA_INET_H CACHE INTERNAL "")
|
||||
SET(HAVE_ASM_MSR_H CACHE INTERNAL "")
|
||||
SET(HAVE_BACKTRACE CACHE INTERNAL "")
|
||||
SET(HAVE_BACKTRACE_SYMBOLS CACHE INTERNAL "")
|
||||
SET(HAVE_BACKTRACE_SYMBOLS_FD CACHE INTERNAL "")
|
||||
|
@ -132,7 +131,6 @@ SET(HAVE_PTHREAD_YIELD_NP CACHE INTERNAL "")
|
|||
SET(HAVE_PTHREAD_YIELD_ZERO_ARG CACHE INTERNAL "")
|
||||
SET(HAVE_PUTENV 1 CACHE INTERNAL "")
|
||||
SET(HAVE_PWD_H CACHE INTERNAL "")
|
||||
SET(HAVE_RDTSCLL CACHE INTERNAL "")
|
||||
SET(HAVE_READDIR_R CACHE INTERNAL "")
|
||||
SET(HAVE_READLINK CACHE INTERNAL "")
|
||||
SET(HAVE_READ_REAL_TIME CACHE INTERNAL "")
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#cmakedefine _GNU_SOURCE 1
|
||||
#cmakedefine HAVE_ALLOCA_H 1
|
||||
#cmakedefine HAVE_ARPA_INET_H 1
|
||||
#cmakedefine HAVE_ASM_MSR_H 1
|
||||
#cmakedefine HAVE_ASM_TERMBITS_H 1
|
||||
#cmakedefine HAVE_CRYPT_H 1
|
||||
#cmakedefine HAVE_CURSES_H 1
|
||||
|
@ -186,7 +185,6 @@
|
|||
#cmakedefine HAVE_POSIX_FALLOCATE 1
|
||||
#cmakedefine HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE 1
|
||||
#cmakedefine HAVE_PREAD 1
|
||||
#cmakedefine HAVE_RDTSCLL 1
|
||||
#cmakedefine HAVE_READ_REAL_TIME 1
|
||||
#cmakedefine HAVE_PTHREAD_ATTR_CREATE 1
|
||||
#cmakedefine HAVE_PTHREAD_ATTR_GETGUARDSIZE 1
|
||||
|
|
|
@ -437,8 +437,6 @@ SET(CMAKE_REQUIRED_FLAGS)
|
|||
CHECK_INCLUDE_FILES(time.h HAVE_TIME_H)
|
||||
CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H)
|
||||
CHECK_INCLUDE_FILES(sys/times.h HAVE_SYS_TIMES_H)
|
||||
CHECK_INCLUDE_FILES(asm/msr.h HAVE_ASM_MSR_H)
|
||||
#msr.h has rdtscll()
|
||||
|
||||
CHECK_INCLUDE_FILES(ia64intrin.h HAVE_IA64INTRIN_H)
|
||||
|
||||
|
@ -453,9 +451,6 @@ CHECK_FUNCTION_EXISTS(ftime HAVE_FTIME)
|
|||
CHECK_FUNCTION_EXISTS(time HAVE_TIME)
|
||||
# We can use time() on Macintosh if there is no ftime().
|
||||
|
||||
CHECK_FUNCTION_EXISTS(rdtscll HAVE_RDTSCLL)
|
||||
# I doubt that we'll ever reach the check for this.
|
||||
|
||||
|
||||
#
|
||||
# Tests for symbols
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2008 MySQL AB, 2009 Sun Microsystems, Inc.
|
||||
Use is subject to license terms.
|
||||
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
|
||||
|
@ -23,6 +23,20 @@
|
|||
#ifndef MY_RDTSC_H
|
||||
#define MY_RDTSC_H
|
||||
|
||||
# ifndef __has_builtin
|
||||
# define __has_builtin(x) 0 /* Compatibility with non-clang compilers */
|
||||
# endif
|
||||
# if __has_builtin(__builtin_readcyclecounter)
|
||||
# elif defined _WIN32
|
||||
# include <intrin.h>
|
||||
# elif defined __i386__ || defined __x86_64__
|
||||
# include <x86intrin.h>
|
||||
# elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H)
|
||||
# include <ia64intrin.h>
|
||||
# elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME)
|
||||
# include <sys/times.h>
|
||||
# endif
|
||||
|
||||
/**
|
||||
Characteristics of a timer.
|
||||
*/
|
||||
|
@ -62,12 +76,104 @@ C_MODE_START
|
|||
|
||||
/**
|
||||
A cycle timer.
|
||||
|
||||
On clang, we use __builtin_readcyclecounter().
|
||||
On other compilers:
|
||||
|
||||
On IA-32 and AMD64, we use the RDTSC instruction.
|
||||
On IA-64, we read the ar.itc register.
|
||||
On SPARC, we read the tick register.
|
||||
On POWER, we read the Time Base Register (which is not really a cycle count
|
||||
but a separate counter with less than nanosecond resolution).
|
||||
On IBM S/390 System z we use the STCK instruction.
|
||||
On ARM, we probably should use the Generic Timer, but should figure out
|
||||
how to ensure that it can be accessed.
|
||||
|
||||
Sadly, we have nothing for the Digital Alpha, MIPS, Motorola m68k,
|
||||
HP PA-RISC or other non-mainstream (or obsolete) processors.
|
||||
|
||||
TODO: consider C++11 std::chrono::high_resolution_clock.
|
||||
|
||||
We fall back to gethrtime() where available.
|
||||
|
||||
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).
|
||||
|
||||
@return the current timer value, in cycles.
|
||||
*/
|
||||
ulonglong my_timer_cycles(void);
|
||||
static inline ulonglong my_timer_cycles(void)
|
||||
{
|
||||
# if __has_builtin(__builtin_readcyclecounter)
|
||||
return __builtin_readcyclecounter();
|
||||
# elif defined _WIN32 || defined __i386__ || defined __x86_64__
|
||||
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__
|
||||
return __builtin_ppc_get_timebase();
|
||||
#elif defined(__GNUC__) && defined(__sparcv9) && defined(_LP64)
|
||||
{
|
||||
ulonglong result;
|
||||
__asm __volatile__ ("rd %%tick,%0" : "=r" (result));
|
||||
return result;
|
||||
}
|
||||
#elif defined(__GNUC__) && defined(__sparc__) && !defined(_LP64)
|
||||
{
|
||||
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(__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
|
||||
}
|
||||
|
||||
/**
|
||||
A namoseconds timer.
|
||||
A nanosecond timer.
|
||||
@return the current timer value, in nanoseconds.
|
||||
*/
|
||||
ulonglong my_timer_nanoseconds(void);
|
||||
|
@ -98,33 +204,22 @@ void my_timer_init(MY_TIMER_INFO *mti);
|
|||
|
||||
C_MODE_END
|
||||
|
||||
#define MY_TIMER_ROUTINE_ASM_X86 1
|
||||
#define MY_TIMER_ROUTINE_ASM_X86_64 2
|
||||
#define MY_TIMER_ROUTINE_RDTSCLL 3
|
||||
#define MY_TIMER_ROUTINE_ASM_X86_WIN 4
|
||||
#define MY_TIMER_ROUTINE_RDTSC 5
|
||||
#define MY_TIMER_ROUTINE_ASM_IA64 6
|
||||
#define MY_TIMER_ROUTINE_ASM_PPC 7
|
||||
#define MY_TIMER_ROUTINE_SGI_CYCLE 8
|
||||
#define MY_TIMER_ROUTINE_PPC_GET_TIMEBASE 7
|
||||
#define MY_TIMER_ROUTINE_GETHRTIME 9
|
||||
#define MY_TIMER_ROUTINE_READ_REAL_TIME 10
|
||||
#define MY_TIMER_ROUTINE_CLOCK_GETTIME 11
|
||||
#define MY_TIMER_ROUTINE_NXGETTIME 12
|
||||
#define MY_TIMER_ROUTINE_GETTIMEOFDAY 13
|
||||
#define MY_TIMER_ROUTINE_QUERYPERFORMANCECOUNTER 14
|
||||
#define MY_TIMER_ROUTINE_GETTICKCOUNT 15
|
||||
#define MY_TIMER_ROUTINE_TIME 16
|
||||
#define MY_TIMER_ROUTINE_TIMES 17
|
||||
#define MY_TIMER_ROUTINE_FTIME 18
|
||||
#define MY_TIMER_ROUTINE_ASM_PPC64 19
|
||||
#define MY_TIMER_ROUTINE_ASM_SUNPRO_SPARC64 20
|
||||
#define MY_TIMER_ROUTINE_ASM_SUNPRO_SPARC32 21
|
||||
#define MY_TIMER_ROUTINE_ASM_SUNPRO_I386 22
|
||||
#define MY_TIMER_ROUTINE_ASM_GCC_SPARC64 23
|
||||
#define MY_TIMER_ROUTINE_ASM_GCC_SPARC32 24
|
||||
#define MY_TIMER_ROUTINE_MACH_ABSOLUTE_TIME 25
|
||||
#define MY_TIMER_ROUTINE_GETSYSTEMTIMEASFILETIME 26
|
||||
#define MY_TIMER_ROUTINE_ASM_SUNPRO_X86_64 27
|
||||
#define MY_TIMER_ROUTINE_ASM_S390 28
|
||||
|
||||
#endif
|
||||
|
|
|
@ -59,12 +59,6 @@ IF(HAVE_ALARM)
|
|||
SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_alarm.c)
|
||||
ENDIF()
|
||||
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_C_COMPILER_ID MATCHES "SunPro")
|
||||
# Inline assembly template for rdtsc
|
||||
SET_SOURCE_FILES_PROPERTIES(my_rdtsc.c
|
||||
PROPERTIES COMPILE_FLAGS "${CMAKE_CURRENT_SOURCE_DIR}/my_timer_cycles.il")
|
||||
ENDIF()
|
||||
|
||||
IF(HAVE_LINUX_LARGE_PAGES)
|
||||
SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_largepage.c)
|
||||
ENDIF()
|
||||
|
|
|
@ -16,19 +16,12 @@
|
|||
#include <my_global.h>
|
||||
#include <my_atomic.h>
|
||||
#include <my_cpu.h>
|
||||
#include <my_rdtsc.h>
|
||||
|
||||
#ifdef HAVE_PAUSE_INSTRUCTION
|
||||
/** How many times to invoke PAUSE in a loop */
|
||||
unsigned my_cpu_relax_multiplier = 200;
|
||||
|
||||
# include <stdint.h>
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
# else
|
||||
# include <x86intrin.h>
|
||||
# endif
|
||||
|
||||
#define PAUSE4 MY_RELAX_CPU(); MY_RELAX_CPU(); MY_RELAX_CPU(); MY_RELAX_CPU()
|
||||
#define PAUSE16 PAUSE4; PAUSE4; PAUSE4; PAUSE4
|
||||
|
||||
|
@ -70,12 +63,12 @@ unsigned my_cpu_relax_multiplier = 200;
|
|||
*/
|
||||
void my_cpu_init(void)
|
||||
{
|
||||
uint64_t t0, t1, t2;
|
||||
t0= __rdtsc();
|
||||
ulonglong t0, t1, t2;
|
||||
t0= my_timer_cycles();
|
||||
PAUSE16;
|
||||
t1= __rdtsc();
|
||||
t1= my_timer_cycles();
|
||||
PAUSE16;
|
||||
t2= __rdtsc();
|
||||
t2= my_timer_cycles();
|
||||
if (t2 - t1 > 30 * 16 && t1 - t0 > 30 * 16)
|
||||
my_cpu_relax_multiplier= 20;
|
||||
}
|
||||
|
|
221
mysys/my_rdtsc.c
221
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),
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/* Copyright (c) 2008 MySQL AB, 2009 Sun Microsystems, Inc.
|
||||
Use is subject to license terms.
|
||||
|
||||
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
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
/* Sun Studio SPARC inline templates for cycle timer */
|
||||
/* Sun Studio i386 and x86_64 inline templates for cycle timer */
|
||||
/* I didn't say ".volatile" or ".nonvolatile". */
|
||||
|
||||
.inline my_timer_cycles_il_sparc64,0
|
||||
rd %tick,%o0
|
||||
.end
|
||||
|
||||
.inline my_timer_cycles_il_sparc32,0
|
||||
rd %tick,%o2
|
||||
srlx %o2,32,%o0
|
||||
sra %o2,0,%o1
|
||||
.end
|
||||
|
||||
.inline my_timer_cycles_il_i386,0
|
||||
rdtsc
|
||||
.end
|
||||
|
||||
.inline my_timer_cycles_il_x86_64,0
|
||||
rdtsc
|
||||
shlq $32,%rdx
|
||||
orq %rdx,%rax
|
||||
.end
|
Loading…
Reference in a new issue