From 1f1c7a90ff5bacf19f0437e6f54cfe97e2d25e97 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 22 Jun 2017 16:11:52 +0200 Subject: Fix statistics(wall_clock) and statistics(runtime) implementation --- erts/doc/src/erlang.xml | 3 +++ erts/emulator/beam/erl_bif_info.c | 26 +++++++++++++------- erts/emulator/beam/erl_time_sup.c | 50 ++++++++++++++++++++++----------------- erts/emulator/beam/erl_utils.h | 1 + erts/emulator/beam/sys.h | 8 +++---- 5 files changed, 53 insertions(+), 35 deletions(-) diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index c3b0bc0d74..24a091073d 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -6362,6 +6362,9 @@ lists:map(

This is the sum of the runtime for all threads in the Erlang runtime system and can therefore be greater than the wall clock time.

+

This value might wrap due to limitations in the + underlying functionality provided by the operating system + that is used.

Example:

 > statistics(runtime).
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 7bd45916f5..7791231d56 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -3468,24 +3468,32 @@ BIF_RETTYPE statistics_1(BIF_ALIST_1)
 	res = TUPLE2(hp, b1, b2); 
 	BIF_RET(res);
     } else if (BIF_ARG_1 == am_runtime) {
-	UWord u1, u2, dummy;
+	ErtsMonotonicTime u1, u2;
 	Eterm b1, b2;
-	elapsed_time_both(&u1,&dummy,&u2,&dummy);
-	b1 = erts_make_integer(u1,BIF_P);
-	b2 = erts_make_integer(u2,BIF_P);
-	hp = HAlloc(BIF_P,3);
+        Uint hsz;
+	elapsed_time_both(&u1, NULL, &u2, NULL);
+        hsz = 3; /* 2-tuple */
+        (void) erts_bld_monotonic_time(NULL, &hsz, u1);
+        (void) erts_bld_monotonic_time(NULL, &hsz, u2);
+	hp = HAlloc(BIF_P, hsz);
+        b1 = erts_bld_monotonic_time(&hp, NULL, u1);
+        b2 = erts_bld_monotonic_time(&hp, NULL, u2);
 	res = TUPLE2(hp, b1, b2);
 	BIF_RET(res);
     } else if (BIF_ARG_1 ==  am_run_queue) {
 	res = erts_run_queues_len(NULL, 1, 0);
 	BIF_RET(make_small(res));
     } else if (BIF_ARG_1 == am_wall_clock) {
-	UWord w1, w2;
+	ErtsMonotonicTime w1, w2;
 	Eterm b1, b2;
+        Uint hsz;
 	wall_clock_elapsed_time_both(&w1, &w2);
-	b1 = erts_make_integer((Uint) w1,BIF_P);
-	b2 = erts_make_integer((Uint) w2,BIF_P);
-	hp = HAlloc(BIF_P,3);
+        hsz = 3; /* 2-tuple */
+        (void) erts_bld_monotonic_time(NULL, &hsz, w1);
+        (void) erts_bld_monotonic_time(NULL, &hsz, w2);
+	hp = HAlloc(BIF_P, hsz);
+        b1 = erts_bld_monotonic_time(&hp, NULL, w1);
+        b2 = erts_bld_monotonic_time(&hp, NULL, w2);
 	res = TUPLE2(hp, b1, b2);
 	BIF_RET(res);
     } else if (BIF_ARG_1 == am_io) {
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index 6aa2a7500f..1ef8c1b73a 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -1289,56 +1289,62 @@ erts_finalize_time_offset(void)
 /* info functions */
 
 void 
-elapsed_time_both(UWord *ms_user, UWord *ms_sys, 
-		  UWord *ms_user_diff, UWord *ms_sys_diff)
+elapsed_time_both(ErtsMonotonicTime *ms_user, ErtsMonotonicTime *ms_sys, 
+		  ErtsMonotonicTime *ms_user_diff, ErtsMonotonicTime *ms_sys_diff)
 {
-    UWord prev_total_user, prev_total_sys;
-    UWord total_user, total_sys;
+    ErtsMonotonicTime prev_total_user, prev_total_sys;
+    ErtsMonotonicTime total_user, total_sys;
     SysTimes now;
 
     sys_times(&now);
-    total_user = (now.tms_utime * 1000) / SYS_CLK_TCK;
-    total_sys = (now.tms_stime * 1000) / SYS_CLK_TCK;
+    total_user = (ErtsMonotonicTime) ((now.tms_utime * 1000) / SYS_CLK_TCK);
+    total_sys = (ErtsMonotonicTime) ((now.tms_stime * 1000) / SYS_CLK_TCK);
 
     if (ms_user != NULL)
 	*ms_user = total_user;
     if (ms_sys != NULL)
 	*ms_sys = total_sys;
 
-    erts_smp_mtx_lock(&erts_timeofday_mtx);
+    if (ms_user_diff || ms_sys_diff) {
+        erts_smp_mtx_lock(&erts_timeofday_mtx);
     
-    prev_total_user = (t_start.tms_utime * 1000) / SYS_CLK_TCK;
-    prev_total_sys = (t_start.tms_stime * 1000) / SYS_CLK_TCK;
-    t_start = now;
+        prev_total_user = (ErtsMonotonicTime) ((t_start.tms_utime * 1000) / SYS_CLK_TCK);
+        prev_total_sys = (ErtsMonotonicTime) ((t_start.tms_stime * 1000) / SYS_CLK_TCK);
+        t_start = now;
     
-    erts_smp_mtx_unlock(&erts_timeofday_mtx);
+        erts_smp_mtx_unlock(&erts_timeofday_mtx);
 
-    if (ms_user_diff != NULL)
-	*ms_user_diff = total_user - prev_total_user;
+        if (ms_user_diff != NULL)
+            *ms_user_diff = total_user - prev_total_user;
 	  
-    if (ms_sys_diff != NULL)
-	*ms_sys_diff = total_sys - prev_total_sys;
+        if (ms_sys_diff != NULL)
+            *ms_sys_diff = total_sys - prev_total_sys;
+    }
 }
 
 
 /* wall clock routines */
 
 void 
-wall_clock_elapsed_time_both(UWord *ms_total, UWord *ms_diff)
+wall_clock_elapsed_time_both(ErtsMonotonicTime *ms_total, ErtsMonotonicTime *ms_diff)
 {
     ErtsMonotonicTime now, elapsed;
 
-    erts_smp_mtx_lock(&erts_timeofday_mtx);
-
     now = time_sup.r.o.get_time();
     update_last_mtime(NULL, now);
 
     elapsed = ERTS_MONOTONIC_TO_MSEC(now);
-    *ms_total = (UWord) elapsed;
-    *ms_diff = (UWord) (elapsed - prev_wall_clock_elapsed);
-    prev_wall_clock_elapsed = elapsed;
 
-    erts_smp_mtx_unlock(&erts_timeofday_mtx);
+    *ms_total = elapsed;
+
+    if (ms_diff) {
+        erts_smp_mtx_lock(&erts_timeofday_mtx);
+
+        *ms_diff = elapsed - prev_wall_clock_elapsed;
+        prev_wall_clock_elapsed = elapsed;
+
+        erts_smp_mtx_unlock(&erts_timeofday_mtx);
+    }
 }
 
 /* get current time */
diff --git a/erts/emulator/beam/erl_utils.h b/erts/emulator/beam/erl_utils.h
index 81800752f0..b0912a346d 100644
--- a/erts/emulator/beam/erl_utils.h
+++ b/erts/emulator/beam/erl_utils.h
@@ -132,6 +132,7 @@ Eterm erts_bld_uint(Uint **hpp, Uint *szp, Uint ui);
 Eterm erts_bld_uword(Uint **hpp, Uint *szp, UWord uw);
 Eterm erts_bld_uint64(Uint **hpp, Uint *szp, Uint64 ui64);
 Eterm erts_bld_sint64(Uint **hpp, Uint *szp, Sint64 si64);
+#define erts_bld_monotonic_time erts_bld_sint64
 Eterm erts_bld_cons(Uint **hpp, Uint *szp, Eterm car, Eterm cdr);
 Eterm erts_bld_tuple(Uint **hpp, Uint *szp, Uint arity, ...);
 #define erts_bld_tuple2(H,S,E1,E2) erts_bld_tuple(H,S,2,E1,E2)
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index dd4f05686b..950583bbfa 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -790,10 +790,10 @@ Preload* sys_preloaded(void);
 unsigned char* sys_preload_begin(Preload*);
 void sys_preload_end(Preload*);
 int sys_get_key(int);
-void elapsed_time_both(UWord *ms_user, UWord *ms_sys, 
-		       UWord *ms_user_diff, UWord *ms_sys_diff);
-void wall_clock_elapsed_time_both(UWord *ms_total, 
-				  UWord *ms_diff);
+void elapsed_time_both(ErtsMonotonicTime *ms_user, ErtsMonotonicTime *ms_sys, 
+		       ErtsMonotonicTime *ms_user_diff, ErtsMonotonicTime *ms_sys_diff);
+void wall_clock_elapsed_time_both(ErtsMonotonicTime *ms_total, 
+				  ErtsMonotonicTime *ms_diff);
 void get_time(int *hour, int *minute, int *second);
 void get_date(int *year, int *month, int *day);
 void get_localtime(int *year, int *month, int *day, 
-- 
cgit v1.2.3