From bbc16cb0e0f24eea7283ba99dadca78893e2b348 Mon Sep 17 00:00:00 2001
From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org>
Date: Tue, 29 Aug 2000 15:40:14 +0200
Subject: [PATCH] gethrtime for non-solaris x586 implemented [bug 101]

Rev: src/acconfig.h:1.65
Rev: src/backend.c:1.58
Rev: src/builtin_functions.c:1.306
Rev: src/configure.in:1.412
Rev: src/main.c:1.101
Rev: src/port.c:1.31
Rev: src/port.h:1.30
---
 src/acconfig.h          | 11 +++++-
 src/backend.c           |  8 ++++-
 src/builtin_functions.c | 11 ++++--
 src/configure.in        | 79 ++++++++++++++++++++++++++++++++++++++++-
 src/main.c              |  6 +++-
 src/port.c              | 67 +++++++++++++++++++++++++++++++++-
 src/port.h              | 10 +++++-
 7 files changed, 183 insertions(+), 9 deletions(-)

diff --git a/src/acconfig.h b/src/acconfig.h
index eb668abeb3..05b620e37d 100644
--- a/src/acconfig.h
+++ b/src/acconfig.h
@@ -1,5 +1,5 @@
 /*
- * $Id: acconfig.h,v 1.64 2000/08/29 12:37:46 grubba Exp $
+ * $Id: acconfig.h,v 1.65 2000/08/29 13:40:13 mirar Exp $
  */
 #ifndef MACHINE_H
 #define MACHINE_H
@@ -152,6 +152,15 @@
 /* Define if gettimeofday takes to arguments */
 #undef GETTIMEOFDAY_TAKES_TWO_ARGS
 
+/* Define if you have gethrtime */
+#undef HAVE_GETHRTIME
+
+/* Can we make our own gethrtime? */
+#undef OWN_GETHRTIME
+
+/* ... by using the RDTSC instruction? */
+#undef OWN_GETHRTIME_RDTSC
+
 /* Define if you have a working, 8-bit-clean memcmp */
 #undef HAVE_MEMCMP
 
diff --git a/src/backend.c b/src/backend.c
index f62507ecf1..d26611fcfb 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: backend.c,v 1.57 2000/08/28 16:23:59 grubba Exp $");
+RCSID("$Id: backend.c,v 1.58 2000/08/29 13:40:13 mirar Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include <errno.h>
@@ -723,7 +723,13 @@ void backend(void)
     if(d_flag > 1) do_debug();
 #endif
 
+#ifndef OWN_GETHRTIME
     GETTIMEOFDAY(&current_time);
+#else
+    /* good place to run the gethrtime-conversion update
+       since we have to run gettimeofday anyway /Mirar */
+    own_gethrtime_update(&current_time);
+#endif
 
     if(my_timercmp(&next_timeout, > , &current_time))
     {
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 592dfa0f81..f6cb28426e 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.305 2000/08/28 17:55:07 grubba Exp $");
+RCSID("$Id: builtin_functions.c,v 1.306 2000/08/29 13:40:13 mirar Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -4486,15 +4486,20 @@ PMOD_EXPORT void f_master(INT32 args)
   ref_push_object(master());
 }
 
-#ifdef HAVE_GETHRVTIME
+#ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
+#endif
+
+#ifdef HAVE_GETHRVTIME
 
 PMOD_EXPORT void f_gethrvtime(INT32 args)
 {
   pop_n_elems(args);
   push_int64(gethrvtime()/1000);
 }
+#endif
 
+#ifdef HAVE_GETHRTIME
 PMOD_EXPORT void f_gethrtime(INT32 args)
 {
   pop_n_elems(args);
@@ -4521,7 +4526,7 @@ PMOD_EXPORT void f_gethrtime(INT32 args)
     push_int64((tv.tv_sec * 1000000) + tv.tv_usec);
 #endif /* INT64 */
 }
-#endif /* HAVE_GETHRVTIME */
+#endif /* HAVE_GETHRTIME */
 
 #ifdef PROFILING
 static void f_get_prof_info(INT32 args)
diff --git a/src/configure.in b/src/configure.in
index f8ca3bed70..07b1445df6 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -1,4 +1,4 @@
-AC_REVISION("$Id: configure.in,v 1.411 2000/08/29 01:10:25 hubbe Exp $")
+AC_REVISION("$Id: configure.in,v 1.412 2000/08/29 13:40:13 mirar Exp $")
 AC_INIT(interpret.c)
 AC_CONFIG_HEADER(machine.h)
 
@@ -2161,6 +2161,83 @@ fi
 
 AC_MSG_RESULT($pike_cv_func_gettimeofday_has_two_args)
 
+if test "x$ac_cv_func_gethrtime" != "xyes"; then
+  AC_MSG_CHECKING(if we can make gethrtime by the RDTSC instruction)
+  AC_CACHE_VAL(pike_cv_own_gethrtime_rdtsc, [
+     AC_TRY_RUN([
+#include <unistd.h>
+#include <sys/time.h>
+
+static long long hrtime_rtsc_zero;
+static struct timeval hrtime_timeval_zero;
+static long double hrtime_conv=0.0;
+
+#define RTSC(x)   							\
+   __asm__ __volatile__ (  "rdtsc"                			\
+			   :"=a" (((unsigned long*)&x)[0]), 		\
+			   "=d" (((unsigned long*)&x)[1]))
+
+void own_gethrtime_init()
+{
+   RTSC(hrtime_rtsc_zero);
+   gettimeofday(&hrtime_timeval_zero,NULL);
+}
+
+void own_gethrtime_update(struct timeval *ptr)
+{
+   long long td,t,now;
+   RTSC(now);
+   gettimeofday(ptr,NULL);
+   td=((long long)ptr->tv_sec-hrtime_timeval_zero.tv_sec)*1000000000+
+      ((long long)ptr->tv_usec-hrtime_timeval_zero.tv_usec)*1000;
+   t=now-hrtime_rtsc_zero;
+   if (t) hrtime_conv=((long double)td)/t;
+}
+
+long long gethrtime()
+{
+   long long now;
+   struct timeval dummy;
+
+   if (hrtime_conv==0.0) own_gethrtime_update(&dummy);
+
+   RTSC(now);
+   return (long long) ( (long double)now * hrtime_conv );
+}
+
+int main()
+{
+   struct timeval tv1,tv2;
+   long long td,t2;
+   own_gethrtime_init();
+
+   gettimeofday(&tv1,NULL);
+   for (;;) /* busy loop */
+   {
+      gettimeofday(&tv2,NULL);
+      td=((long long)tv2.tv_sec-tv1.tv_sec)*1000000000+
+	 ((long long)tv2.tv_usec-tv1.tv_usec)*1000;
+      if (td>1000000) break;
+   }
+   t2=gethrtime();
+
+   if (t2!=hrtime_rtsc_zero) return 0;
+
+   return 1;
+}
+	],pike_cv_own_gethrtime_rdtsc=yes,
+	pike_cv_own_gethrtime_rdtsc=no)
+	])
+  if test "x$pike_cv_own_gethrtime_rdtsc" = "xyes"; then
+    AC_MSG_RESULT(yes)
+    AC_DEFINE(OWN_GETHRTIME)
+    AC_DEFINE(OWN_GETHRTIME_RDTSC)
+    AC_DEFINE(HAVE_GETHRTIME)
+  else 
+    AC_MSG_RESULT([no])
+  fi
+fi
+
 AC_MSG_CHECKING(if struct tm has tm_gmtoff)
 
 AC_CACHE_VAL(pike_cv_struct_tm_has_gmtoff,[
diff --git a/src/main.c b/src/main.c
index d974762cd7..2b089d50b5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: main.c,v 1.100 2000/08/24 04:04:41 hubbe Exp $");
+RCSID("$Id: main.c,v 1.101 2000/08/29 13:40:14 mirar Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include "module.h"
@@ -152,6 +152,10 @@ int dbm_main(int argc, char **argv)
 #ifdef TRY_USE_MMX
   try_use_mmx=mmx_ok();
 #endif
+#ifdef OWN_GETHRTIME
+/* initialize our own gethrtime conversion /Mirar */
+  own_gethrtime_init();
+#endif
 
   ARGV=argv;
 
diff --git a/src/port.c b/src/port.c
index 5505319961..7b30a68cee 100644
--- a/src/port.c
+++ b/src/port.c
@@ -18,7 +18,7 @@
 #include <float.h>
 #include <string.h>
 
-RCSID("$Id: port.c,v 1.30 2000/08/29 12:34:02 grubba Exp $");
+RCSID("$Id: port.c,v 1.31 2000/08/29 13:40:14 mirar Exp $");
 
 #ifdef sun
 time_t time PROT((time_t *));
@@ -638,3 +638,68 @@ PMOD_EXPORT INT32 EXTRACT_INT_(unsigned char *p)
   return a;
 }
 #endif
+
+#ifdef OWN_GETHRTIME
+
+#ifdef OWN_GETHRTIME_RDTSC
+
+static long long hrtime_rtsc_zero;
+static long long hrtime_rtsc_last;
+static struct timeval hrtime_timeval_zero;
+static long double hrtime_conv=0.0;
+
+#define RTSC(x)   							\
+   __asm__ __volatile__ (  "rdtsc"                			\
+			   :"=a" (((unsigned long*)&x)[0]), 		\
+			   "=d" (((unsigned long*)&x)[1]))
+
+void own_gethrtime_init()
+{
+   RTSC(hrtime_rtsc_zero);
+   hrtime_rtsc_last=hrtime_rtsc_zero;
+   GETTIMEOFDAY(&hrtime_timeval_zero);
+}
+
+void own_gethrtime_update(struct timeval *ptr)
+{
+   long long td,t,now;
+   RTSC(now);
+   GETTIMEOFDAY(ptr);
+   td=((long long)ptr->tv_sec-hrtime_timeval_zero.tv_sec)*1000000000+
+      ((long long)ptr->tv_usec-hrtime_timeval_zero.tv_usec)*1000;
+   hrtime_rtsc_last=now;
+   t=now-hrtime_rtsc_zero;
+   if (t) hrtime_conv=((long double)td)/t;
+
+/* fixme: add time deviation detection;
+   when time is adjusted, this calculation isn't linear anymore,
+   so it might be best to reset it */
+
+#if 0
+   fprintf(stderr,"conv=%.8llg MHz=%.8llg\n",hrtime_conv,1000.0/hrtime_conv);
+#endif
+}
+
+long long gethrtime()
+{
+   long long now;
+   struct timeval dummy;
+
+   if (hrtime_conv==0.0) own_gethrtime_update(&dummy);
+
+   RTSC(now);
+
+/* 2 seconds between updates */
+   if (now-hrtime_rtsc_last > 2000000000) 
+   {
+      fprintf(stderr,"update: %.8llg\n",1e-9*(now-hrtime_rtsc_last));
+      own_gethrtime_update(&dummy);
+      return gethrtime();
+   }
+
+   return (long long) ( (long double)now * hrtime_conv );
+}
+
+#endif
+
+#endif
diff --git a/src/port.h b/src/port.h
index 181f2cc847..e7ea1d38b8 100644
--- a/src/port.h
+++ b/src/port.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: port.h,v 1.29 2000/06/30 09:46:14 grubba Exp $
+ * $Id: port.h,v 1.30 2000/08/29 13:40:14 mirar Exp $
  */
 #ifndef PORT_H
 #define PORT_H
@@ -221,4 +221,12 @@ static INLINE INT32 EXTRACT_INT_(unsigned char *p)
 unsigned long my_rand(void);
 void my_srand(long seed);
 
+#ifdef OWN_GETHRTIME
+void own_gethrtime_init();
+void own_gethrtime_update(struct timeval *ptr);
+long long gethrtime();
+
+#define hrtime_t long long
+#endif
+
 #endif
-- 
GitLab