diff options
author | Lukas Larsson <[email protected]> | 2014-09-11 18:26:26 +0200 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2016-02-02 10:45:21 +0100 |
commit | eea5f896780e07f7ca76685061d01e7be5a7abaa (patch) | |
tree | 7d4a852b20f2075637457052844865e1c56b1e21 /erts/emulator/sys | |
parent | d76ee58c07f32dfc0652844ec2b513af2105ffa1 (diff) | |
download | otp-eea5f896780e07f7ca76685061d01e7be5a7abaa.tar.gz otp-eea5f896780e07f7ca76685061d01e7be5a7abaa.tar.bz2 otp-eea5f896780e07f7ca76685061d01e7be5a7abaa.zip |
erts, kernel: Add os:perf_counter function
The perf_counter is a very very cheap and high resolution timer
that can be used to timestamp system events. It does not have
monoticity guarantees, but should on most OS's expose a monotonous
time.
A special instruction has been created for this counter to further
speed up fetching it.
OTP-12908
Diffstat (limited to 'erts/emulator/sys')
-rw-r--r-- | erts/emulator/sys/unix/erl_unix_sys.h | 30 | ||||
-rw-r--r-- | erts/emulator/sys/unix/sys_time.c | 2 | ||||
-rw-r--r-- | erts/emulator/sys/win32/erl_win_sys.h | 2 |
3 files changed, 33 insertions, 1 deletions
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h index 0352ee1b3c..9f137048de 100644 --- a/erts/emulator/sys/unix/erl_unix_sys.h +++ b/erts/emulator/sys/unix/erl_unix_sys.h @@ -101,6 +101,10 @@ #endif #include <netdb.h> +#ifdef HAVE_MACH_ABSOLUTE_TIME +#include <mach/mach_time.h> +#endif + #ifdef HAVE_POSIX_MEMALIGN # define ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC 1 #endif @@ -266,7 +270,31 @@ erts_os_times(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep) #endif /* ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT */ /* - * + * Functions for getting the performance counter + */ + +#if defined(__x86_64__) + /* available on all x86_64. Best if used when we have constant_tsc and + nonstop_tsc cpu features. It may have been a good idea to put the + cpuid instruction before the rdtsc, but I decided against it + because it is not really needed for msacc, and it slows it down by + quite a bit. As a result though, this timestamp becomes much less + accurate as it might be re-ordered to be executed way before this + function is called. + */ +#define sys_perf_counter(ts) do { \ + __asm__ __volatile__ ("rdtsc\n\t" \ + "shl $32, %%rdx\n\t" \ + "or %%rdx, %0" : "=a" (*ts) : : "rdx"); \ + } while(0) +#define SYS_PERF_COUNTER_UNIT erts_perf_counter_unit() +#else +#define sys_perf_counter(ts) *(ts) = erts_get_perf_counter() +#define SYS_PERF_COUNTER_UNIT 1000000000LL +#endif + +/* + * Functions for measuring CPU time */ #if (defined(HAVE_GETHRVTIME) || defined(HAVE_CLOCK_GETTIME_CPU_TIME)) diff --git a/erts/emulator/sys/unix/sys_time.c b/erts/emulator/sys/unix/sys_time.c index 2e1914f564..6fc4fc7dc4 100644 --- a/erts/emulator/sys/unix/sys_time.c +++ b/erts/emulator/sys/unix/sys_time.c @@ -912,6 +912,8 @@ erts_os_times(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep) #ifdef HAVE_GETHRVTIME_PROCFS_IOCTL +/* The code below only has effect on solaris < 10, + needed in order for gehhrvtime to work properly */ int sys_start_hrvtime(void) { long msacct = PR_MSACCT; diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h index 7e8dd8a4ca..1ab9eadefd 100644 --- a/erts/emulator/sys/win32/erl_win_sys.h +++ b/erts/emulator/sys/win32/erl_win_sys.h @@ -238,6 +238,8 @@ erts_sys_hrtime(void) extern void sys_gettimeofday(SysTimeval *tv); extern clock_t sys_times(SysTimes *buffer); +#define sys_perf_counter(ts) *(ts) = erts_sys_hrtime() +#define SYS_PERF_COUNTER_UNIT ERTS_I64_LITERAL(1000000000) extern char *win_build_environment(char *); |