This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ia64 clock_gettime and HP_TIMING


Hi

I am looking at a problem with the current implementation of HP_TIMING
on ia64.

The problem is that HP_TIMING uses the ITC (similar to the x86 TSC)
which isn't synchronized across nodes, hence in a multi-node NUMA system
you can get the situation where HP_TIMING() goes backwards.

I fixed this for glibc-2.2 a while ago by making HP_TIMING() call
gettimeofday() which is fine (patch below) as with the fast system calls
on ia64 it's about 150 cycles.

Now my question is what one should do wrt clock_gettime(). The
implementation in CVS uses HP_TIMING() for CLOCK_PROCESS_CPUTIME_ID,
however I was curious if I could just switch that to calling
sys_clock_gettime() directly and then use gettimeofday() as a fall-back?

Any oppinions/suggestions?

Thanks,
Jes

2003-03-21  Jes Sorensen  <jes@wildopensource.com>

	* libc-2.3/sysdeps/ia64/hp-timing.h: Migrate HP_TIMING_NOW() to
	use gettimeofday(). Adjust HP_TIMING_PRINT() accordingly.
	* libc-2.3/sysdeps/unix/sysv/linux/ia64/get_clockfreq.c: Timing
	clock is now in micro seconds, independant of the CPU clock.

--- glibc-2.3.2-vanilla/sysdeps/ia64/hp-timing.h	Sat Aug 24 20:59:22 2002
+++ glibc-2.3.2/sysdeps/ia64/hp-timing.h	Tue Nov 11 07:36:23 2003
@@ -1,5 +1,5 @@
 /* High precision, low overhead timing functions.  IA-64 version.
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 2001.
 
@@ -25,6 +25,7 @@
 #include <sys/param.h>
 #include <stdio-common/_itoa.h>
 #include <ia64intrin.h>
+#include <sys/time.h>
 
 /* The macros defined here use the timestamp counter in IA-64.  They
    provide a very accurate way to measure the time with very little
@@ -88,15 +89,23 @@
    processor implementation.  */
 #define REPEAT_READ(val) __builtin_expect ((int) val == -1, 0)
 
-/* That's quite simple.  Use the `ar.itc' instruction.  */
-#define HP_TIMING_NOW(Var) \
-  ({ unsigned long int __itc;						      \
-     do									      \
-       asm volatile ("mov %0=ar.itc" : "=r" (__itc) : : "memory");	      \
-     while (REPEAT_READ (__itc));					      \
-     Var = __itc; })
+#define HP_TIMING_NOW(Var) (Var = __hp_timing_now())
 
-/* Use two 'ar.itc' instructions in a row to find out how long it takes.  */
+static inline hp_timing_t
+__hp_timing_now(void)
+{
+  hp_timing_t val = 0;
+  struct timeval tv;
+  int status;
+
+  status = gettimeofday (&tv, NULL);
+  if (!status)
+    val = (hp_timing_t) tv.tv_usec;
+
+  return (hp_timing_t) val;
+}
+
+/* Call twice in a row to find out how long it takes.  */
 #define HP_TIMING_DIFF_INIT() \
   do {									      \
     int __cnt = 5;							      \
@@ -141,8 +150,8 @@
     char *__dest = (Buf);						      \
     while (__len-- > 0 && __cp < __buf + sizeof (__buf))		      \
       *__dest++ = *__cp++;						      \
-    memcpy (__dest, " clock cycles", MIN (__len,			      \
-					  (int) sizeof (" clock cycles")));   \
+    memcpy (__dest, " micro seconds", MIN (__len,			      \
+					  (int) sizeof (" micro seconds")));  \
   } while (0)
 
 #endif	/* hp-timing.h */
--- glibc-2.3.2-vanilla/sysdeps/unix/sysv/linux/ia64/get_clockfreq.c	Sat Jul  7 12:21:34 2001
+++ glibc-2.3.2/sysdeps/unix/sysv/linux/ia64/get_clockfreq.c	Tue Nov 11 07:35:28 2003
@@ -1,5 +1,5 @@
 /* Get frequency of the system processor.  IA-64/Linux version.
-   Copyright (C) 2001 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -27,63 +27,5 @@
 hp_timing_t
 __get_clockfreq (void)
 {
-  /* We read the information from the /proc filesystem.  It contains at
-     least one line like
-	itc MHz    : 733.390988
-     We search for this line and convert the number in an integer.  */
-  static hp_timing_t result;
-  int fd;
-
-  /* If this function was called before, we know the result.  */
-  if (result != 0)
-    return result;
-
-  fd = open ("/proc/cpuinfo", O_RDONLY);
-  if (__builtin_expect (fd != -1, 1))
-    {
-      /* XXX AFAIK the /proc filesystem can generate "files" only up
-         to a size of 4096 bytes.  */
-      char buf[4096];
-      ssize_t n;
-
-      n = read (fd, buf, sizeof buf);
-      if (__builtin_expect (n, 1) > 0)
-	{
-	  char *mhz = memmem (buf, n, "itc MHz", 7);
-
-	  if (__builtin_expect (mhz != NULL, 1))
-	    {
-	      char *endp = buf + n;
-	      int seen_decpoint = 0;
-	      int ndigits = 0;
-
-	      /* Search for the beginning of the string.  */
-	      while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n')
-		++mhz;
-
-	      while (mhz < endp && *mhz != '\n')
-		{
-		  if (*mhz >= '0' && *mhz <= '9')
-		    {
-		      result *= 10;
-		      result += *mhz - '0';
-		      if (seen_decpoint)
-			++ndigits;
-		    }
-		  else if (*mhz == '.')
-		    seen_decpoint = 1;
-
-		  ++mhz;
-		}
-
-	      /* Compensate for missing digits at the end.  */
-	      while (ndigits++ < 6)
-		result *= 10;
-	    }
-	}
-
-      close (fd);
-    }
-
-  return result;
+  return (hp_timing_t) 1000000;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]