Skip to content

Commit

Permalink
MDEV-23249: Support aarch64 architecture timer
Browse files Browse the repository at this point in the history
aarch64 timer is available to userspace via arch register.
clang's __builtin_readcyclecounter is wrong for aarch64 (reads the PMU
cycle counter instead of the archi-timer register), so we don't use it.

my_rdtsc unit-test on AWS m6g shows:
frequency: 121830845
resolution: 1
overhead: 1

This counter is not strictly increasing, but it is non-decreasing.
  • Loading branch information
Tzachi Zidenberg committed Jul 23, 2020
1 parent 5f2628d commit c76b45a
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 2 deletions.
14 changes: 12 additions & 2 deletions include/my_rdtsc.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ C_MODE_START
/**
A cycle timer.
On clang, we use __builtin_readcyclecounter().
On clang we use __builtin_readcyclecounter(), except for AARCH64.
On other compilers:
On IA-32 and AMD64, we use the RDTSC instruction.
Expand All @@ -88,6 +88,9 @@ C_MODE_START
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.
On AARCH64, we use the generic timer base register. We override clang
implementation for aarch64 as it access a PMU register which is not
guarenteed to be active.
Sadly, we have nothing for the Digital Alpha, MIPS, Motorola m68k,
HP PA-RISC or other non-mainstream (or obsolete) processors.
Expand Down Expand Up @@ -125,7 +128,7 @@ C_MODE_START
*/
static inline ulonglong my_timer_cycles(void)
{
# if __has_builtin(__builtin_readcyclecounter)
# if __has_builtin(__builtin_readcyclecounter) && !defined (__aarch64__)
return __builtin_readcyclecounter();
# elif defined _WIN32 || defined __i386__ || defined __x86_64__
return __rdtsc();
Expand Down Expand Up @@ -164,6 +167,12 @@ static inline ulonglong my_timer_cycles(void)
__asm__ __volatile__ ("stck %0" : "=Q" (result) : : "cc");
return result;
}
#elif defined(__GNUC__) && defined (__aarch64__)
{
ulonglong result;
__asm __volatile("mrs %0, CNTVCT_EL0" : "=&r" (result));
return result;
}
#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME)
/* gethrtime may appear as either cycle or nanosecond counter */
return (ulonglong) gethrtime();
Expand Down Expand Up @@ -221,6 +230,7 @@ C_MODE_END
#define MY_TIMER_ROUTINE_MACH_ABSOLUTE_TIME 25
#define MY_TIMER_ROUTINE_GETSYSTEMTIMEASFILETIME 26
#define MY_TIMER_ROUTINE_ASM_S390 28
#define MY_TIMER_ROUTINE_AARCH64 29

#endif

2 changes: 2 additions & 0 deletions mysys/my_rdtsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ void my_timer_init(MY_TIMER_INFO *mti)
mti->cycles.routine= MY_TIMER_ROUTINE_ASM_GCC_SPARC32;
#elif defined(__GNUC__) && defined(__s390__)
mti->cycles.routine= MY_TIMER_ROUTINE_ASM_S390;
#elif defined(__GNUC__) && defined (__aarch64__)
mti->cycles.routine= MY_TIMER_ROUTINE_AARCH64;
#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME)
mti->cycles.routine= MY_TIMER_ROUTINE_GETHRTIME;
#else
Expand Down

0 comments on commit c76b45a

Please sign in to comment.