LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File 0315-erts-Make-cpu_timestamp-use-per-thread-on-Linux.patch of Package erlang (Project home:Ledest:erlang:20)

From d5dc5584884488c8fcb5710997a14c2c418692f3 Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas@erlang.org>
Date: Tue, 15 May 2018 16:32:26 +0200
Subject: [PATCH] erts: Make cpu_timestamp use per thread on Linux

If we don't use per thread the value becomes completely
nonsensical on systems with more than one scheduler.
We keep the old solaris behaviour in order to support the
option, but it only really works when using a single
scheduler.
---
 erts/aclocal.m4                       |  8 ++++----
 erts/emulator/beam/erl_bif_trace.c    |  4 ++--
 erts/emulator/beam/erl_time_sup.c     |  2 +-
 erts/emulator/beam/erl_trace.c        | 14 --------------
 erts/emulator/sys/unix/erl_unix_sys.h | 10 ++++++----
 lib/tools/doc/src/fprof.xml           | 10 ++++++++--
 6 files changed, 21 insertions(+), 27 deletions(-)

diff --git a/erts/aclocal.m4 b/erts/aclocal.m4
index a4d09810bd..99b96eb5bc 100644
--- a/erts/aclocal.m4
+++ b/erts/aclocal.m4
@@ -2645,7 +2645,7 @@ case $erl_gethrvtime in
 	dnl Check if clock_gettime (linux) is working
 	dnl
 
-	AC_MSG_CHECKING([if clock_gettime can be used to get process CPU time])
+	AC_MSG_CHECKING([if clock_gettime can be used to get thread CPU time])
 	save_libs=$LIBS
 	LIBS="-lrt"
 	AC_TRY_RUN([
@@ -2659,11 +2659,11 @@ case $erl_gethrvtime in
 	    int i;
 	    struct timespec tp;
 
-	    if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp) < 0)
+	    if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp) < 0)
 	      exit(1);
 	    start = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
 	    for (i = 0; i < 100; i++)
-	      clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);
+	      clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp);
 	    stop = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec;
 	    if (start == 0)
 	      exit(4);
@@ -2686,7 +2686,7 @@ case $erl_gethrvtime in
 	case $erl_clock_gettime_cpu_time in
 		yes)
 			AC_DEFINE(HAVE_CLOCK_GETTIME_CPU_TIME,[],
-				  [define if clock_gettime() works for getting process time])
+				  [define if clock_gettime() works for getting thread time])
 			LIBRT=-lrt
 			;;
 		cross)
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 1953f79d79..fd3400ab71 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -643,12 +643,12 @@ Eterm erts_internal_trace_3(BIF_ALIST_3)
 			    SysTimespec tp;
 			    int i;
 			    
-			    if (sys_get_proc_cputime(start, tp) < 0)
+			    if (sys_get_cputime(start, tp) < 0)
 				goto error;
 			    start = ((SysCpuTime)tp.tv_sec * 1000000000LL) + 
 				    (SysCpuTime)tp.tv_nsec;
 			    for (i = 0; i < 100; i++)
-				sys_get_proc_cputime(stop, tp);
+				sys_get_cputime(stop, tp);
 			    stop = ((SysCpuTime)tp.tv_sec * 1000000000LL) + 
 				   (SysCpuTime)tp.tv_nsec;
 			    if (start == 0) goto error;
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index 4f91d9ad07..29c698e34f 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -1860,7 +1860,7 @@ void erts_get_now_cpu(Uint* megasec, Uint* sec, Uint* microsec) {
   SysCpuTime t;
   SysTimespec tp;
 
-  sys_get_proc_cputime(t, tp);
+  sys_get_cputime(t, tp);
   *microsec = (Uint)(tp.tv_nsec / 1000);
   t = (tp.tv_sec / 1000000);
   *megasec = (Uint)(t % 1000000);
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 065a560b52..e9a413904b 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -625,20 +625,6 @@ erts_get_system_profile(void) {
     return profile;
 }
 
-
-#ifdef HAVE_ERTS_NOW_CPU
-#  define GET_NOW(m, s, u) \
-do { \
-    if (erts_cpu_timestamp) \
-	erts_get_now_cpu(m, s, u); \
-    else \
-	get_now(m, s, u); \
-} while (0)
-#else
-#  define GET_NOW(m, s, u) do {get_now(m, s, u);} while (0)
-#endif
-
-
 static void
 write_sys_msg_to_port(Eterm unused_to,
 		      Port* trace_port,
diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h
index 10adf80875..5bfe5a8e2d 100644
--- a/erts/emulator/sys/unix/erl_unix_sys.h
+++ b/erts/emulator/sys/unix/erl_unix_sys.h
@@ -292,6 +292,8 @@ erts_sys_perf_counter()
 
 /*
  * Functions for measuring CPU time
+ *
+ * Note that gethrvtime is time per process and clock_gettime is per thread.
  */
 
 #if (defined(HAVE_GETHRVTIME) || defined(HAVE_CLOCK_GETTIME_CPU_TIME))
@@ -300,15 +302,15 @@ typedef struct timespec SysTimespec;
 
 #if defined(HAVE_GETHRVTIME)
 #define sys_gethrvtime() gethrvtime()
-#define sys_get_proc_cputime(t,tp) (t) = sys_gethrvtime(), \
-                                   (tp).tv_sec = (time_t)((t)/1000000000LL), \
-                                   (tp).tv_nsec = (long)((t)%1000000000LL)
+#define sys_get_cputime(t,tp) (t) = sys_gethrvtime(), \
+        (tp).tv_sec = (time_t)((t)/1000000000LL),     \
+        (tp).tv_nsec = (long)((t)%1000000000LL)
 int sys_start_hrvtime(void);
 int sys_stop_hrvtime(void);
 
 #elif defined(HAVE_CLOCK_GETTIME_CPU_TIME)
 #define sys_clock_gettime(cid,tp) clock_gettime((cid),&(tp))
-#define sys_get_proc_cputime(t,tp) sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID,(tp))
+#define sys_get_cputime(t,tp) sys_clock_gettime(CLOCK_THREAD_CPUTIME_ID,(tp))
 
 #endif
 #endif
diff --git a/lib/tools/doc/src/fprof.xml b/lib/tools/doc/src/fprof.xml
index 4c9e48045e..72624bd33b 100644
--- a/lib/tools/doc/src/fprof.xml
+++ b/lib/tools/doc/src/fprof.xml
@@ -328,10 +328,16 @@
            purposes. This option is only
            allowed with the <c>start</c> option.</item>
           <tag><c>cpu_time</c>| <c>{cpu_time, bool()}</c></tag>
-          <item>The options <c>cpu_time</c> or <c>{cpu_time, true></c>
+          <item>The options <c>cpu_time</c> or <c>{cpu_time, true}</c>
            makes the timestamps in the trace be in CPU time instead
            of wallclock time which is the default. This option is
-           only allowed with the <c>start</c> option.</item>
+           only allowed with the <c>start</c> option.
+           <warning><p>Getting correct values out of cpu_time can be difficult.
+           The best way to get correct values is to run using a single
+           scheduler and bind that scheduler to a specific CPU,
+           i.e. <c>erl +S 1 +sbt db</c>.</p>
+           </warning>
+          </item>
           <tag><c>{procs, PidSpec}</c>| <c>{procs, [PidSpec]}</c></tag>
           <item>Specifies which processes that shall be traced. If
            this option is not given, the calling process is
-- 
2.17.0