From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6267 invoked by alias); 12 Nov 2003 15:35:51 -0000 Mailing-List: contact libc-hacker-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sources.redhat.com Received: (qmail 6249 invoked from network); 12 Nov 2003 15:35:51 -0000 Received: from unknown (HELO jaguar.mkp.net) (192.139.46.146) by sources.redhat.com with SMTP; 12 Nov 2003 15:35:51 -0000 Received: from jes by jaguar.mkp.net with local (Exim 3.35 #1) id 1AJx25-0003mN-00 for libc-hacker@sources.redhat.com; Wed, 12 Nov 2003 10:35:49 -0500 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <16306.21333.78785.923547@gargle.gargle.HOWL> Date: Wed, 12 Nov 2003 15:35:00 -0000 To: libc-hacker@sources.redhat.com Subject: ia64 clock_gettime and HP_TIMING From: Jes Sorensen X-SW-Source: 2003-11/txt/msg00015.txt.bz2 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 * 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 , 2001. @@ -25,6 +25,7 @@ #include #include #include +#include /* 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; }