2015-08-31  Maria Guseva  <m.guseva@samsung.com>

	* elf/dl-support.c (HP_TIMING_AVAIL): Use instead of
	ifndef HP_TIMING_NONAVAIL.
	[HP_TIMING_AVAIL]: Time _dl_cpuclock_offset.
	* elf/rtld.c (HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL):
	Use instead of ifndef HP_TIMING_NONAVAIL.
	(DL_STATISTICS_TIMING_NOW): New macro to define timing
	in case of DL_DEBUG_STATISTICS set.
	(DL_STATISTICS_TIMING_DIFF): Likewise.
	(DL_STATISTICS_TIMING_ACCUM_NT): Likewise.
	[HP_TIMING_AVAIL]: Time dl_cpuclock_offset.
	(start): Initialize with 0 to prevent warnings.
	* sysdeps/generic/hp-timing-common.h (HP_TIMING_UNIT): New.
	Define to "cycles".
	(HP_TIMING_PRINT): Print HP_TIMING_UNIT instead of "cycles".
	* sysdeps/generic/hp-timing.h: Add include <stdint.h>, <sysdep.h>,
	<hp-timing-common.h>.
	(hp_timing_t): Typedef.
	(HP_GENERIC_TIMING_AVAIL): New. Define to 1.
	(HP_SMALL_TIMING_AVAIL): Define to 1.
	[!HAVE_CLOCK_GETTIME_VSYSCALL](__INTERNAL_SYSCALL): New.
	Define to INTERNAL_SYSCALL.
	[HAVE_CLOCK_GETTIME_VSYSCALL](__INTERNAL_SYSCALL): New.
	Define to INTERNAL_VSYSCALL.
	[__NR_clock_gettime] (HP_TIMING_NOW): Define using clock_gettime.
	[__NR_clock_gettime] (HP_TIMING_UNIT): Define to "nsec".
	[!__NR_clock_gettime]: Add include <sys/time.h>.
	[!__NR_clock_gettime] (HP_TIMING_NOW): Define using __gettimeofday.
	[!__NR_clock_gettime] (HP_TIMING_UNIT): Define to "usec".

 elf/dl-support.c                   |    4 +-
 elf/rtld.c                         |  109 ++++++++++++++++++++++--------------
 sysdeps/generic/hp-timing-common.h |    9 ++-
 sysdeps/generic/hp-timing.h        |   67 +++++++++++++++++-----
 5 files changed, 164 insertions(+), 57 deletions(-)

diff --git a/elf/dl-support.c b/elf/dl-support.c
index 4d036f1..802f328 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -130,7 +130,7 @@ void *_dl_random;
 #include <dl-procinfo.c>
 
 /* Initial value of the CPU clock.  */
-#ifndef HP_TIMING_NONAVAIL
+#if HP_TIMING_AVAIL
 hp_timing_t _dl_cpuclock_offset;
 #endif
 
@@ -309,8 +309,10 @@ _dl_non_dynamic_init (void)
   _dl_main_map.l_phdr = GL(dl_phdr);
   _dl_main_map.l_phnum = GL(dl_phnum);
 
+#if HP_TIMING_AVAIL
   if (HP_SMALL_TIMING_AVAIL)
     HP_TIMING_NOW (_dl_cpuclock_offset);
+#endif
 
   _dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
 
diff --git a/elf/rtld.c b/elf/rtld.c
index 69873c2..bb9db80 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -196,7 +196,7 @@ static struct libname_list _dl_rtld_libname;
 static struct libname_list _dl_rtld_libname2;
 
 /* Variable for statistics.  */
-#ifndef HP_TIMING_NONAVAIL
+#if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
 static hp_timing_t relocate_time;
 static hp_timing_t load_time attribute_relro;
 static hp_timing_t start_time attribute_relro;
@@ -228,7 +228,7 @@ static ElfW(Addr) _dl_start_final (void *arg);
 struct dl_start_final_info
 {
   struct link_map l;
-#if !defined HP_TIMING_NONAVAIL && HP_TIMING_INLINE
+#if (HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL) && HP_TIMING_INLINE
   hp_timing_t start_time;
 #endif
 };
@@ -241,6 +241,29 @@ extern char _begin[] attribute_hidden;
 extern char _etext[] attribute_hidden;
 extern char _end[] attribute_hidden;
 
+/* Macros to define timing in case of DL_DEBUG_STATISTICS set */
+# if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
+#define DL_STATISTICS_TIMING_NOW(tval) \
+if (__glibc_unlikely (HP_SMALL_TIMING_AVAIL &&                      \
+                      (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS))) \
+  HP_TIMING_NOW (tval)
+
+#define DL_STATISTICS_TIMING_DIFF(tdiff, tval1, tval2) \
+if (__glibc_unlikely (HP_SMALL_TIMING_AVAIL &&                      \
+                      (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS))) \
+  HP_TIMING_DIFF (tdiff, tval1, tval2)
+
+#define DL_STATISTICS_TIMING_ACCUM_NT(tsum, tval) \
+if (__glibc_unlikely (HP_SMALL_TIMING_AVAIL &&                       \
+                      (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS)))  \
+  HP_TIMING_ACCUM_NT (tsum, tval)
+
+# else
+#define DL_STATISTICS_TIMING_NOW(tval)
+#define DL_STATISTICS_TIMING_DIFF(tdiff, tval1, tval2)
+#define DL_STATISTICS_TIMING_ACCUM(tsum, tval)
+# endif
+
 
 #ifdef RTLD_START
 RTLD_START
@@ -296,7 +319,9 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
 # endif
 #endif
 
+#if HP_TIMING_AVAIL
   HP_TIMING_NOW (GL(dl_cpuclock_offset));
+#endif
 
   /* Initialize the stack end variable.  */
   __libc_stack_end = __builtin_frame_address (0);
@@ -307,23 +332,23 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
      entry point on the same stack we entered on.  */
   start_addr = _dl_sysdep_start (arg, &dl_main);
 
-#ifndef HP_TIMING_NONAVAIL
+#if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
   hp_timing_t rtld_total_time;
   if (HP_SMALL_TIMING_AVAIL)
     {
       hp_timing_t end_time;
 
       /* Get the current time.  */
-      HP_TIMING_NOW (end_time);
+      DL_STATISTICS_TIMING_NOW (end_time);
 
       /* Compute the difference.  */
-      HP_TIMING_DIFF (rtld_total_time, start_time, end_time);
+      DL_STATISTICS_TIMING_DIFF (rtld_total_time, start_time, end_time);
     }
 #endif
 
   if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS))
     {
-#ifndef HP_TIMING_NONAVAIL
+#if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
       print_statistics (&rtld_total_time);
 #else
       print_statistics (NULL);
@@ -351,12 +376,14 @@ _dl_start (void *arg)
 #define RESOLVE_MAP(sym, version, flags) (&bootstrap_map)
 #include "dynamic-link.h"
 
+#if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
   if (HP_TIMING_INLINE && HP_SMALL_TIMING_AVAIL)
 #ifdef DONT_USE_BOOTSTRAP_MAP
     HP_TIMING_NOW (start_time);
 #else
     HP_TIMING_NOW (info.start_time);
 #endif
+#endif
 
   /* Partly clean the `bootstrap_map' structure up.  Don't use
      `memset' since it might not be built in or inlined and we cannot
@@ -749,8 +776,8 @@ dl_main (const ElfW(Phdr) *phdr,
   unsigned int i;
   bool prelinked = false;
   bool rtld_is_main = false;
-#ifndef HP_TIMING_NONAVAIL
-  hp_timing_t start;
+#if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
+  hp_timing_t start = 0;
   hp_timing_t stop;
   hp_timing_t diff;
 #endif
@@ -926,12 +953,12 @@ of this helper program; chances are you did not intend to run this program.\n\
 	}
       else
 	{
-	  HP_TIMING_NOW (start);
+	  DL_STATISTICS_TIMING_NOW (start);
 	  _dl_map_object (NULL, rtld_progname, lt_executable, 0,
 			  __RTLD_OPENEXEC, LM_ID_BASE);
-	  HP_TIMING_NOW (stop);
+	  DL_STATISTICS_TIMING_NOW (stop);
 
-	  HP_TIMING_DIFF (load_time, start, stop);
+	  DL_STATISTICS_TIMING_DIFF (load_time, start, stop);
 	}
 
       /* Now the map for the main executable is available.  */
@@ -1493,7 +1520,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
       char *list = strdupa (preloadlist);
       char *p;
 
-      HP_TIMING_NOW (start);
+      DL_STATISTICS_TIMING_NOW (start);
 
       /* Prevent optimizing strsep.  Speed is not important here.  */
       while ((p = (strsep) (&list, " :")) != NULL)
@@ -1502,9 +1529,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 		|| strchr (p, '/') == NULL))
 	  npreloads += do_preload (p, main_map, "LD_PRELOAD");
 
-      HP_TIMING_NOW (stop);
-      HP_TIMING_DIFF (diff, start, stop);
-      HP_TIMING_ACCUM_NT (load_time, diff);
+      DL_STATISTICS_TIMING_NOW (stop);
+      DL_STATISTICS_TIMING_DIFF (diff, start, stop);
+      DL_STATISTICS_TIMING_ACCUM_NT (load_time, diff);
     }
 
   /* There usually is no ld.so.preload file, it should only be used
@@ -1564,7 +1591,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	      file[file_size - 1] = '\0';
 	    }
 
-	  HP_TIMING_NOW (start);
+	  DL_STATISTICS_TIMING_NOW (start);
 
 	  if (file != problem)
 	    {
@@ -1582,9 +1609,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	      npreloads += do_preload (p, main_map, preload_file);
 	    }
 
-	  HP_TIMING_NOW (stop);
-	  HP_TIMING_DIFF (diff, start, stop);
-	  HP_TIMING_ACCUM_NT (load_time, diff);
+	  DL_STATISTICS_TIMING_NOW (stop);
+	  DL_STATISTICS_TIMING_DIFF (diff, start, stop);
+	  DL_STATISTICS_TIMING_ACCUM_NT (load_time, diff);
 
 	  /* We don't need the file anymore.  */
 	  __munmap (file, file_size);
@@ -1608,11 +1635,11 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
   /* Load all the libraries specified by DT_NEEDED entries.  If LD_PRELOAD
      specified some libraries to load, these are inserted before the actual
      dependencies in the executable's searchlist for symbol resolution.  */
-  HP_TIMING_NOW (start);
+  DL_STATISTICS_TIMING_NOW (start);
   _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0);
-  HP_TIMING_NOW (stop);
-  HP_TIMING_DIFF (diff, start, stop);
-  HP_TIMING_ACCUM_NT (load_time, diff);
+  DL_STATISTICS_TIMING_NOW (stop);
+  DL_STATISTICS_TIMING_DIFF (diff, start, stop);
+  DL_STATISTICS_TIMING_ACCUM_NT (load_time, diff);
 
   /* Mark all objects as being in the global scope.  */
   for (i = main_map->l_searchlist.r_nlist; i > 0; )
@@ -2001,12 +2028,12 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
       if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL)
 	{
 	  ElfW(Rela) *conflict, *conflictend;
-#ifndef HP_TIMING_NONAVAIL
-	  hp_timing_t start;
+#if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
+	  hp_timing_t start = 0;
 	  hp_timing_t stop;
 #endif
 
-	  HP_TIMING_NOW (start);
+	  DL_STATISTICS_TIMING_NOW (start);
 	  assert (main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)] != NULL);
 	  conflict = (ElfW(Rela) *)
 	    main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)]->d_un.d_ptr;
@@ -2014,8 +2041,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	    ((char *) conflict
 	     + main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)]->d_un.d_val);
 	  _dl_resolve_conflicts (main_map, conflict, conflictend);
-	  HP_TIMING_NOW (stop);
-	  HP_TIMING_DIFF (relocate_time, start, stop);
+	  DL_STATISTICS_TIMING_NOW (stop);
+	  DL_STATISTICS_TIMING_DIFF (relocate_time, start, stop);
 	}
 
 
@@ -2043,15 +2070,15 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	 know that because it is self-contained).  */
 
       int consider_profiling = GLRO(dl_profile) != NULL;
-#ifndef HP_TIMING_NONAVAIL
-      hp_timing_t start;
+#if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
+      hp_timing_t start = 0;
       hp_timing_t stop;
 #endif
 
       /* If we are profiling we also must do lazy reloaction.  */
       GLRO(dl_lazy) |= consider_profiling;
 
-      HP_TIMING_NOW (start);
+      DL_STATISTICS_TIMING_NOW (start);
       unsigned i = main_map->l_searchlist.r_nlist;
       while (i-- > 0)
 	{
@@ -2078,9 +2105,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	  if (l->l_tls_blocksize != 0 && tls_init_tp_called)
 	    _dl_add_to_slotinfo (l);
 	}
-      HP_TIMING_NOW (stop);
+      DL_STATISTICS_TIMING_NOW (stop);
 
-      HP_TIMING_DIFF (relocate_time, start, stop);
+      DL_STATISTICS_TIMING_DIFF (relocate_time, start, stop);
 
       /* Now enable profiling if needed.  Like the previous call,
 	 this has to go here because the calls it makes should use the
@@ -2121,19 +2148,19 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	 re-relocation, we might call a user-supplied function
 	 (e.g. calloc from _dl_relocate_object) that uses TLS data.  */
 
-#ifndef HP_TIMING_NONAVAIL
-      hp_timing_t start;
+#if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
+      hp_timing_t start = 0;
       hp_timing_t stop;
       hp_timing_t add;
 #endif
 
-      HP_TIMING_NOW (start);
+      DL_STATISTICS_TIMING_NOW (start);
       /* Mark the link map as not yet relocated again.  */
       GL(dl_rtld_map).l_relocated = 0;
       _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
-      HP_TIMING_NOW (stop);
-      HP_TIMING_DIFF (add, start, stop);
-      HP_TIMING_ACCUM_NT (relocate_time, add);
+      DL_STATISTICS_TIMING_NOW (stop);
+      DL_STATISTICS_TIMING_DIFF (add, start, stop);
+      DL_STATISTICS_TIMING_ACCUM_NT (relocate_time, add);
     }
 
   /* Do any necessary cleanups for the startup OS interface code.
@@ -2575,7 +2602,7 @@ static void
 __attribute ((noinline))
 print_statistics (hp_timing_t *rtld_total_timep)
 {
-#ifndef HP_TIMING_NONAVAIL
+#if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
   char buf[200];
   char *cp;
   char *wp;
@@ -2647,7 +2674,7 @@ print_statistics (hp_timing_t *rtld_total_timep)
 		    GL(dl_num_cache_relocations),
 		    num_relative_relocations);
 
-#ifndef HP_TIMING_NONAVAIL
+#if HP_TIMING_AVAIL || HP_GENERIC_TIMING_AVAIL
   /* Time spend while loading the object and the dependencies.  */
   if (HP_SMALL_TIMING_AVAIL)
     {
diff --git a/sysdeps/generic/hp-timing-common.h b/sysdeps/generic/hp-timing-common.h
index 1e3e9b5..42b3baf 100644
--- a/sysdeps/generic/hp-timing-common.h
+++ b/sysdeps/generic/hp-timing-common.h
@@ -47,6 +47,11 @@
 /* Accumulate ADD into SUM.  No attempt is made to be thread-safe.  */
 #define HP_TIMING_ACCUM_NT(Sum, Diff)		((Sum) += (Diff))
 
+/* Define timing unit name to be printed, default is cycles */
+#ifndef HP_TIMING_UNIT
+#define HP_TIMING_UNIT "cycles"
+#endif
+
 /* Write a decimal representation of the timing value into the given string.  */
 #define HP_TIMING_PRINT(Dest, Len, Val) 				\
   do {									\
@@ -56,7 +61,7 @@
     char *__cp = _itoa ((Val), __buf + sizeof (__buf), 10, 0);		\
     size_t __cp_len = MIN (__buf + sizeof (__buf) - __cp, __len);	\
     memcpy (__dest, __cp, __cp_len);					\
-    memcpy (__dest + __cp_len, " cycles",				\
-	    MIN (__len - __cp_len, sizeof (" cycles")));		\
+    memcpy (__dest + __cp_len, " " HP_TIMING_UNIT,		\
+	    MIN (__len - __cp_len, sizeof (" " HP_TIMING_UNIT)));	\
     __dest[__len - 1] = '\0';						\
   } while (0)
diff --git a/sysdeps/generic/hp-timing.h b/sysdeps/generic/hp-timing.h
index 142fa62..458a021 100644
--- a/sysdeps/generic/hp-timing.h
+++ b/sysdeps/generic/hp-timing.h
@@ -20,21 +20,62 @@
 #ifndef _HP_TIMING_H
 #define _HP_TIMING_H	1
 
-/* There are no generic definitions for the times.  We could write something
-   using the `gettimeofday' system call where available but the overhead of
-   the system call might be too high.  */
+/* Generic definitions for the times using the `clock_gettime'
+   system or vdso call where available
+   or gettimeofday function call in  other cases. */
 
-/* Provide dummy definitions.  */
 #define HP_TIMING_AVAIL		(0)
-#define HP_SMALL_TIMING_AVAIL	(0)
+#define HP_GENERIC_TIMING_AVAIL	(1)
+#define HP_SMALL_TIMING_AVAIL	(1)
 #define HP_TIMING_INLINE	(0)
-typedef int hp_timing_t;
-#define HP_TIMING_NOW(var)
-#define HP_TIMING_DIFF(Diff, Start, End)
-#define HP_TIMING_ACCUM_NT(Sum, Diff)
-#define HP_TIMING_PRINT(Buf, Len, Val)
-
-/* Since this implementation is not available we tell the user about it.  */
-#define HP_TIMING_NONAVAIL	1
+
+/* Use 64bit values for the times in nano- or microseconds. */
+#include <stdint.h>
+typedef uint64_t hp_timing_t;
+
+/* Use vdso syscall where available */
+#include <sysdep.h>
+#ifndef HAVE_CLOCK_GETTIME_VSYSCALL
+# define __INTERNAL_SYSCALL INTERNAL_SYSCALL
+#else
+# include <sysdep-vdso.h>
+# define __INTERNAL_SYSCALL INTERNAL_VSYSCALL
+#endif
+
+# ifdef __NR_clock_gettime
+
+/* Use clockgettime where available */
+#define HP_TIMING_NOW(var)                                              \
+do                                                                      \
+  {                                                                     \
+    struct timespec __t;                                                \
+    INTERNAL_SYSCALL_DECL (__err);                                      \
+    __INTERNAL_SYSCALL (clock_gettime, __err, 2, CLOCK_MONOTONIC, &(__t));\
+    var = (uint64_t)__t.tv_nsec + (uint64_t)__t.tv_sec * 1000000000L;   \
+  }                                                                     \
+while (0)
+
+/* Define timing unit name to be printed */
+#define HP_TIMING_UNIT "nsec"
+
+# else
+
+/* Use gettimeofday function in other cases */
+#include <sys/time.h>
+#define HP_TIMING_NOW(var)                                              \
+do                                                                      \
+  {                                                                     \
+    struct timeval __t;                                                 \
+    (void) __gettimeofday (&__t, NULL)                                  \
+    var = (uint64_t)__t.tv_usec + (uint64_t)__t.tv_sec * 1000000L;      \
+  }                                                                     \
+while (0)
+
+/* Define timing unit name to be printed */
+#define HP_TIMING_UNIT "usec"
+
+# endif /* __NR_clock_gettime */
+
+#include <hp-timing-common.h>
 
 #endif	/* hp-timing.h */
-- 
1.7.9.5

