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


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

[Bug libc/220] New: IA64: return EINVAL if ITC is an unreliable time source on clock_gettime(CLOCK_PROCESS_TIMEID)


ITC on an IA64 may not be a reliable source of timing information if the CPUs in
an SMP system do not have synchronized ITC values. 

The clock_getcputimeid() function call returns ENOENT in cases where the ITC is
not reliable. However, the ITC is also the source for the CLOCK_PROCESS_TIMEID
and CLOCK_THREAD_TIMEID clocks. Applications may use this clock and fail because
the timers are not reliable when a process is migrated to a different cpu. The
patch below makes clock_gettime() also return NOENT in cases where ITC is
unreliable.

Index: glibc-2.3.2-200309260658/elf/rtld-Rules
===================================================================
--- glibc-2.3.2-200309260658.orig/elf/rtld-Rules	2003-07-24 20:31:13.000000000 -0700
+++ glibc-2.3.2-200309260658/elf/rtld-Rules	2004-06-03 18:46:55.000000000 -0700
@@ -31,7 +31,7 @@
 ifeq ($(subdir),elf)
 
 ifndef rtld-subdirs
-error This makefile is a subroutine of elf/Makefile not to be used directly
+$(error This makefile is a subroutine of elf/Makefile not to be used directly)
 endif
 
 include ../Makeconfig
Index: glibc-2.3.2-200309260658/sysdeps/ia64/Makefile
===================================================================
--- glibc-2.3.2-200309260658.orig/sysdeps/ia64/Makefile	2004-06-03
18:44:10.000000000 -0700
+++ glibc-2.3.2-200309260658/sysdeps/ia64/Makefile	2004-06-03 18:46:55.000000000
-0700
@@ -12,7 +12,7 @@
 
 ifeq (yes,$(build-shared))
 # Compatibility
-sysdep_routines += libgcc-compat
+sysdep_routines += libgcc-compat 
 shared-only-routines += libgcc-compat
 endif
 endif
@@ -21,4 +21,15 @@
 sysdep-dl-routines += dl-symaddr dl-fptr
 sysdep_routines += $(sysdep-dl-routines)
 sysdep-rtld-routines += $(sysdep-dl-routines)
+sysdep-dl-routines += hp-timing
 endif
+
+ifeq ($(subdir),posix)
+sysdep_routines += hp-timing
+endif
+
+ifeq ($(subdir),malloc)
+libmemusage-sysdep_routines += hp-timing
+endif
+
+
Index: glibc-2.3.2-200309260658/sysdeps/ia64/hp-timing.c
===================================================================
--- glibc-2.3.2-200309260658.orig/sysdeps/ia64/hp-timing.c	2002-01-31
23:48:41.000000000 -0800
+++ glibc-2.3.2-200309260658/sysdeps/ia64/hp-timing.c	2004-06-04
08:29:06.000000000 -0700
@@ -18,7 +18,61 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
 #include <hp-timing.h>
 
 /* We have to define the variable for the overhead.  */
 hp_timing_t _dl_hp_timing_overhead;
+
+static int freq;
+extern hp_timing_t __get_clockfreq (void);
+
+/* Values
+   itc_drifting ==-1 using ITC
+   itc_drifting == 1 using CLOCK_REALTIME
+   itc_drifting == 0 ITC drift status undetermined
+*/
+int itc_drifting=0;
+
+unsigned long int hp_gettimestamp(void)
+{
+	if (itc_drifting>0)
+get_realtimestamp:
+	{
+		struct timeval t;
+		unsigned long usecs;
+		
+		/* Make sure that CPU clock frequency has already been determined */
+		if (freq==0) 
+		{
+			freq=__get_clockfreq()/1000000UL;
+			if (freq==0) freq=10;
+		}
+		/* clock_gettime is not working in the elf loader... use gettimeofday */
+		__gettimeofday(&t,NULL);
+		usecs=t.tv_usec+t.tv_sec*1000000UL;
+		/* properly scale the microseconds according to the CPU clock rate */
+		return usecs*freq;
+	}
+	else
+	{
+		unsigned long x;
+
+		if (itc_is_drifting())
+		{
+			itc_drifting=1;
+			goto get_realtimestamp;
+		}
+		itc_drifting=-1;
+		HP_TIMING_NOW(x);
+		return x;
+	}
+}
+
Index: glibc-2.3.2-200309260658/sysdeps/ia64/hp-timing.h
===================================================================
--- glibc-2.3.2-200309260658.orig/sysdeps/ia64/hp-timing.h	2003-07-20
14:51:49.000000000 -0700
+++ glibc-2.3.2-200309260658/sysdeps/ia64/hp-timing.h	2004-06-03
18:46:55.000000000 -0700
@@ -72,11 +72,13 @@
 /* We always assume having the timestamp register.  */
 #define HP_TIMING_AVAIL		(1)
 
-/* We indeed have inlined functions.  */
-#define HP_TIMING_INLINE	(1)
+/* We indeed have inlined functions but sometimes we need to make a call.  */
+#define HP_TIMING_INLINE	(0)
 
 /* We use 64bit values for the times.  */
 typedef unsigned long int hp_timing_t;
+int itc_drifting;
+unsigned long hp_gettimestamp(void);
 
 /* Set timestamp value to zero.  */
 #define HP_TIMING_ZERO(Var)	(Var) = (0)
@@ -91,10 +93,13 @@
 /* That's quite simple.  Use the `ar.itc' instruction.  */
 #define HP_TIMING_NOW(Var) \
   ({ unsigned long int __itc;						      \
+    if (itc_drifting>=0) Var=hp_gettimestamp();				\
+    else {								\
      do									      \
        asm volatile ("mov %0=ar.itc" : "=r" (__itc) : : "memory");	      \
-     while (REPEAT_READ (__itc));					      \
-     Var = __itc; })
+      while (REPEAT_READ (__itc));					      \
+      Var = __itc; }							\
+   })
 
 /* Use two 'ar.itc' instructions in a row to find out how long it takes.  */
 #define HP_TIMING_DIFF_INIT() \
Index: glibc-2.3.2-200309260658/sysdeps/unix/sysv/linux/ia64/Makefile
===================================================================
--- glibc-2.3.2-200309260658.orig/sysdeps/unix/sysv/linux/ia64/Makefile
2003-06-02 12:56:22.000000000 -0700
+++ glibc-2.3.2-200309260658/sysdeps/unix/sysv/linux/ia64/Makefile	2004-06-03
18:46:55.000000000 -0700
@@ -7,6 +7,11 @@
 gen-as-const-headers += sigcontext-offsets.sym
 endif
 
+ifeq ($(subdir), csu)
+sysdep_routines += get_clockfreq
+static-only-routines += get_clockfreq
+endif
+
 ifeq ($(subdir),misc)
 sysdep_headers += sys/io.h
 sysdep_routines += ioperm clone2
@@ -16,6 +21,15 @@
 sysdep-dl-routines += dl-static
 sysdep_routines += $(sysdep-dl-routines)
 sysdep-rtld-routines += $(sysdep-dl-routines)
+sysdep-dl-routines += get_clockfreq
+endif
+
+ifeq ($(subdir),malloc)
+libmemusage-sysdep_routines += get_clockfreq
+endif
+
+ifeq ($(subdir),posix)
+sysdep_routines += get_clockfreq
 endif
 
 # This is a crude attempt to silence the compiler which complains about
Index: glibc-2.3.2-200309260658/sysdeps/unix/sysv/linux/ia64/hp-timing.c
===================================================================
--- glibc-2.3.2-200309260658.orig/sysdeps/unix/sysv/linux/ia64/hp-timing.c
1969-12-31 16:00:00.000000000 -0800
+++ glibc-2.3.2-200309260658/sysdeps/unix/sysv/linux/ia64/hp-timing.c	2004-06-03
18:46:55.000000000 -0700
@@ -0,0 +1,49 @@
+/* Support for high precision, low overhead timing functions.  IA-64 version.
+   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+int itc_is_drifting(void)
+{
+	int itc_drifting=0;
+
+	int fd = open ("/proc/sal/itc_drift", O_RDONLY);
+
+	if (__builtin_expect (fd != -1, 1))
+	{
+		char buf[16];
+		/* We expect the file to contain a single digit followed by
+		   a newline.  If the format changes we better not rely on
+		   the file content.  */
+		if (read (fd, buf, sizeof buf) != 2 || buf[0] != '0' || buf[1] != '\n')
+			itc_drifting=1;
+		close (fd);
+	}
+	return itc_drifting;
+}
+
+#include <sysdeps/ia64/hp-timing.c>
+

-- 
           Summary: IA64: return EINVAL if ITC is an unreliable time source
                    on clock_gettime(CLOCK_PROCESS_TIMEID)
           Product: glibc
           Version: 2.3.3
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: gotom at debian dot or dot jp
        ReportedBy: clameter at sgi dot com
                CC: glibc-bugs at sources dot redhat dot com
 GCC build triplet: ia64-redhat-linux
  GCC host triplet: ia64-redhat-linux
GCC target triplet: ia64-redhat-linux


http://sources.redhat.com/bugzilla/show_bug.cgi?id=220

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


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