aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/sys/unix
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2014-09-11 18:26:26 +0200
committerLukas Larsson <[email protected]>2016-02-02 10:45:21 +0100
commiteea5f896780e07f7ca76685061d01e7be5a7abaa (patch)
tree7d4a852b20f2075637457052844865e1c56b1e21 /erts/emulator/sys/unix
parentd76ee58c07f32dfc0652844ec2b513af2105ffa1 (diff)
downloadotp-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/unix')
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys.h30
-rw-r--r--erts/emulator/sys/unix/sys_time.c2
2 files changed, 31 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;