aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/aclocal.m48
-rw-r--r--erts/emulator/beam/erl_time_sup.c48
-rw-r--r--erts/emulator/sys/unix/erl_unix_sys.h99
-rw-r--r--erts/emulator/sys/unix/sys_time.c491
-rw-r--r--erts/emulator/sys/win32/erl_win_sys.h9
-rw-r--r--erts/emulator/sys/win32/sys_time.c121
-rw-r--r--erts/emulator/test/node_container_SUITE.erl3
-rw-r--r--erts/emulator/test/timer_bif_SUITE.erl6
-rw-r--r--lib/common_test/src/ct_telnet.erl96
-rw-r--r--lib/common_test/src/ct_telnet_client.erl10
-rw-r--r--lib/common_test/test/ct_telnet_SUITE.erl4
-rw-r--r--lib/compiler/src/cerl.erl26
-rw-r--r--lib/compiler/src/cerl_trees.erl2
-rw-r--r--lib/inets/examples/httpd_load_test/hdlt_random_html.erl14
-rw-r--r--lib/inets/src/ftp/ftp.erl10
-rw-r--r--lib/inets/src/http_client/httpc_handler.erl4
-rw-r--r--lib/inets/src/inets_app/Makefile3
-rw-r--r--lib/inets/src/inets_app/inets.app.src1
-rw-r--r--lib/inets/src/inets_app/inets_lib.erl3
-rw-r--r--lib/inets/src/inets_app/inets_time_compat.erl71
-rw-r--r--lib/inets/src/tftp/tftp_logger.erl11
-rw-r--r--lib/inets/src/tftp/tftp_sup.erl13
-rw-r--r--lib/inets/test/ftp_suite_lib.erl13
-rw-r--r--lib/inets/test/httpc_SUITE.erl21
-rw-r--r--lib/inets/test/httpd_time_test.erl11
-rw-r--r--lib/ssh/src/ssh_info.erl2
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl16
27 files changed, 769 insertions, 347 deletions
diff --git a/erts/aclocal.m4 b/erts/aclocal.m4
index fb5ae4f02d..83f735d332 100644
--- a/erts/aclocal.m4
+++ b/erts/aclocal.m4
@@ -745,9 +745,9 @@ AC_DEFUN(ERL_MONOTONIC_CLOCK,
done
])
- AC_CHECK_FUNCS([clock_getres gethrtime])
+ AC_CHECK_FUNCS([clock_getres clock_get_attributes gethrtime])
- AC_CACHE_CHECK([for mach clock_get_time()], erl_cv_mach_clock_get_time_monotonic,
+ AC_CACHE_CHECK([for mach clock_get_time() with monotonic clock type], erl_cv_mach_clock_get_time_monotonic,
[
AC_TRY_COMPILE([
#include <mach/clock.h>
@@ -854,9 +854,9 @@ AC_DEFUN(ERL_WALL_CLOCK,
done
])
- AC_CHECK_FUNCS([clock_getres gettimeofday])
+ AC_CHECK_FUNCS([clock_getres clock_get_attributes gettimeofday])
- AC_CACHE_CHECK([for mach clock_get_time()], erl_cv_mach_clock_get_time_wall,
+ AC_CACHE_CHECK([for mach clock_get_time() with wall clock type], erl_cv_mach_clock_get_time_wall,
[
AC_TRY_COMPILE([
#include <mach/clock.h>
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index ef39f4b5f4..8203436c85 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1999-2012. All Rights Reserved.
+ * Copyright Ericsson AB 1999-2015. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -139,12 +139,12 @@ struct time_sup_read_only__ {
int os_monotonic_time_locked;
Uint64 os_monotonic_time_resolution;
Uint64 os_monotonic_time_extended;
+#endif
char *os_system_time_func;
char *os_system_time_clock_id;
int os_system_time_locked;
Uint64 os_system_time_resolution;
Uint64 os_system_time_extended;
-#endif
#if !ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT
ErtsMonotonicTime start;
struct {
@@ -287,7 +287,7 @@ get_time_offset(void)
#define ERTS_LONG_TIME_CORRECTION_CHECK ERTS_SEC_TO_MONOTONIC(60)
#define ERTS_SHORT_TIME_CORRECTION_CHECK ERTS_SEC_TO_MONOTONIC(15)
-#define ERTS_TIME_DRIFT_MAX_ADJ_DIFF ERTS_USEC_TO_MONOTONIC(100)
+#define ERTS_TIME_DRIFT_MAX_ADJ_DIFF ERTS_USEC_TO_MONOTONIC(50)
#define ERTS_TIME_DRIFT_MIN_ADJ_DIFF ERTS_USEC_TO_MONOTONIC(5)
static ERTS_INLINE ErtsMonotonicTime
@@ -353,21 +353,21 @@ print_correction(int change,
if (!change)
fprintf(stderr,
- "sdiff = %lld usec : [ec=%lld ppm, dc=%lld ppm] : "
+ "sdiff = %lld usec : [ec=%lld ppm, dc=%lld ppb] : "
"tmo = %lld msec\r\n",
(long long) usec_sdiff,
(long long) (1000000*old_ecorr) / ERTS_TCORR_ERR_UNIT,
- (long long) (1000000*old_dcorr) / ERTS_MONOTONIC_TIME_UNIT,
+ (long long) (1000000000*old_dcorr) / ERTS_MONOTONIC_TIME_UNIT,
(long long) tmo);
else
fprintf(stderr,
- "sdiff = %lld usec : [ec=%lld ppm, dc=%lld ppm] "
- "-> [ec=%lld ppm, dc=%lld ppm] : tmo = %lld msec\r\n",
+ "sdiff = %lld usec : [ec=%lld ppm, dc=%lld ppb] "
+ "-> [ec=%lld ppm, dc=%lld ppb] : tmo = %lld msec\r\n",
(long long) usec_sdiff,
(long long) (1000000*old_ecorr) / ERTS_TCORR_ERR_UNIT,
- (long long) (1000000*old_dcorr) / ERTS_MONOTONIC_TIME_UNIT,
+ (long long) (1000000000*old_dcorr) / ERTS_MONOTONIC_TIME_UNIT,
(long long) (1000000*new_ecorr) / ERTS_TCORR_ERR_UNIT,
- (long long) (1000000*new_dcorr) / ERTS_MONOTONIC_TIME_UNIT,
+ (long long) (1000000000*new_dcorr) / ERTS_MONOTONIC_TIME_UNIT,
(long long) tmo);
}
@@ -412,8 +412,7 @@ check_time_correction(void *unused)
ASSERT(time_sup.inf.c.finalized_offset);
- os_mtime = erts_os_monotonic_time();
- os_stime = erts_os_system_time();
+ erts_os_times(&os_mtime, &os_stime);
cdata = time_sup.inf.c.parmon.cdata;
@@ -556,13 +555,6 @@ check_time_correction(void *unused)
ddp->acc.mon = mtime_acc;
ddp->acc.sys = stime_acc;
- /*
- * If calculated drift adjustment is if off by more than 20%
- * from the average drift we interpret this as a discontinous
- * leap in system time and ignore it. If it actually is a
- * change in drift we will later detect this when the average
- * drift change.
- */
drift_adj_diff = avg_drift_adj - drift_adj;
if (drift_adj_diff < -ERTS_TIME_DRIFT_MAX_ADJ_DIFF
|| ERTS_TIME_DRIFT_MAX_ADJ_DIFF < drift_adj_diff) {
@@ -691,8 +683,7 @@ init_check_time_correction(void *unused)
old_mtime = ddp->intervals[0].time.mon;
old_stime = ddp->intervals[0].time.sys;
- mtime = erts_os_monotonic_time();
- stime = erts_os_system_time();
+ erts_os_times(&mtime, &stime);
mtime_diff = mtime - old_mtime;
stime_diff = stime - old_stime;
@@ -732,8 +723,7 @@ finalize_corrected_time_offset(ErtsSystemTime *stimep)
erts_smp_rwmtx_rlock(&time_sup.inf.c.parmon.rwmtx);
- os_mtime = erts_os_monotonic_time();
- *stimep = erts_os_system_time();
+ erts_os_times(&os_mtime, stimep);
cdata = time_sup.inf.c.parmon.cdata;
@@ -852,6 +842,7 @@ void erts_init_sys_time_sup(void)
= sys_init_time_res.os_monotonic_time_info.resolution;
time_sup.r.o.os_monotonic_time_extended
= sys_init_time_res.os_monotonic_time_info.extended;
+#endif
time_sup.r.o.os_system_time_func
= sys_init_time_res.os_system_time_info.func;
time_sup.r.o.os_system_time_clock_id
@@ -860,7 +851,6 @@ void erts_init_sys_time_sup(void)
= sys_init_time_res.os_system_time_info.locked_use;
time_sup.r.o.os_system_time_resolution
= sys_init_time_res.os_system_time_info.resolution;
-#endif
}
int
@@ -935,9 +925,11 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
#endif
- resolution = time_sup.r.o.os_monotonic_time_resolution;
- if (resolution > time_sup.r.o.os_system_time_resolution)
- resolution = time_sup.r.o.os_system_time_resolution;
+ resolution = time_sup.r.o.os_system_time_resolution;
+#ifdef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
+ if (resolution > time_sup.r.o.os_monotonic_time_resolution)
+ resolution = time_sup.r.o.os_monotonic_time_resolution;
+#endif
time_sup.r.o.adj.large_diff = erts_time_sup__.r.o.monotonic_time_unit;
time_sup.r.o.adj.large_diff *= 50;
@@ -972,8 +964,8 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
ErtsMonotonicCorrectionData *cdatap;
erts_smp_rwmtx_opt_t rwmtx_opts = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
ErtsMonotonicTime offset;
- time_sup.inf.c.minit = erts_os_monotonic_time();
- time_sup.inf.c.sinit = erts_os_system_time();
+ erts_os_times(&time_sup.inf.c.minit,
+ &time_sup.inf.c.sinit);
time_sup.r.o.moffset = -1*time_sup.inf.c.minit;
offset = time_sup.inf.c.sinit;
offset -= ERTS_MONOTONIC_TIME_UNIT;
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h
index aa158390d6..8fc5a3ca49 100644
--- a/erts/emulator/sys/unix/erl_unix_sys.h
+++ b/erts/emulator/sys/unix/erl_unix_sys.h
@@ -171,61 +171,47 @@ typedef long long ErtsSysHrTime;
typedef ErtsMonotonicTime ErtsSystemTime;
-ErtsSystemTime erts_os_system_time(void);
-
#define ERTS_MONOTONIC_TIME_MIN (((ErtsMonotonicTime) 1) << 63)
#define ERTS_MONOTONIC_TIME_MAX (~ERTS_MONOTONIC_TIME_MIN)
/*
- * OS monotonic time
+ * OS monotonic time and OS system time
*/
-/*
- * Most common with os monotonic time using nano second
- * time unit. These defines are modified below if this
- * isn't the case...
- */
-#define ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT 1
-#define ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT (1000*1000*1000)
+#undef ERTS_OS_TIMES_INLINE_FUNC_PTR_CALL__
+
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+# if defined(__linux__)
+# define ERTS_OS_TIMES_INLINE_FUNC_PTR_CALL__ 1
+# endif
+#endif
+
+ErtsSystemTime erts_os_system_time(void);
+#undef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
+#undef ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT
#undef ERTS_OS_MONOTONIC_INLINE_FUNC_PTR_CALL__
#undef ERTS_HAVE_CORRECTED_OS_MONOTONIC
#if defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)
-
-#if defined(__linux__)
-
-#define ERTS_HAVE_CORRECTED_OS_MONOTONIC 1
-#define ERTS_OS_MONOTONIC_INLINE_FUNC_PTR_CALL__ 1
-
-#else /* !defined(__linux__) */
-
-ErtsMonotonicTime erts_os_monotonic_time(void);
-
-#endif /* !defined(__linux__) */
-
+# define ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT 1
+# define ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT (1000*1000*1000)
+# if defined(__linux__)
+# define ERTS_HAVE_CORRECTED_OS_MONOTONIC 1
+# define ERTS_OS_MONOTONIC_INLINE_FUNC_PTR_CALL__ 1
+# endif
+#elif defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME)
+# define ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT 1
+# define ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT (1000*1000*1000)
#elif defined(OS_MONOTONIC_TIME_USING_GETHRTIME)
-
-#define erts_os_monotonic() ((ErtsMonotonicTime) gethrtime())
-#define erts_sys_hrtime() ((ErtsSysHrTime) gethrtime())
-
-#elif defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME) \
- || defined(OS_MONOTONIC_TIME_USING_TIMES)
-
-#if defined(OS_MONOTONIC_TIME_USING_TIMES)
+# define ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT 1
+# define ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT (1000*1000*1000)
+#elif defined(OS_MONOTONIC_TIME_USING_TIMES)
+# define ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT 1
/* Time unit determined at runtime... */
-# undef ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT
# define ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT 0
-#endif
-
-ErtsMonotonicTime erts_os_monotonic_time(void);
-
#else /* No OS monotonic available... */
-
-#undef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
-#undef ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT
-#define ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT (1000*1000)
-
+# define ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT (1000*1000)
#endif
/*
@@ -233,14 +219,15 @@ ErtsMonotonicTime erts_os_monotonic_time(void);
* time function found. Time unit is nano-seconds.
* It may or may not be monotonic.
*/
-#ifndef erts_sys_hrtime
-extern ErtsSysHrTime erts_sys_hrtime(void);
-#endif
+ErtsSysHrTime erts_sys_hrtime(void);
struct erts_sys_time_read_only_data__ {
#ifdef ERTS_OS_MONOTONIC_INLINE_FUNC_PTR_CALL__
ErtsMonotonicTime (*os_monotonic_time)(void);
#endif
+#ifdef ERTS_OS_TIMES_INLINE_FUNC_PTR_CALL__
+ void (*os_times)(ErtsMonotonicTime *, ErtsSystemTime *);
+#endif
int ticks_per_sec;
};
@@ -255,21 +242,43 @@ typedef struct {
extern ErtsSysTimeData__ erts_sys_time_data__;
+#ifdef ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT
+
#ifdef ERTS_OS_MONOTONIC_INLINE_FUNC_PTR_CALL__
+ERTS_GLB_INLINE
+#endif
+ErtsMonotonicTime erts_os_monotonic_time(void);
-ERTS_GLB_INLINE ErtsMonotonicTime erts_os_monotonic_time(void);
+#ifdef ERTS_OS_TIMES_INLINE_FUNC_PTR_CALL__
+ERTS_GLB_INLINE
+#endif
+void erts_os_times(ErtsMonotonicTime *, ErtsSystemTime *);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
+#ifdef ERTS_OS_MONOTONIC_INLINE_FUNC_PTR_CALL__
+
ERTS_GLB_INLINE ErtsMonotonicTime
erts_os_monotonic_time(void)
{
return (*erts_sys_time_data__.r.o.os_monotonic_time)();
}
+#endif /* ERTS_OS_MONOTONIC_INLINE_FUNC_PTR_CALL__ */
+
+#ifdef ERTS_OS_TIMES_INLINE_FUNC_PTR_CALL__
+
+ERTS_GLB_INLINE void
+erts_os_times(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep)
+{
+ return (*erts_sys_time_data__.r.o.os_times)(mtimep, stimep);
+}
+
+#endif /* ERTS_OS_TIMES_INLINE_FUNC_PTR_CALL__ */
+
#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
-#endif /* ERTS_OS_MONOTONIC_INLINE_FUNC_PTR_CALL__ */
+#endif /* ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT */
/*
*
diff --git a/erts/emulator/sys/unix/sys_time.c b/erts/emulator/sys/unix/sys_time.c
index d6591a8296..ea021a27cf 100644
--- a/erts/emulator/sys/unix/sys_time.c
+++ b/erts/emulator/sys/unix/sys_time.c
@@ -35,6 +35,20 @@
#include "global.h"
#include "erl_os_monotonic_time_extender.h"
+#undef ERTS_HAVE_ERTS_OS_TIMES_IMPL__
+#undef ERTS_HAVE_ERTS_SYS_HRTIME_IMPL__
+
+#if defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME) \
+ || defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME)
+# include <mach/clock.h>
+# include <mach/mach.h>
+# ifdef HAVE_CLOCK_GET_ATTRIBUTES
+# define ERTS_HAVE_MACH_CLOCK_GETRES
+static Sint64
+mach_clock_getres(clock_id_t clkid, char *clkid_str);
+# endif
+#endif
+
#ifdef NO_SYSCONF
# define TICKS_PER_SEC() HZ
#else
@@ -87,6 +101,10 @@ ErtsSysTimeData__ erts_sys_time_data__ erts_align_attribute(ERTS_CACHE_LINE_SIZE
static ErtsMonotonicTime clock_gettime_monotonic_raw(void);
static ErtsMonotonicTime clock_gettime_monotonic_verified(void);
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+static void clock_gettime_times_raw(ErtsMonotonicTime *, ErtsSystemTime *);
+static void clock_gettime_times_verified(ErtsMonotonicTime *, ErtsSystemTime *);
+#endif
#endif /* defined(__linux__) && defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME) */
@@ -167,6 +185,9 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
init_resp->os_monotonic_time_info.resolution = 1;
}
}
+#elif defined(ERTS_HAVE_MACH_CLOCK_GETRES) && defined(MONOTONIC_CLOCK_ID)
+ init_resp->os_monotonic_time_info.resolution
+ = mach_clock_getres(MONOTONIC_CLOCK_ID, MONOTONIC_CLOCK_ID_STR);
#endif
#ifdef MONOTONIC_CLOCK_ID_STR
@@ -197,9 +218,14 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
#if defined(__linux__) && defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)
- if (vsn >= ERTS_MK_VSN_INT(2, 6, 33))
+ if (vsn >= ERTS_MK_VSN_INT(2, 6, 33)) {
erts_sys_time_data__.r.o.os_monotonic_time =
clock_gettime_monotonic_raw;
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+ erts_sys_time_data__.r.o.os_times =
+ clock_gettime_times_raw;
+#endif
+ }
else {
/*
* Linux versions prior to 2.6.33 have a
@@ -208,6 +234,10 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
*/
erts_sys_time_data__.r.o.os_monotonic_time =
clock_gettime_monotonic_verified;
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+ erts_sys_time_data__.r.o.os_times =
+ clock_gettime_times_verified;
+#endif
erts_smp_mtx_init(&internal_state.w.f.mtx,
"os_monotonic_time");
internal_state.w.f.last_delivered
@@ -292,6 +322,9 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
init_resp->os_system_time_info.resolution = 1;
}
}
+#elif defined(ERTS_HAVE_MACH_CLOCK_GETRES) && defined(WALL_CLOCK_ID)
+ init_resp->os_system_time_info.resolution
+ = mach_clock_getres(WALL_CLOCK_ID, WALL_CLOCK_ID_STR);
#endif
#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
@@ -303,7 +336,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
init_resp->os_system_time_info.resolution = 1000*1000;
init_resp->os_system_time_info.clock_id = NULL;
#else
-# error Missing erts_os_system_time() implmenentation
+# error Missing erts_os_system_time() implementation
#endif
}
@@ -333,117 +366,102 @@ adj_stime_time_unit(ErtsSystemTime stime, Uint32 res)
(Uint32) ERTS_MONOTONIC_TIME_UNIT));
}
-#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * POSIX clock_gettime() *
+\* */
-ErtsSystemTime
-erts_os_system_time(void)
+#if defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME) \
+ || defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+
+static ERTS_INLINE ErtsMonotonicTime
+timespec2montime(struct timespec *ts)
+{
+ ErtsMonotonicTime time;
+ time = (ErtsMonotonicTime) ts->tv_sec;
+ time *= (ErtsMonotonicTime) 1000*1000*1000;
+ time += (ErtsMonotonicTime) ts->tv_nsec;
+ return time;
+}
+
+static ERTS_INLINE ErtsMonotonicTime
+posix_clock_gettime(clockid_t id, char *name)
{
- ErtsSystemTime stime;
struct timespec ts;
- if (clock_gettime(WALL_CLOCK_ID,&ts) != 0) {
+ if (clock_gettime(id, &ts) != 0) {
int err = errno;
char *errstr = err ? strerror(err) : "unknown";
erl_exit(ERTS_ABORT_EXIT,
"clock_gettime(%s, _) failed: %s (%d)\n",
- WALL_CLOCK_ID_STR, errstr, err);
-
+ name, errstr, err);
}
-
- stime = (ErtsSystemTime) ts.tv_sec;
- stime *= (ErtsSystemTime) 1000*1000*1000;
- stime += (ErtsSystemTime) ts.tv_nsec;
- return adj_stime_time_unit(stime, (Uint32) 1000*1000*1000);
+ return timespec2montime(&ts);
}
-#elif defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME)
+#endif /* defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME) \
+ || defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME) */
+
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
ErtsSystemTime
erts_os_system_time(void)
{
ErtsSystemTime stime;
- kern_return_t res;
- clock_serv_t clk_srv;
- mach_timespec_t time_spec;
- int err;
-
- host_get_clock_service(mach_host_self(),
- WALL_CLOCK_ID,
- &clk_srv);
- errno = 0;
- res = clock_get_time(clk_srv, &time_spec);
- err = errno;
- mach_port_deallocate(mach_task_self(), clk_srv);
- if (res != KERN_SUCCESS) {
- char *errstr = err ? strerror(err) : "unknown";
- erl_exit(ERTS_ABORT_EXIT,
- "clock_get_time(%s, _) failed: %s (%d)\n",
- MONOTONIC_CLOCK_ID_STR, errstr, err);
- }
-
- stime = (ErtsSystemTime) time_spec.tv_sec;
- stime *= (ErtsSystemTime) 1000*1000*1000;
- stime += (ErtsSystemTime) time_spec.tv_nsec;
+ stime = (ErtsSystemTime) posix_clock_gettime(WALL_CLOCK_ID,
+ WALL_CLOCK_ID_STR);
+#if defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)
+ return stime;
+#else
return adj_stime_time_unit(stime, (Uint32) 1000*1000*1000);
+#endif
}
-#elif defined(OS_SYSTEM_TIME_GETTIMEOFDAY)
-
-ErtsSystemTime
-erts_os_system_time(void)
-{
- ErtsSystemTime stime;
- struct timeval tv;
-
- if (gettimeofday(&tv, NULL) != 0) {
- int err = errno;
- char *errstr = err ? strerror(err) : "unknown";
- erl_exit(ERTS_ABORT_EXIT,
- "gettimeofday(_, NULL) failed: %s (%d)\n",
- errstr, err);
- }
-
- stime = (ErtsSystemTime) tv.tv_sec;
- stime *= (ErtsSystemTime) 1000*1000;
- stime += (ErtsSystemTime) tv.tv_usec;
+#endif /* defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME) */
- return adj_stime_time_unit(stime, (Uint32) 1000*1000);
-}
+#if defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)
-#else
-# error Missing erts_os_system_time() implmenentation
-#endif
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
-#if defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME)
+#define ERTS_HAVE_ERTS_OS_TIMES_IMPL__
-static ERTS_INLINE ErtsMonotonicTime
-clock_gettime_monotonic(void)
+static ERTS_INLINE void
+posix_clock_gettime_times(ErtsMonotonicTime *mtimep,
+ ErtsSystemTime *stimep)
{
- ErtsMonotonicTime mtime;
- struct timespec ts;
+ struct timespec mts, sts;
+ int mres, sres, merr, serr;
- if (clock_gettime(MONOTONIC_CLOCK_ID,&ts) != 0) {
- int err = errno;
- char *errstr = err ? strerror(err) : "unknown";
+ mres = clock_gettime(MONOTONIC_CLOCK_ID, &mts);
+ merr = errno;
+ sres = clock_gettime(WALL_CLOCK_ID, &sts);
+ serr = errno;
+
+ if (mres != 0) {
+ char *errstr = merr ? strerror(merr) : "unknown";
erl_exit(ERTS_ABORT_EXIT,
"clock_gettime(%s, _) failed: %s (%d)\n",
- MONOTONIC_CLOCK_ID_STR, errstr, err);
-
+ MONOTONIC_CLOCK_ID_STR, errstr, merr);
}
- mtime = (ErtsMonotonicTime) ts.tv_sec;
- mtime *= (ErtsMonotonicTime) 1000*1000*1000;
- mtime += (ErtsMonotonicTime) ts.tv_nsec;
- return mtime;
+ if (sres != 0) {
+ char *errstr = serr ? strerror(serr) : "unknown";
+ erl_exit(ERTS_ABORT_EXIT,
+ "clock_gettime(%s, _) failed: %s (%d)\n",
+ WALL_CLOCK_ID_STR, errstr, serr);
+ }
+
+ *mtimep = timespec2montime(&mts);
+ *stimep = (ErtsSystemTime) timespec2montime(&sts);
}
+#endif /* defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME) */
+
#if defined(__linux__)
static ErtsMonotonicTime clock_gettime_monotonic_verified(void)
{
- ErtsMonotonicTime mtime;
-
- mtime = clock_gettime_monotonic();
+ ErtsMonotonicTime mtime = posix_clock_gettime(MONOTONIC_CLOCK_ID,
+ MONOTONIC_CLOCK_ID_STR);
erts_smp_mtx_lock(&internal_state.w.f.mtx);
if (mtime < internal_state.w.f.last_delivered)
@@ -455,66 +473,301 @@ static ErtsMonotonicTime clock_gettime_monotonic_verified(void)
return mtime;
}
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+
+static void clock_gettime_times_verified(ErtsMonotonicTime *mtimep,
+ ErtsSystemTime *stimep)
+{
+ posix_clock_gettime_times(mtimep, stimep);
+
+ erts_smp_mtx_lock(&internal_state.w.f.mtx);
+ if (*mtimep < internal_state.w.f.last_delivered)
+ *mtimep = internal_state.w.f.last_delivered;
+ else
+ internal_state.w.f.last_delivered = *mtimep;
+ erts_smp_mtx_unlock(&internal_state.w.f.mtx);
+}
+
+#endif /* defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME) */
+
static ErtsMonotonicTime clock_gettime_monotonic_raw(void)
{
- return clock_gettime_monotonic();
+ return posix_clock_gettime(MONOTONIC_CLOCK_ID,
+ MONOTONIC_CLOCK_ID_STR);
}
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+
+static void clock_gettime_times_raw(ErtsMonotonicTime *mtimep,
+ ErtsSystemTime *stimep)
+{
+ posix_clock_gettime_times(mtimep, stimep);
+}
+
+#endif /* defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME) */
+
#else /* !defined(__linux__) */
ErtsMonotonicTime erts_os_monotonic_time(void)
{
- return clock_gettime_monotonic();
+ return posix_clock_gettime(MONOTONIC_CLOCK_ID,
+ MONOTONIC_CLOCK_ID_STR);
+}
+
+#if defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME)
+
+static void erts_os_times(ErtsMonotonicTime *mtimep,
+ ErtsSystemTime *stimep)
+{
+ posix_clock_gettime_times(mtimep, stimep);
}
+#endif /* defined(OS_SYSTEM_TIME_USING_CLOCK_GETTIME) */
+
#endif /* !defined(__linux__) */
+#define ERTS_HAVE_ERTS_SYS_HRTIME_IMPL__
+
ErtsSysHrTime
erts_sys_hrtime(void)
{
- return (ErtsSysHrTime) clock_gettime_monotonic();
+ return (ErtsSysHrTime) posix_clock_gettime(MONOTONIC_CLOCK_ID,
+ MONOTONIC_CLOCK_ID_STR);
}
-#elif defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME)
+#endif /* defined(OS_MONOTONIC_TIME_USING_CLOCK_GETTIME) */
-#include <mach/clock.h>
-#include <mach/mach.h>
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * MACH clock_get_time() *
+\* */
-ErtsMonotonicTime erts_os_monotonic_time(void)
+#if defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME) \
+ || defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME)
+
+#ifdef ERTS_HAVE_MACH_CLOCK_GETRES
+
+static Sint64
+mach_clock_getres(clock_id_t clkid, char *clkid_str)
{
- ErtsMonotonicTime mtime;
- kern_return_t res;
+ mach_port_t task;
+ host_name_port_t host;
+ natural_t attr[1];
+ kern_return_t kret;
+ clock_serv_t clk_srv;
+ mach_msg_type_number_t cnt;
+
+ host = mach_host_self();
+ kret = host_get_clock_service(host, clkid, &clk_srv);
+ if (kret != KERN_SUCCESS) {
+ erl_exit(ERTS_ABORT_EXIT,
+ "host_get_clock_service(_, %s, _) failed\n",
+ clkid_str);
+ }
+
+ cnt = sizeof(attr);
+ kret = clock_get_attributes(clk_srv, CLOCK_GET_TIME_RES, (clock_attr_t) attr, &cnt);
+ if (kret != KERN_SUCCESS) {
+ erl_exit(ERTS_ABORT_EXIT,
+ "clock_get_attributes(%s, _) failed\n",
+ clkid_str);
+ }
+ task = mach_task_self();
+ mach_port_deallocate(task, host);
+ mach_port_deallocate(task, clk_srv);
+
+ return (Sint64) attr[0];
+}
+
+#endif /* ERTS_HAVE_MACH_CLOCK_GETRES */
+
+static ERTS_INLINE Sint64
+mach_clock_gettime(clock_id_t clkid, char *clkid_str)
+{
+ Sint64 time;
+ mach_port_t task;
+ host_name_port_t host;
+ kern_return_t kret;
clock_serv_t clk_srv;
mach_timespec_t time_spec;
- int err;
- host_get_clock_service(mach_host_self(),
- MONOTONIC_CLOCK_ID,
- &clk_srv);
+ host = mach_host_self();
+ kret = host_get_clock_service(host, clkid, &clk_srv);
+ if (kret != KERN_SUCCESS) {
+ erl_exit(ERTS_ABORT_EXIT,
+ "host_get_clock_service(_, %s, _) failed\n",
+ clkid_str);
+ }
errno = 0;
- res = clock_get_time(clk_srv, &time_spec);
- err = errno;
- mach_port_deallocate(mach_task_self(), clk_srv);
- if (res != KERN_SUCCESS) {
- char *errstr = err ? strerror(err) : "unknown";
+ kret = clock_get_time(clk_srv, &time_spec);
+ if (kret != KERN_SUCCESS) {
+ erl_exit(ERTS_ABORT_EXIT,
+ "clock_get_time(%s, _) failed\n",
+ clkid_str);
+ }
+ task = mach_task_self();
+ mach_port_deallocate(task, host);
+ mach_port_deallocate(task, clk_srv);
+
+ time = (Sint64) time_spec.tv_sec;
+ time *= (Sint64) 1000*1000*1000;
+ time += (Sint64) time_spec.tv_nsec;
+ return time;
+}
+
+#endif /* defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME) \
+ || defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME) */
+
+#if defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME)
+
+#define ERTS_HAVE_ERTS_OS_TIMES_IMPL__
+
+ErtsSystemTime
+erts_os_system_time(void)
+{
+ ErtsSystemTime stime;
+ stime = (ErtsSystemTime) mach_clock_gettime(WALL_CLOCK_ID,
+ WALL_CLOCK_ID_STR);
+#if defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME)
+ return stime;
+#else
+ return adj_stime_time_unit(stime, (Uint32) 1000*1000*1000);
+#endif
+}
+
+#endif /* defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME) */
+
+#if defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME)
+
+ErtsMonotonicTime
+erts_os_monotonic_time(void)
+{
+ return (ErtsMonotonicTime) mach_clock_gettime(MONOTONIC_CLOCK_ID,
+ MONOTONIC_CLOCK_ID_STR);
+}
+
+#define ERTS_HAVE_ERTS_SYS_HRTIME_IMPL__
+
+ErtsSysHrTime
+erts_sys_hrtime(void)
+{
+ return (ErtsMonotonicTime) mach_clock_gettime(MONOTONIC_CLOCK_ID,
+ MONOTONIC_CLOCK_ID_STR);
+}
+
+#if defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME)
+
+#define ERTS_HAVE_ERTS_OS_TIMES_IMPL__
+
+void
+erts_os_times(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep)
+{
+ ErtsMonotonicTime mtime;
+ ErtsSystemTime stime;
+ mach_port_t task;
+ host_name_port_t host;
+ kern_return_t mkret, skret;
+ clock_serv_t mclk_srv, sclk_srv;
+ mach_timespec_t mon_time_spec, sys_time_spec;
+
+ host = mach_host_self();
+ mkret = host_get_clock_service(host, MONOTONIC_CLOCK_ID, &mclk_srv);
+ skret = host_get_clock_service(host, WALL_CLOCK_ID, &sclk_srv);
+ if (mkret != KERN_SUCCESS) {
+ erl_exit(ERTS_ABORT_EXIT,
+ "host_get_clock_service(_, %s, _) failed\n",
+ MONOTONIC_CLOCK_ID);
+ }
+ if (skret != KERN_SUCCESS) {
erl_exit(ERTS_ABORT_EXIT,
- "clock_get_time(%s, _) failed: %s (%d)\n",
- MONOTONIC_CLOCK_ID_STR, errstr, err);
+ "host_get_clock_service(_, %s, _) failed\n",
+ WALL_CLOCK_ID);
}
+ mkret = clock_get_time(mclk_srv, &mon_time_spec);
+ skret = clock_get_time(sclk_srv, &sys_time_spec);
+ if (mkret != KERN_SUCCESS) {
+ erl_exit(ERTS_ABORT_EXIT,
+ "clock_get_time(%s, _) failed\n",
+ MONOTONIC_CLOCK_ID);
+ }
+ if (skret != KERN_SUCCESS) {
+ erl_exit(ERTS_ABORT_EXIT,
+ "clock_get_time(%s, _) failed\n",
+ WALL_CLOCK_ID);
+ }
+ task = mach_task_self();
+ mach_port_deallocate(task, host);
+ mach_port_deallocate(task, mclk_srv);
+ mach_port_deallocate(task, sclk_srv);
- mtime = (ErtsMonotonicTime) time_spec.tv_sec;
+ mtime = (ErtsMonotonicTime) mon_time_spec.tv_sec;
mtime *= (ErtsMonotonicTime) 1000*1000*1000;
- mtime += (ErtsMonotonicTime) time_spec.tv_nsec;
- return mtime;
+ mtime += (ErtsMonotonicTime) mon_time_spec.tv_nsec;
+ stime = (ErtsSystemTime) sys_time_spec.tv_sec;
+ stime *= (ErtsSystemTime) 1000*1000*1000;
+ stime += (ErtsSystemTime) sys_time_spec.tv_nsec;
+ *mtimep = mtime;
+ *stimep = stime;
+}
+
+#endif /* defined(OS_SYSTEM_TIME_USING_MACH_CLOCK_GET_TIME) */
+
+#endif /* defined(OS_MONOTONIC_TIME_USING_MACH_CLOCK_GET_TIME) */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * Solaris gethrtime() - OS monotonic time *
+\* */
+
+#if defined(OS_MONOTONIC_TIME_USING_GETHRTIME)
+
+ErtsMonotonicTime erts_os_monotonic_time(void)
+{
+ return (ErtsMonotonicTime) gethrtime();
}
+#define ERTS_HAVE_ERTS_SYS_HRTIME_IMPL__
+
ErtsSysHrTime
erts_sys_hrtime(void)
{
- return (ErtsSysHrTime) erts_os_monotonic_time();
+ return (ErtsSysHrTime) gethrtime();
}
-#elif defined(OS_MONOTONIC_TIME_USING_TIMES)
+#endif /* defined(OS_MONOTONIC_TIME_USING_GETHRTIME) */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * gettimeofday() - OS system time *
+\* */
+
+#if defined(OS_SYSTEM_TIME_GETTIMEOFDAY)
+
+ErtsSystemTime
+erts_os_system_time(void)
+{
+ ErtsSystemTime stime;
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) != 0) {
+ int err = errno;
+ char *errstr = err ? strerror(err) : "unknown";
+ erl_exit(ERTS_ABORT_EXIT,
+ "gettimeofday(_, NULL) failed: %s (%d)\n",
+ errstr, err);
+ }
+
+ stime = (ErtsSystemTime) tv.tv_sec;
+ stime *= (ErtsSystemTime) 1000*1000;
+ stime += (ErtsSystemTime) tv.tv_usec;
+
+ return adj_stime_time_unit(stime, (Uint32) 1000*1000);
+}
+
+#endif /* defined(OS_SYSTEM_TIME_GETTIMEOFDAY) */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * times() - OS monotonic time *
+\* */
+
+#if defined(OS_MONOTONIC_TIME_USING_TIMES)
ErtsMonotonicTime
erts_os_monotonic_time(void)
@@ -526,29 +779,35 @@ erts_os_monotonic_time(void)
ticks) << internal_state.r.o.times_shift;
}
-# define ERTS_NEED_ERTS_SYS_HRTIME_FALLBACK
-
-#else /* !defined(OS_MONOTONIC_TIME_USING_TIMES) */
-/* No os-monotonic-time */
-# define ERTS_NEED_ERTS_SYS_HRTIME_FALLBACK
#endif
-#ifdef ERTS_NEED_ERTS_SYS_HRTIME_FALLBACK
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
+ * Fallbacks *
+\* */
+
+#ifndef ERTS_HAVE_ERTS_SYS_HRTIME_IMPL__
ErtsSysHrTime
erts_sys_hrtime(void)
{
- ErtsSysHrTime time;
- struct timeval tv;
- gettimeofday(&tv);
- time = (ErtsSysHrTime) tv.tv_sec;
- time *= (ErtsSysHrTime) 1000*1000*1000;
- time += ((ErtsSysHrTime) tv.tv_usec)*1000;
- return time;
+ return (ErtsSysHrTime) ERTS_MONOTONIC_TO_NSEC(erts_os_system_time());
+}
+
+#endif
+
+#if !defined(ERTS_HAVE_ERTS_OS_TIMES_IMPL__) \
+ && defined(ERTS_HAVE_OS_MONOTONIC_TIME_SUPPORT)
+
+void
+erts_os_times(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep)
+{
+ *mtimep = erts_os_monotonic_time();
+ *stimep = erts_os_system_time();
}
#endif
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifdef HAVE_GETHRVTIME_PROCFS_IOCTL
diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h
index 9aeb460720..5181d6b584 100644
--- a/erts/emulator/sys/win32/erl_win_sys.h
+++ b/erts/emulator/sys/win32/erl_win_sys.h
@@ -193,6 +193,7 @@ ErtsSystemTime erts_os_system_time(void);
struct erts_sys_time_read_only_data__ {
ErtsMonotonicTime (*os_monotonic_time)(void);
+ void (*os_times)(ErtsMonotonicTime *, ErtsSystemTime*);
ErtsSysHrTime (*sys_hrtime)(void);
};
@@ -208,6 +209,8 @@ typedef struct {
extern ErtsSysTimeData__ erts_sys_time_data__;
ERTS_GLB_INLINE ErtsMonotonicTime erts_os_monotonic_time(void);
+ERTS_GLB_INLINE void erts_os_times(ErtsMonotonicTime *,
+ ErtsSystemTime *);
ERTS_GLB_INLINE ErtsSysHrTime erts_sys_hrtime(void);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
@@ -218,6 +221,12 @@ erts_os_monotonic_time(void)
return (*erts_sys_time_data__.r.o.os_monotonic_time)();
}
+ERTS_GLB_INLINE void
+erts_os_times(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep)
+{
+ return (*erts_sys_time_data__.r.o.os_times)(mtimep, stimep);
+}
+
ERTS_GLB_INLINE ErtsSysHrTime
erts_sys_hrtime(void)
{
diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index da9c4d2e29..7fe61084ce 100644
--- a/erts/emulator/sys/win32/sys_time.c
+++ b/erts/emulator/sys/win32/sys_time.c
@@ -119,6 +119,24 @@ __declspec(align(ASSUMED_CACHE_LINE_SIZE)) struct {
__declspec(align(ASSUMED_CACHE_LINE_SIZE)) ErtsSysTimeData__ erts_sys_time_data__;
+
+static ERTS_INLINE ErtsSystemTime
+SystemTime2MilliSec(SYSTEMTIME *stp)
+{
+ ErtsSystemTime stime;
+ FILETIME ft;
+ ULARGE_INTEGER ull;
+
+ SystemTimeToFileTime(stp, &ft);
+ FILETIME_TO_ULI(ull,ft);
+ /* now in 100 ns units */
+ stime = (ErtsSystemTime) ull.QuadPart;
+ stime -= (((ErtsSystemTime) EPOCH_JULIAN_DIFF)
+ * ((ErtsSystemTime) (10*1000*1000)));
+ stime /= (ErtsSystemTime) (10*1000); /* ms */
+ return stime;
+}
+
static ErtsMonotonicTime
os_monotonic_time_qpc(void)
{
@@ -130,6 +148,30 @@ os_monotonic_time_qpc(void)
return (ErtsMonotonicTime) pc.QuadPart;
}
+static void
+os_times_qpc(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep)
+{
+ LARGE_INTEGER pc;
+ SYSTEMTIME st;
+ ErtsSystemTime stime;
+ BOOL qpcr;
+
+ qpcr = (*internal_state.r.o.pQueryPerformanceCounter)(&pc);
+ GetSystemTime(&st);
+
+ if (!qpcr)
+ erl_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n");
+
+ *mtimep = (ErtsMonotonicTime) pc.QuadPart;
+
+ stime = SystemTime2MilliSec(&st);
+
+ *stimep = ((ErtsSystemTime)
+ erts_time_unit_conversion((Uint64) stime,
+ (Uint32) 1000,
+ internal_state.r.o.pcf));
+}
+
static Uint32
get_tick_count(void)
{
@@ -139,18 +181,64 @@ get_tick_count(void)
static ErtsMonotonicTime
os_monotonic_time_gtc32(void)
{
+ ErtsMonotonicTime mtime;
Uint32 ticks = (Uint32) GetTickCount();
ERTS_CHK_EXTEND_OS_MONOTONIC_TIME(&internal_state.wr.m.os_mtime_xtnd,
- tick_count);
- return ERTS_EXTEND_OS_MONOTONIC_TIME(&internal_state.wr.m.os_mtime_xtnd,
- ticks) << 10;
+ ticks);
+ mtime = ERTS_EXTEND_OS_MONOTONIC_TIME(&internal_state.wr.m.os_mtime_xtnd,
+ ticks);
+ mtime <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
+ return mtime;
+}
+
+static void
+os_times_gtc32(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep)
+{
+ SYSTEMTIME st;
+ ErtsSystemTime stime, mtime;
+ Uint32 ticks;
+
+ ticks = (Uint32) GetTickCount();
+ GetSystemTime(&st);
+
+ ERTS_CHK_EXTEND_OS_MONOTONIC_TIME(&internal_state.wr.m.os_mtime_xtnd,
+ ticks);
+ mtime = ERTS_EXTEND_OS_MONOTONIC_TIME(&internal_state.wr.m.os_mtime_xtnd,
+ ticks);
+ mtime <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
+ *mtimep = mtime;
+
+ stime = SystemTime2MilliSec(&st);
+ stime <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
+ *stimep = stime;
+
}
static ErtsMonotonicTime
os_monotonic_time_gtc64(void)
{
ULONGLONG ticks = (*internal_state.r.o.pGetTickCount64)();
- return (ErtsMonotonicTime) ticks << 10;
+ ErtsMonotonicTime mtime = (ErtsMonotonicTime) ticks;
+ return mtime << ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
+}
+
+static void
+os_times_gtc64(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep)
+{
+ SYSTEMTIME st;
+ ErtsSystemTime stime, mtime;
+ ULONGLONG ticks;
+
+ ticks = (*internal_state.r.o.pGetTickCount64)();
+ GetSystemTime(&st);
+
+ mtime = (ErtsMonotonicTime) ticks;
+ mtime <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
+ *mtimep = mtime;
+
+ stime = SystemTime2MilliSec(&st);
+ stime <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
+ *stimep = stime;
}
static ErtsSysHrTime
@@ -197,6 +285,7 @@ void
sys_init_time(ErtsSysInitTimeResult *init_resp)
{
ErtsMonotonicTime (*os_mtime_func)(void);
+ void (*os_times_func)(ErtsMonotonicTime *, ErtsSystemTime *);
ErtsSysHrTime (*sys_hrtime_func)(void) = NULL;
ErtsMonotonicTime time_unit;
char kernel_dll_name[] = "kernel32";
@@ -220,6 +309,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
time_unit <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
internal_state.r.o.using_get_tick_count_time_unit = 1;
os_mtime_func = os_monotonic_time_gtc32;
+ os_times_func = os_times_gtc32;
init_resp->os_monotonic_time_info.extended = 1;
erts_init_os_monotonic_time_extender(&internal_state.wr.m.os_mtime_xtnd,
get_tick_count,
@@ -250,6 +340,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
time_unit <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
internal_state.r.o.using_get_tick_count_time_unit = 1;
os_mtime_func = os_monotonic_time_gtc64;
+ os_times_func = os_times_gtc64;
if (!sys_hrtime_func)
sys_hrtime_func = sys_hrtime_gtc64;
}
@@ -292,10 +383,12 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
internal_state.r.o.using_get_tick_count_time_unit = 0;
init_resp->os_monotonic_time_info.resolution = time_unit;
os_mtime_func = os_monotonic_time_qpc;
+ os_times_func = os_times_qpc;
}
}
erts_sys_time_data__.r.o.os_monotonic_time = os_mtime_func;
+ erts_sys_time_data__.r.o.os_times = os_times_func;
init_resp->os_monotonic_time_unit = time_unit;
init_resp->have_os_monotonic_time = 1;
init_resp->sys_clock_resolution = 1;
@@ -600,21 +693,11 @@ sys_gettimeofday(SysTimeval *tv)
ErtsSystemTime
erts_os_system_time(void)
{
- SYSTEMTIME t;
- FILETIME ft;
- ULARGE_INTEGER ull;
+ SYSTEMTIME st;
ErtsSystemTime stime;
- GetSystemTime(&t);
- SystemTimeToFileTime(&t, &ft);
- FILETIME_TO_ULI(ull,ft);
-
- /* now in 100 ns units */
-
- stime = (ErtsSystemTime) ull.QuadPart;
- stime -= (((ErtsSystemTime) EPOCH_JULIAN_DIFF)
- * ((ErtsSystemTime) (10*1000*1000)));
- stime /= (ErtsSystemTime) (10*1000);
+ GetSystemTime(&st);
+ stime = SystemTime2MilliSec(&st);
if (internal_state.r.o.using_get_tick_count_time_unit) {
stime <<= ERTS_GET_TICK_COUNT_TIME_UNIT_SHIFT;
@@ -622,9 +705,9 @@ erts_os_system_time(void)
}
return ((ErtsSystemTime)
- erts_time_unit_conversion(stime,
+ erts_time_unit_conversion((Uint64) stime,
(Uint32) 1000,
- (Uint32) ERTS_MONOTONIC_TIME_UNIT));
+ internal_state.r.o.pcf));
}
diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl
index 3f9b339ed2..9c1839811a 100644
--- a/erts/emulator/test/node_container_SUITE.erl
+++ b/erts/emulator/test/node_container_SUITE.erl
@@ -686,6 +686,9 @@ timer_refc(doc) ->
"as they should for data stored in bif timers."];
timer_refc(suite) -> [];
timer_refc(Config) when is_list(Config) ->
+ {skipped, "Test needs to be UPDATED for new timer implementation"}.
+
+timer_refc_test(Config) when is_list(Config) ->
?line RNode = {get_nodename(), 1},
?line RPid = mk_pid(RNode, 4711, 2),
?line RPort = mk_port(RNode, 4711),
diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl
index da19be3424..56a1cef761 100644
--- a/erts/emulator/test/timer_bif_SUITE.erl
+++ b/erts/emulator/test/timer_bif_SUITE.erl
@@ -232,6 +232,9 @@ read_timer(Config) when is_list(Config) ->
cleanup(doc) -> [];
cleanup(suite) -> [];
cleanup(Config) when is_list(Config) ->
+ {skipped, "Test needs to be UPDATED for new timer implementation"}.
+
+cleanup_test(Config) when is_list(Config) ->
?line Mem = mem(),
%% Timer on dead process
?line P1 = spawn(fun () -> ok end),
@@ -420,6 +423,9 @@ evil_recv_timeouts(TOs, N, M) ->
registered_process(doc) -> [];
registered_process(suite) -> [];
registered_process(Config) when is_list(Config) ->
+ {skipped, "Test needs to be UPDATED for new timer implementation"}.
+
+registered_process_test(Config) when is_list(Config) ->
?line Mem = mem(),
%% Cancel
?line T1 = erlang:start_timer(500, ?MODULE, "hej"),
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index 4e03bf8630..d906a267a1 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -29,7 +29,9 @@
%% Command timeout = 10 sec (time to wait for a command to return)
%% Max no of reconnection attempts = 3
%% Reconnection interval = 5 sek (time to wait in between reconnection attempts)
-%% Keep alive = true (will send NOP to the server every 10 sec if connection is idle)</pre>
+%% Keep alive = true (will send NOP to the server every 10 sec if connection is idle)
+%% Polling limit = 0 (max number of times to poll to get a remaining string terminated)
+%% Polling interval = 1 sec (sleep time between polls)</pre>
%% <p>These parameters can be altered by the user with the following
%% configuration term:</p>
%% <pre>
@@ -37,7 +39,9 @@
%% {command_timeout,Millisec},
%% {reconnection_attempts,N},
%% {reconnection_interval,Millisec},
-%% {keep_alive,Bool}]}.</pre>
+%% {keep_alive,Bool},
+%% {poll_limit,N},
+%% {poll_interval,Millisec}]}.</pre>
%% <p><code>Millisec = integer(), N = integer()</code></p>
%% <p>Enter the <code>telnet_settings</code> term in a configuration
%% file included in the test and ct_telnet will retrieve the information
@@ -156,6 +160,8 @@
-define(RECONN_TIMEOUT,5000).
-define(DEFAULT_TIMEOUT,10000).
-define(DEFAULT_PORT,23).
+-define(POLL_LIMIT,0).
+-define(POLL_INTERVAL,1000).
-include("ct_util.hrl").
@@ -169,6 +175,8 @@
type,
target_mod,
keep_alive,
+ poll_limit=?POLL_LIMIT,
+ poll_interval=?POLL_INTERVAL,
extra,
conn_to=?DEFAULT_TIMEOUT,
com_to=?DEFAULT_TIMEOUT,
@@ -379,8 +387,15 @@ cmdf(Connection,CmdFormat,Args,Opts) when is_list(Args) ->
%%% Connection = ct_telnet:connection()
%%% Data = [string()]
%%% Reason = term()
-%%% @doc Get all data which has been received by the telnet client
-%%% since last command was sent.
+%%% @doc Get all data that has been received by the telnet client
+%%% since the last command was sent. Note that only newline terminated
+%%% strings are returned. If the last string received has not yet
+%%% been terminated, the connection may be polled automatically until
+%%% the string is complete. The polling feature is controlled
+%%% by the `poll_limit' and `poll_interval' config values and is
+%%% by default disabled (meaning the function will immediately
+%%% return all complete strings received and save a remaining
+%%% non-terminated string for a later `get_data' call).
get_data(Connection) ->
case get_handle(Connection) of
{ok,Pid} ->
@@ -596,9 +611,12 @@ init(Name,{Ip,Port,Type},{TargetMod,KeepAlive,Extra}) ->
"Reconnection attempts: ~p\n"
"Reconnection interval: ~p\n"
"Connection timeout: ~p\n"
- "Keep alive: ~w",
+ "Keep alive: ~w\n"
+ "Poll limit: ~w\n"
+ "Poll interval: ~w",
[Ip,Port,S1#state.com_to,S1#state.reconns,
- S1#state.reconn_int,S1#state.conn_to,KeepAlive]),
+ S1#state.reconn_int,S1#state.conn_to,KeepAlive,
+ S1#state.poll_limit,S1#state.poll_interval]),
{ok,TelnPid,S1};
{'EXIT',Reason} ->
{error,Reason};
@@ -619,6 +637,10 @@ set_telnet_defaults([{reconnection_interval,RInt}|Ss],S) ->
set_telnet_defaults(Ss,S#state{reconn_int=RInt});
set_telnet_defaults([{keep_alive,_}|Ss],S) ->
set_telnet_defaults(Ss,S);
+set_telnet_defaults([{poll_limit,PL}|Ss],S) ->
+ set_telnet_defaults(Ss,S#state{poll_limit=PL});
+set_telnet_defaults([{poll_interval,PI}|Ss],S) ->
+ set_telnet_defaults(Ss,S#state{poll_interval=PI});
set_telnet_defaults([Unknown|Ss],S) ->
force_log(S,error,
"Bad element in telnet_settings: ~p",[Unknown]),
@@ -706,10 +728,8 @@ handle_msg({send,Cmd,Opts},State) ->
handle_msg(get_data,State) ->
start_gen_log(heading(get_data,State#state.name)),
log(State,cmd,"Reading data...",[]),
- {ok,Data,Buffer} = teln_get_all_data(State#state.teln_pid,
- State#state.prx,
- State#state.buffer,
- [],[]),
+ {ok,Data,Buffer} = teln_get_all_data(State,State#state.buffer,[],[],
+ State#state.poll_limit),
log(State,recv,"Return: ~p",[{ok,Data}]),
end_gen_log(),
{{ok,Data},State#state{buffer=Buffer}};
@@ -944,16 +964,25 @@ teln_cmd(Pid,Cmd,Prx,Newline,Timeout) ->
ct_telnet_client:send_data(Pid,Cmd,Newline),
teln_receive_until_prompt(Pid,Prx,Timeout).
-teln_get_all_data(Pid,Prx,Data,Acc,LastLine) ->
+teln_get_all_data(State=#state{teln_pid=Pid,prx=Prx},Data,Acc,LastLine,Polls) ->
case check_for_prompt(Prx,LastLine++Data) of
{prompt,Lines,_PromptType,Rest} ->
- teln_get_all_data(Pid,Prx,Rest,[Lines|Acc],[]);
+ teln_get_all_data(State,Rest,[Lines|Acc],[],State#state.poll_limit);
{noprompt,Lines,LastLine1} ->
case ct_telnet_client:get_data(Pid) of
+ {ok,[]} when LastLine1 /= [], Polls > 0 ->
+ %% No more data from server but the last string is not
+ %% a complete line (maybe because of a slow connection),
+ timer:sleep(State#state.poll_interval),
+ NewPolls = if Polls == infinity -> infinity;
+ true -> Polls-1
+ end,
+ teln_get_all_data(State,[],[Lines|Acc],LastLine1,NewPolls);
{ok,[]} ->
{ok,lists:reverse(lists:append([Lines|Acc])),LastLine1};
{ok,Data1} ->
- teln_get_all_data(Pid,Prx,Data1,[Lines|Acc],LastLine1)
+ teln_get_all_data(State,Data1,[Lines|Acc],LastLine1,
+ State#state.poll_limit)
end
end.
@@ -1106,12 +1135,18 @@ repeat_expect(Name,Pid,Data,Pattern,Acc,EO) ->
teln_expect1(Name,Pid,Data,Pattern,Acc,EO=#eo{idle_timeout=IdleTO,
total_timeout=TotalTO}) ->
- ExpectFun = case EO#eo.seq of
+ %% TotalTO is a float value in this loop (unless it's 'infinity'),
+ %% but an integer value will be passed to the other functions
+ EOMod = if TotalTO /= infinity -> EO#eo{total_timeout=trunc(TotalTO)};
+ true -> EO
+ end,
+
+ ExpectFun = case EOMod#eo.seq of
true -> fun() ->
- seq_expect(Name,Pid,Data,Pattern,Acc,EO)
+ seq_expect(Name,Pid,Data,Pattern,Acc,EOMod)
end;
false -> fun() ->
- one_expect(Name,Pid,Data,Pattern,EO)
+ one_expect(Name,Pid,Data,Pattern,EOMod)
end
end,
case ExpectFun() of
@@ -1121,9 +1156,14 @@ teln_expect1(Name,Pid,Data,Pattern,Acc,EO=#eo{idle_timeout=IdleTO,
{halt,Why,Rest};
NotFinished ->
%% Get more data
- Fun = fun() -> get_data1(EO#eo.teln_pid) end,
- BreakAfter = if TotalTO < IdleTO -> TotalTO; true -> IdleTO end,
- case timer:tc(ct_gen_conn, do_within_time, [Fun, BreakAfter]) of
+ Fun = fun() -> get_data1(EOMod#eo.teln_pid) end,
+ BreakAfter = if TotalTO < IdleTO ->
+ %% use the integer value
+ EOMod#eo.total_timeout;
+ true ->
+ IdleTO
+ end,
+ case timer:tc(ct_gen_conn, do_within_time, [Fun,BreakAfter]) of
{_,{error,Reason}} ->
%% A timeout will occur when the telnet connection
%% is idle for EO#eo.idle_timeout milliseconds.
@@ -1132,13 +1172,15 @@ teln_expect1(Name,Pid,Data,Pattern,Acc,EO=#eo{idle_timeout=IdleTO,
case NotFinished of
{nomatch,Rest} ->
%% One expect
- teln_expect1(Name,Pid,Rest++Data1,Pattern,[],EO);
+ teln_expect1(Name,Pid,Rest++Data1,
+ Pattern,[],EOMod);
{continue,Patterns1,Acc1,Rest} ->
%% Sequence
- teln_expect1(Name,Pid,Rest++Data1,Patterns1,Acc1,EO)
+ teln_expect1(Name,Pid,Rest++Data1,
+ Patterns1,Acc1,EOMod)
end;
{Elapsed,{ok,Data1}} ->
- TVal = trunc(TotalTO - (Elapsed/1000)),
+ TVal = TotalTO - (Elapsed/1000),
if TVal =< 0 ->
{error,timeout};
true ->
@@ -1146,10 +1188,12 @@ teln_expect1(Name,Pid,Data,Pattern,Acc,EO=#eo{idle_timeout=IdleTO,
case NotFinished of
{nomatch,Rest} ->
%% One expect
- teln_expect1(Name,Pid,Rest++Data1,Pattern,[],EO1);
+ teln_expect1(Name,Pid,Rest++Data1,
+ Pattern,[],EO1);
{continue,Patterns1,Acc1,Rest} ->
%% Sequence
- teln_expect1(Name,Pid,Rest++Data1,Patterns1,Acc1,EO1)
+ teln_expect1(Name,Pid,Rest++Data1,
+ Patterns1,Acc1,EO1)
end
end
end
@@ -1430,8 +1474,10 @@ check_for_prompt(Prx,Data) ->
split_lines(String) ->
split_lines(String,[],[]).
-split_lines([$\n|Rest],Line,Lines) ->
+split_lines([$\n|Rest],Line,Lines) when Line /= [] ->
split_lines(Rest,[],[lists:reverse(Line)|Lines]);
+split_lines([$\n|Rest],[],Lines) ->
+ split_lines(Rest,[],Lines);
split_lines([$\r|Rest],Line,Lines) ->
split_lines(Rest,Line,Lines);
split_lines([0|Rest],Line,Lines) ->
diff --git a/lib/common_test/src/ct_telnet_client.erl b/lib/common_test/src/ct_telnet_client.erl
index f39863824c..b0734d8d65 100644
--- a/lib/common_test/src/ct_telnet_client.erl
+++ b/lib/common_test/src/ct_telnet_client.erl
@@ -32,7 +32,7 @@
-module(ct_telnet_client).
-%% -define(debug, true).
+%%-define(debug, true).
-export([open/2, open/3, open/4, open/5, close/1]).
-export([send_data/2, send_data/3, get_data/1]).
@@ -111,7 +111,6 @@ get_data(Pid) ->
{ok,Data}
end.
-
%%%-----------------------------------------------------------------
%%% Internal functions
init(Parent, Server, Port, Timeout, KeepAlive, ConnName) ->
@@ -146,7 +145,7 @@ loop(State, Sock, Acc) ->
ok
end;
{tcp,_,Msg0} ->
- dbg("tcp msg: ~tp~n",[Msg0]),
+ dbg("rcv tcp msg: ~tp~n",[Msg0]),
Msg = check_msg(Sock,Msg0,[]),
loop(State, Sock, [Msg | Acc]);
{send_data,Data} ->
@@ -180,6 +179,7 @@ loop(State, Sock, Acc) ->
NewState =
case State of
#state{keep_alive = true, get_data = 0} ->
+ dbg("sending NOP\n",[]),
if Acc == [] -> send([?IAC,?NOP], Sock,
State#state.conn_name);
true -> ok
@@ -225,15 +225,17 @@ loop(State, Sock, Acc) ->
gen_tcp:close(Sock),
Pid ! closed
after wait(State#state.keep_alive,?IDLE_TIMEOUT) ->
+ dbg("idle timeout\n",[]),
Data = lists:reverse(lists:append(Acc)),
case Data of
[] ->
+ dbg("sending NOP\n",[]),
send([?IAC,?NOP], Sock, State#state.conn_name),
loop(State, Sock, Acc);
_ when State#state.log_pos == length(Data)+1 ->
loop(State, Sock, Acc);
_ ->
- dbg("Idle timeout, printing ~tp\n",[Data]),
+ dbg("idle timeout, printing ~tp\n",[Data]),
Len = length(Data),
ct_telnet:log(State#state.conn_name,
general_io, "~ts",
diff --git a/lib/common_test/test/ct_telnet_SUITE.erl b/lib/common_test/test/ct_telnet_SUITE.erl
index 84e69c2b54..62cb821ede 100644
--- a/lib/common_test/test/ct_telnet_SUITE.erl
+++ b/lib/common_test/test/ct_telnet_SUITE.erl
@@ -203,7 +203,9 @@ telnet_config(_, LogType) ->
{command_timeout,10000},
{reconnection_attempts,0},
{reconnection_interval,0},
- {keep_alive,true}]} |
+ {keep_alive,true},
+ {poll_limit,10},
+ {poll_interval,1000}]} |
if LogType == legacy ->
[{ct_conn_log,[]}];
true ->
diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl
index 8367a1e19e..ea960abc1a 100644
--- a/lib/compiler/src/cerl.erl
+++ b/lib/compiler/src/cerl.erl
@@ -256,7 +256,7 @@
%% @see c_primop/2
%% @see c_receive/1
%% @see c_seq/2
-%% @see c_try/3
+%% @see c_try/5
%% @see c_tuple/1
%% @see c_values/1
%% @see c_var/1
@@ -1456,7 +1456,7 @@ is_proper_list(_) ->
%% X4]</code>.
%%
%% @see c_cons/2
-%% @see c_nil/1
+%% @see c_nil/0
%% @see is_c_list/1
%% @see list_length/1
%% @see make_list/2
@@ -1487,7 +1487,7 @@ abstract_list([]) ->
%% efficient.</p>
%%
%% @see c_cons/2
-%% @see c_nil/1
+%% @see c_nil/0
%% @see is_c_list/1
%% @see list_elements/1
@@ -1992,7 +1992,7 @@ update_c_fname(Node, Atom, Arity) ->
%%
%% @see c_fname/2
%% @see c_var/1
-%% @see c_var_name/1
+%% @see var_name/1
-spec is_c_fname(cerl()) -> boolean().
@@ -3670,7 +3670,7 @@ c_try(Expr, Vs, Body, Evs, Handler) ->
%% @spec ann_c_try(As::[term()], Expression::cerl(),
%% Variables::[cerl()], Body::cerl(),
%% EVars::[cerl()], Handler::cerl()) -> cerl()
-%% @see c_try/3
+%% @see c_try/5
-spec ann_c_try([term()], cerl(), [cerl()], cerl(), [cerl()], cerl()) ->
c_try().
@@ -3683,7 +3683,7 @@ ann_c_try(As, Expr, Vs, Body, Evs, Handler) ->
%% @spec update_c_try(Old::cerl(), Expression::cerl(),
%% Variables::[cerl()], Body::cerl(),
%% EVars::[cerl()], Handler::cerl()) -> cerl()
-%% @see c_try/3
+%% @see c_try/5
-spec update_c_try(c_try(), cerl(), [cerl()], cerl(), [cerl()], cerl()) ->
c_try().
@@ -3698,7 +3698,7 @@ update_c_try(Node, Expr, Vs, Body, Evs, Handler) ->
%% @doc Returns <code>true</code> if <code>Node</code> is an abstract
%% try-expression, otherwise <code>false</code>.
%%
-%% @see c_try/3
+%% @see c_try/5
-spec is_c_try(cerl()) -> boolean().
@@ -3712,7 +3712,7 @@ is_c_try(_) ->
%%
%% @doc Returns the expression subtree of an abstract try-expression.
%%
-%% @see c_try/3
+%% @see c_try/5
-spec try_arg(c_try()) -> cerl().
@@ -3725,7 +3725,7 @@ try_arg(Node) ->
%% @doc Returns the list of success variable subtrees of an abstract
%% try-expression.
%%
-%% @see c_try/3
+%% @see c_try/5
-spec try_vars(c_try()) -> [cerl()].
@@ -3737,7 +3737,7 @@ try_vars(Node) ->
%%
%% @doc Returns the success body subtree of an abstract try-expression.
%%
-%% @see c_try/3
+%% @see c_try/5
-spec try_body(c_try()) -> cerl().
@@ -3750,7 +3750,7 @@ try_body(Node) ->
%% @doc Returns the list of exception variable subtrees of an abstract
%% try-expression.
%%
-%% @see c_try/3
+%% @see c_try/5
-spec try_evars(c_try()) -> [cerl()].
@@ -3763,7 +3763,7 @@ try_evars(Node) ->
%% @doc Returns the exception body subtree of an abstract
%% try-expression.
%%
-%% @see c_try/3
+%% @see c_try/5
-spec try_handler(c_try()) -> cerl().
@@ -3785,7 +3785,7 @@ try_handler(Node) ->
%% @see update_c_catch/2
%% @see is_c_catch/1
%% @see catch_body/1
-%% @see c_try/3
+%% @see c_try/5
-spec c_catch(cerl()) -> c_catch().
diff --git a/lib/compiler/src/cerl_trees.erl b/lib/compiler/src/cerl_trees.erl
index b93da8e97f..f1bf0e02e7 100644
--- a/lib/compiler/src/cerl_trees.erl
+++ b/lib/compiler/src/cerl_trees.erl
@@ -19,7 +19,7 @@
%% @doc Basic functions on Core Erlang abstract syntax trees.
%%
%% <p>Syntax trees are defined in the module <a
-%% href=""><code>cerl</code></a>.</p>
+%% href="cerl"><code>cerl</code></a>.</p>
%%
%% @type cerl() = cerl:cerl()
diff --git a/lib/inets/examples/httpd_load_test/hdlt_random_html.erl b/lib/inets/examples/httpd_load_test/hdlt_random_html.erl
index c55de628c1..59073a3d23 100644
--- a/lib/inets/examples/httpd_load_test/hdlt_random_html.erl
+++ b/lib/inets/examples/httpd_load_test/hdlt_random_html.erl
@@ -19,7 +19,6 @@
%%
-module(hdlt_random_html).
--compile([{nowarn_deprecated_function,{erlang,now,0}}]).
-export([page/3]).
page(SessionID, _Env, Input) ->
@@ -49,15 +48,10 @@ stop() ->
".
content(WorkSim, SzSim) ->
- %% Adapt to OTP 18 erlang time API and be backwards compatible
- {A, B, C} = try
- {erlang:phash2([node()]),
- erlang:monotonic_time(),
- erlang:unique_integer()}
- catch
- error:undef ->
- erlang:now()
- end,
+ {A, B, C} = {erlang:phash2([node()]),
+ inets_time_compat:monotonic_time(),
+ inets_time_compat:unique_integer()},
+
random:seed(A, B, C),
lists:sort([random:uniform(X) || X <- lists:seq(1, WorkSim)]),
lists:flatten(lists:duplicate(SzSim, "Dummy data ")).
diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl
index 361a775024..7eebe8d5bf 100644
--- a/lib/inets/src/ftp/ftp.erl
+++ b/lib/inets/src/ftp/ftp.erl
@@ -21,7 +21,6 @@
%% It also supports ipv6 RFC 2428 and starttls RFC 4217.
-module(ftp).
--compile([{nowarn_deprecated_function,{erlang,now,0}}]).
-behaviour(gen_server).
-behaviour(inets_service).
@@ -2177,14 +2176,7 @@ handle_caller(#state{caller = {transfer_data, {Cmd, Bin, RemoteFile}}} =
%% Connect to FTP server at Host (default is TCP port 21)
%% in order to establish a control connection.
setup_ctrl_connection(Host, Port, Timeout, State) ->
- %% Adapt to OTP 18 erlang time API and be backwards compatible
- MsTime = try
- erlang:monotonic_time()
- catch
- error:undef ->
- %% Use Erlang system time as monotonic time
- erlang:now()
- end,
+ MsTime = inets_time_compat:monotonic_time(),
case connect(Host, Port, Timeout, State) of
{ok, IpFam, CSock} ->
NewState = State#state{csock = {tcp, CSock}, ipfamily = IpFam},
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 7f7328f1d9..8f2f11ce8e 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -1122,7 +1122,7 @@ handle_http_body(Body, #state{headers = Headers,
handle_response(State#state{headers = NewHeaders,
body = NewBody});
_ ->
- {NewBody2, NewRequest} =
+ {NewBody2, _NewRequest} =
stream(NewBody, Request, Code),
handle_response(State#state{headers = NewHeaders,
body = NewBody2})
diff --git a/lib/inets/src/inets_app/Makefile b/lib/inets/src/inets_app/Makefile
index 5d3f652441..926585f198 100644
--- a/lib/inets/src/inets_app/Makefile
+++ b/lib/inets/src/inets_app/Makefile
@@ -48,7 +48,8 @@ MODULES = \
inets_sup \
inets_regexp \
inets_trace \
- inets_lib
+ inets_lib \
+ inets_time_compat
INTERNAL_HRL_FILES = inets_internal.hrl
EXTERNAL_HRL_FILES = ../../include/httpd.hrl \
diff --git a/lib/inets/src/inets_app/inets.app.src b/lib/inets/src/inets_app/inets.app.src
index 01d4cefc55..7207672b7f 100644
--- a/lib/inets/src/inets_app/inets.app.src
+++ b/lib/inets/src/inets_app/inets.app.src
@@ -28,6 +28,7 @@
inets_regexp,
inets_trace,
inets_lib,
+ inets_time_compat,
%% FTP
ftp,
diff --git a/lib/inets/src/inets_app/inets_lib.erl b/lib/inets/src/inets_app/inets_lib.erl
index 11d3bac6bb..e79959f678 100644
--- a/lib/inets/src/inets_app/inets_lib.erl
+++ b/lib/inets/src/inets_app/inets_lib.erl
@@ -18,7 +18,6 @@
%%
-module(inets_lib).
--compile([{nowarn_deprecated_function,{erlang,now,0}}]).
-export([millisec_passed/1, formated_timestamp/0, format_timestamp/1]).
@@ -27,7 +26,7 @@
%% Help function, elapsed milliseconds since T0
millisec_passed({_,_,_} = T0 ) ->
%% OTP 17 and earlier
- timer:now_diff(erlang:now(), T0) div 1000;
+ timer:now_diff(inets_time_compat:monotonic_time(), T0) div 1000;
millisec_passed(T0) ->
%% OTP 18
diff --git a/lib/inets/src/inets_app/inets_time_compat.erl b/lib/inets/src/inets_app/inets_time_compat.erl
new file mode 100644
index 0000000000..d6297d9caf
--- /dev/null
+++ b/lib/inets/src/inets_app/inets_time_compat.erl
@@ -0,0 +1,71 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2015-2015. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%% This module is created to be able to execute on ERTS versions both
+%% earlier and later than 7.0.
+
+-module(inets_time_compat).
+
+%% We don't want warnings about the use of erlang:now/0 in
+%% this module.
+-compile(nowarn_deprecated_function).
+
+-export([monotonic_time/0,
+ timestamp/0,
+ unique_integer/0,
+ unique_integer/1]).
+
+monotonic_time() ->
+ try
+ erlang:monotonic_time()
+ catch
+ error:undef ->
+ %% Use Erlang system time as monotonic time
+ erlang_system_time_fallback()
+ end.
+
+timestamp() ->
+ try
+ erlang:timestamp()
+ catch
+ error:undef ->
+ erlang:now()
+ end.
+
+unique_integer() ->
+ try
+ erlang:unique_integer()
+ catch
+ error:undef ->
+ erlang_system_time_fallback()
+ end.
+
+unique_integer(Modifiers) ->
+ try
+ erlang:unique_integer(Modifiers)
+ catch
+ error:badarg ->
+ erlang:error(badarg, [Modifiers]);
+ error:undef ->
+ erlang_system_time_fallback()
+ end.
+
+erlang_system_time_fallback() ->
+ {MS, S, US} = erlang:now(),
+ (MS*1000000+S)*1000000+US.
diff --git a/lib/inets/src/tftp/tftp_logger.erl b/lib/inets/src/tftp/tftp_logger.erl
index 104d6a91c6..231a705371 100644
--- a/lib/inets/src/tftp/tftp_logger.erl
+++ b/lib/inets/src/tftp/tftp_logger.erl
@@ -18,7 +18,6 @@
%%
%%
-module(tftp_logger).
--compile([{nowarn_deprecated_function,{erlang,now,0}}]).
%%-------------------------------------------------------------------
%% Interface
@@ -85,14 +84,8 @@ info_msg(Format, Data) ->
%%-------------------------------------------------------------------
add_timestamp(Format, Data) ->
- %% Adapt to new OTP 18 erlang time API and be backwards compatible
- Now = try
- erlang:timestamp()
- catch
- error:undef ->
- erlang:now()
- end,
- {{_Y, _Mo, _D}, {H, Mi, S}} = calendar:now_to_universal_time(Now),
+ Time = inets_time_compat:timestamp(),
+ {{_Y, _Mo, _D}, {H, Mi, S}} = calendar:now_to_universal_time(Time),
%% {"~p-~s-~sT~s:~s:~sZ,~6.6.0w tftp: " ++ Format ++ "\n",
%% [Y, t(Mo), t(D), t(H), t(Mi), t(S), MicroSecs | Data]}.
{"~s:~s:~s tftp: " ++ Format, [t(H), t(Mi), t(S) | Data]}.
diff --git a/lib/inets/src/tftp/tftp_sup.erl b/lib/inets/src/tftp/tftp_sup.erl
index 3065279515..7a0dcffc90 100644
--- a/lib/inets/src/tftp/tftp_sup.erl
+++ b/lib/inets/src/tftp/tftp_sup.erl
@@ -22,7 +22,6 @@
%%----------------------------------------------------------------------
-module(tftp_sup).
--compile([{nowarn_deprecated_function,{erlang,now,0}}]).
-behaviour(supervisor).
@@ -94,17 +93,7 @@ unique_name(Options) ->
{value, {_, Port}} when is_integer(Port), Port > 0 ->
{tftpd, Port};
_ ->
- {tftpd, unique_integer()}
- end.
-
-unique_integer() ->
- %% Adapt to OTP 18 erlang time API and be backwards compatible
- try
- erlang:unique_integer([positive])
- catch
- error:undef ->
- {MS, S, US} = erlang:now(),
- (MS*1000000+S)*1000000+US
+ {tftpd, inets_time_compat:unique_integer([positive])}
end.
default_kill_after() ->
diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl
index 5ae9eb736e..b637832101 100644
--- a/lib/inets/test/ftp_suite_lib.erl
+++ b/lib/inets/test/ftp_suite_lib.erl
@@ -29,7 +29,6 @@
% -export([init_per_testcase/2, end_per_testcase/2]).
-compile(export_all).
--compile([{nowarn_deprecated_function,{erlang,now,0}}]).
-record(progress, {
@@ -1353,15 +1352,9 @@ do_delete(Pid, Config) ->
ok.
do_mkdir(Pid) ->
- %% Adapt to OTP 18 erlang time API and be backwards compatible
- NewDir = try
- "earl_" ++ integer_to_list(erlang:unique_integer([positive]))
- catch
- error:undef ->
- {A, B, C} = erlang:now(),
- "nisse_" ++ integer_to_list(A) ++ "_" ++
- integer_to_list(B) ++ "_" ++ integer_to_list(C)
- end,
+ NewDir = "earl_" ++
+ integer_to_list(inets_time_compat:unique_integer([positive])),
+
ok = ftp:cd(Pid, "incoming"),
{ok, CurrDir} = ftp:pwd(Pid),
{error, efnamena} = ftp:mkdir(Pid, NewDir++"\r\nCWD ."),
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 2193588031..0dfc65e8f7 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -31,7 +31,6 @@
-include("httpc_internal.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
--compile([{nowarn_deprecated_function,{erlang,now,0}}]).
-define(URL_START, "http://").
-define(TLS_URL_START, "https://").
@@ -1934,14 +1933,8 @@ run_clients(NumClients, ServerPort, SeqNumServer) ->
wait4clients([], _Timeout) ->
ok;
wait4clients(Clients, Timeout) when Timeout > 0 ->
- %% Adapt to OTP 18 erlang time API and be backwards compatible
- Time = try
- erlang:monotonic_time()
- catch
- error:undef ->
- %% Use Erlang system time as monotonic time
- erlang:now()
- end,
+ Time = inets_time_compat:monotonic_time(),
+
receive
{'DOWN', _MRef, process, Pid, normal} ->
{value, {Id, _, _}} = lists:keysearch(Pid, 2, Clients),
@@ -2040,14 +2033,8 @@ parse_connection_type(Request) ->
end.
set_random_seed() ->
- %% Adapt to OTP 18 erlang time API and be backwards compatible
- Unique = try
- erlang:unique_integer()
- catch
- error:undef ->
- {MS, S, US} = erlang:now(),
- (MS*1000000+S)*1000000+US
- end,
+ Unique = inets_time_compat:unique_integer(),
+
A = erlang:phash2([make_ref(), self(), Unique]),
random:seed(A, A, A).
diff --git a/lib/inets/test/httpd_time_test.erl b/lib/inets/test/httpd_time_test.erl
index b3e6746a01..7dd61a5517 100644
--- a/lib/inets/test/httpd_time_test.erl
+++ b/lib/inets/test/httpd_time_test.erl
@@ -18,7 +18,6 @@
%%
%%
-module(httpd_time_test).
--compile([{nowarn_deprecated_function,{erlang,now,0}}]).
-export([t/3, t1/2, t2/2, t4/2]).
@@ -117,15 +116,7 @@ main(N, SocketType, Host, Port, Time)
loop(Pollers, Timeout) ->
d("loop -> entry when"
"~n Timeout: ~p", [Timeout]),
- %% Adapt to OTP 18 erlang time API and be backwards compatible
- Start = try
- erlang:monotonic_time(1000)
- catch
- error:undef ->
- %% Use Erlang system time as monotonic time
- {A,B,C} = erlang:now(),
- A*1000000000+B*1000+(C div 1000)
- end,
+ Start = inets_time_compat:monotonic_time(),
receive
{'EXIT', Pid, {poller_stat_failure, SocketType, Host, Port, Time, Reason}} ->
diff --git a/lib/ssh/src/ssh_info.erl b/lib/ssh/src/ssh_info.erl
index 9a91875894..eae9ded5c6 100644
--- a/lib/ssh/src/ssh_info.erl
+++ b/lib/ssh/src/ssh_info.erl
@@ -179,7 +179,7 @@ line(Len, Char) ->
datetime() ->
- {{YYYY,MM,DD}, {H,M,S}} = calendar:now_to_universal_time(now()),
+ {{YYYY,MM,DD}, {H,M,S}} = calendar:now_to_universal_time(erlang:timestamp()),
lists:flatten(io_lib:format('~4w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w UTC',[YYYY,MM,DD, H,M,S])).
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 48a6627e0f..4c5498dc0e 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -715,7 +715,7 @@ ssh_connect_arg4_timeout(_Config) ->
%% try to connect with a timeout, but "supervise" it
Client = spawn(fun() ->
- T0 = now(),
+ T0 = erlang:monotonic_time(),
Rc = ssh:connect("localhost",Port,[],Timeout),
ct:log("Client ssh:connect got ~p",[Rc]),
Parent ! {done,self(),Rc,T0}
@@ -724,7 +724,7 @@ ssh_connect_arg4_timeout(_Config) ->
%% Wait for client reaction on the connection try:
receive
{done, Client, {error,timeout}, T0} ->
- Msp = ms_passed(T0, now()),
+ Msp = ms_passed(T0),
exit(Server,hasta_la_vista___baby),
Low = 0.9*Timeout,
High = 1.1*Timeout,
@@ -748,12 +748,12 @@ ssh_connect_arg4_timeout(_Config) ->
{fail, "Didn't timeout"}
end.
-%% Help function
-%% N2-N1
-ms_passed(N1={_,_,M1}, N2={_,_,M2}) ->
- {0,{0,Min,Sec}} = calendar:time_difference(calendar:now_to_local_time(N1),
- calendar:now_to_local_time(N2)),
- 1000 * (Min*60 + Sec + (M2-M1)/1000000).
+%% Help function, elapsed milliseconds since T0
+ms_passed(T0) ->
+ %% OTP 18
+ erlang:convert_time_unit(erlang:monotonic_time() - T0,
+ native,
+ micro_seconds) / 1000.
%%--------------------------------------------------------------------
ssh_connect_negtimeout_parallel(Config) -> ssh_connect_negtimeout(Config,true).