Index: libc/sysdeps/unix/sysv/linux/clock_gettime.c =================================================================== --- libc.orig/sysdeps/unix/sysv/linux/clock_gettime.c 2004-09-28 15:22:02.359949008 -0700 +++ libc/sysdeps/unix/sysv/linux/clock_gettime.c 2004-10-01 08:57:51.025894976 -0700 @@ -16,61 +16,174 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include +#include +#include +#include +#include #include +#include #include "kernel-features.h" #ifdef __ASSUME_POSIX_TIMERS -/* This means the REALTIME and MONOTONIC clock are definitely - supported in the kernel. */ -# define SYSDEP_GETTIME \ - case CLOCK_REALTIME: \ - case CLOCK_MONOTONIC: \ - retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \ - break -#elif defined __NR_clock_gettime -/* Is the syscall known to exist? */ -int __libc_missing_posix_timers attribute_hidden; - -/* The REALTIME and MONOTONIC clock might be available. Try the - syscall first. */ -# define SYSDEP_GETTIME \ - case CLOCK_REALTIME: \ - case CLOCK_MONOTONIC: \ - { \ - int e = EINVAL; \ - \ - if (!__libc_missing_posix_timers) \ - { \ - INTERNAL_SYSCALL_DECL (err); \ - int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); \ - if (!INTERNAL_SYSCALL_ERROR_P (r, err)) \ - { \ - retval = 0; \ - break; \ - } \ - \ - e = INTERNAL_SYSCALL_ERRNO (r, err); \ - if (e == ENOSYS) \ - { \ - __libc_missing_posix_timers = 1; \ - e = EINVAL; \ - } \ - } \ - \ - /* Fallback code. */ \ - if (e == EINVAL && clock_id == CLOCK_REALTIME) \ - HANDLE_REALTIME; \ - else \ - __set_errno (e); \ - } \ - break +/* This means all clocks are definitely supported in the kernel. */ +int +clock_gettime (clockid_t clock_id, struct timespec *tp) +{ + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + return 0; + return -1; +} + +#else + +/* + * Need to deal with multiple complex fallback and legacy scenarios + * + * Give priority to the clock_gettime syscall but fall back if + * certain clocks are not available + * for CLOCK_REALTIME fall back to gettimeofday + * for CLOCK_PROCESS_CPUTIME_ID fall back to HP_TIMING + * for CLOCK_THREAD_CPUTIME_ID fall back to pthreads + */ + +int __libc_missing_posix_stdtimers attribute_hidden; +int __libc_missing_posix_cputimers attribute_hidden; + +int +clock_gettime (clockid_t clock_id, struct timespec *tp) +{ + int retval = -1; + + switch (clock_id) + { +#if defined __NR_clock_gettime + case CLOCK_REALTIME: case CLOCK_MONOTONIC: + { + int e = EINVAL; + + if (!__libc_missing_posix_stdtimers) + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + { + retval = 0; + break; + } + + e = INTERNAL_SYSCALL_ERRNO (r, err); + if (e == ENOSYS) + { + __libc_missing_posix_stdtimers = 1; + e = EINVAL; + } + } + + /* Fallback code. */ + if (e != EINVAL || clock_id != CLOCK_REALTIME) + { + __set_errno (e); + break; + } + } + /* Fall through */ +#else + case CLOCK_REALTIME: #endif + struct timeval tv; + retval = gettimeofday (&tv, NULL); + if (retval == 0) + /* Convert into `timespec'. */ + TIMEVAL_TO_TIMESPEC (&tv, tp); + break; + + case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: +#if defined __NR_clock_gettime + if (!__libc_missing_posix_cputimers) + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + { + retval = 0; + break; + } + + if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS) + __libc_missing_posix_cputimers = 1; + } + +#if HP_TIMING_AVAIL + /* Fallback code. */ + { +/* Clock frequency of the processor. We make it a 64-bit variable + because some jokers are already playing with processors with more + than 4GHz. */ +static hp_timing_t freq; + + +/* This function is defined in the thread library. */ +extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq, + struct timespec *tp) + __attribute__ ((__weak__)); + + hp_timing_t tsc; + + if (__builtin_expect (freq == 0, 0)) + { + /* This can only happen if we haven't initialized the `freq' + variable yet. Do this now. We don't have to protect this + code against multiple execution since all of them should + lead to the same result. */ + freq = __get_clockfreq (); + if (__builtin_expect (freq == 0, 0)) + /* Something went wrong. */ + break; + } + + if (clock_id != CLOCK_PROCESS_CPUTIME_ID + && __pthread_clock_gettime != NULL) + { + retval = __pthread_clock_gettime (clock_id, freq, tp); + break; + } + + /* Get the current counter. */ + HP_TIMING_NOW (tsc); + + /* Compute the offset since the start time of the process. */ + tsc -= GL(dl_cpuclock_offset); + + /* Compute the seconds. */ + tp->tv_sec = tsc / freq; + + /* And the nanoseconds. This computation should be stable until + we get machines with about 16GHz frequency. */ + tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq; + + retval = 0; + } +#endif +#endif + break; + + default: +#if defined __NR_clock_gettime + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + retval = 0; +#else + __set_errno(EINVAL); +#endif + } + return retval; +} -#ifdef __NR_clock_gettime -/* We handled the REALTIME clock here. */ -# define HANDLED_REALTIME 1 #endif -#include Index: libc/sysdeps/unix/sysv/linux/clock_settime.c =================================================================== --- libc.orig/sysdeps/unix/sysv/linux/clock_settime.c 2004-10-01 10:27:15.007445832 -0700 +++ libc/sysdeps/unix/sysv/linux/clock_settime.c 2004-10-01 11:09:40.938405496 -0700 @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 1999,2000,2001,2002,2003,2004 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 @@ -16,61 +16,160 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include - +#include +#include +#include +#include +#include #include "kernel-features.h" - #ifdef __ASSUME_POSIX_TIMERS -/* This means the REALTIME clock is definitely supported in the - kernel. */ -# define SYSDEP_SETTIME \ - case CLOCK_REALTIME: \ - retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp); \ - break -#elif defined __NR_clock_settime -/* Is the syscall known to exist? */ -extern int __libc_missing_posix_timers attribute_hidden; - -/* The REALTIME clock might be available. Try the syscall first. */ -# define SYSDEP_SETTIME \ - case CLOCK_REALTIME: \ - { \ - int e = EINVAL; \ - \ - if (!__libc_missing_posix_timers) \ - { \ - INTERNAL_SYSCALL_DECL (err); \ - int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp); \ - if (!INTERNAL_SYSCALL_ERROR_P (r, err)) \ - { \ - retval = 0; \ - break; \ - } \ - \ - e = INTERNAL_SYSCALL_ERRNO (r, err); \ - if (e == ENOSYS) \ - { \ - __libc_missing_posix_timers = 1; \ - e = EINVAL; \ - } \ - } \ - \ - /* Fallback code. */ \ - if (e == EINVAL && clock_id == CLOCK_REALTIME) \ - HANDLE_REALTIME; \ - else \ - { \ - __set_errno (e); \ - retval = -1; \ - } \ - } \ - break +/* This means all clocks are definitely supported in the kernel. */ +int +clock_settime (clockid_t clock_id, struct timespec *tp) +{ + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + return 0; + return -1; +} + +#else +/* + * Need to deal with multiple complex fallback and legacy scenarios + * + * Give priority to the clock_gettime syscall but fall back if + * certain clocks are not available + * for CLOCK_REALTIME fall back to gettimeofday + * for CLOCK_PROCESS_CPUTIME_ID fall back to HP_TIMING + * for CLOCK_THREAD_CPUTIME_ID fall back to pthreads + */ + +int __libc_missing_posix_stdtimers attribute_hidden; +int __libc_missing_posix_cputimers attribute_hidden; + +int +clock_settime (clockid_t clock_id,const struct timespec *tp) +{ + int retval = -1; + + switch (clock_id) + { +#if defined __NR_clock_gettime + case CLOCK_REALTIME: case CLOCK_MONOTONIC: + { + int e = EINVAL; + + if (!__libc_missing_posix_stdtimers) + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + { + retval = 0; + break; + } + + e = INTERNAL_SYSCALL_ERRNO (r, err); + if (e == ENOSYS) + { + __libc_missing_posix_stdtimers = 1; + e = EINVAL; + } + } + + /* Fallback code. */ + if (e != EINVAL || clock_id != CLOCK_REALTIME) + { + __set_errno (e); + break; + } + } + /* Fall through */ +#else + case CLOCK_REALTIME: +#endif + struct timeval tv; + TIMESPEC_TO_TIMEVAL (&tv, tp); + retval = settimeofday (&tv, NULL); + break; + + case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: +#if defined __NR_clock_gettime + if (!__libc_missing_posix_cputimers) + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + { + retval = 0; + break; + } + + if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS) + __libc_missing_posix_cputimers = 1; + } + +#if HP_TIMING_AVAIL + /* Fallback code. */ + { +/* Clock frequency of the processor. We make it a 64-bit variable + because some jokers are already playing with processors with more + than 4GHz. */ +static hp_timing_t freq; + + +/* This function is defined in the thread library. */ +extern int __pthread_clock_settime (clockid_t clock_id, hp_timing_t offset) + __attribute__ ((__weak__)); + + hp_timing_t tsc; + hp_timing_t usertime; + + if (__builtin_expect (freq == 0, 0)) + { + /* This can only happen if we haven't initialized the `freq' + variable yet. Do this now. We don't have to protect this + code against multiple execution since all of them should + lead to the same result. */ + freq = __get_clockfreq (); + if (__builtin_expect (freq == 0, 0)) + /* Something went wrong. */ + break; + } + + /* Get the current counter. */ + HP_TIMING_NOW (tsc); + + /* Convert the user-provided time into CPU ticks. */ + usertime = tp->tv_sec * freq + (tp->tv_nsec * freq) / 1000000000ull; + + /* Determine the offset and use it as the new base value. */ + if (clock_id == CLOCK_PROCESS_CPUTIME_ID + || __pthread_clock_settime == NULL) + GL(dl_cpuclock_offset) = tsc - usertime; + else + __pthread_clock_settime (clock_id, tsc - usertime); + + retval = 0; + } +#endif +#endif + break; + + default: +#if defined __NR_clock_gettime + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + retval = 0; +#else + __set_errno(EINVAL); #endif + } + return retval; +} -#ifdef __NR_clock_settime -/* We handled the REALTIME clock here. */ -# define HANDLED_REALTIME 1 #endif -#include Index: libc/sysdeps/unix/sysv/linux/clock_getres.c =================================================================== --- libc.orig/sysdeps/unix/sysv/linux/clock_getres.c 2004-09-28 15:22:02.351950224 -0700 +++ libc/sysdeps/unix/sysv/linux/clock_getres.c 2004-10-01 12:23:50.099030272 -0700 @@ -16,61 +16,159 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include +#include +#include +#include +#include +#include #include +#include #include "kernel-features.h" #ifdef __ASSUME_POSIX_TIMERS -/* This means the REALTIME and MONOTONIC clock are definitely - supported in the kernel. */ -# define SYSDEP_GETRES \ - case CLOCK_REALTIME: \ - case CLOCK_MONOTONIC: \ - retval = INLINE_SYSCALL (clock_getres, 2, clock_id, res); \ - break -#elif defined __NR_clock_getres -/* Is the syscall known to exist? */ -extern int __libc_missing_posix_timers attribute_hidden; - -/* The REALTIME and MONOTONIC clock might be available. Try the - syscall first. */ -# define SYSDEP_GETRES \ - case CLOCK_REALTIME: \ - case CLOCK_MONOTONIC: \ - { \ - int e = EINVAL; \ - \ - if (!__libc_missing_posix_timers) \ - { \ - INTERNAL_SYSCALL_DECL (err); \ - int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res); \ - if (!INTERNAL_SYSCALL_ERROR_P (r, err)) \ - { \ - retval = 0; \ - break; \ - } \ - \ - e = INTERNAL_SYSCALL_ERRNO (r, err); \ - if (e == ENOSYS) \ - { \ - __libc_missing_posix_timers = 1; \ - e = EINVAL; \ - } \ - } \ - \ - /* Fallback code. */ \ - if (e == EINVAL && clock_id == CLOCK_REALTIME) \ - HANDLE_REALTIME; \ - else \ - __set_errno (e); \ - } \ - break +/* This means all clocks are definitely supported in the kernel. */ +int +clock_getres (clockid_t clock_id, struct timespec *res) +{ + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + return 0; + return -1; +} + +#else + +/* + * Need to deal with multiple complex fallback and legacy scenarios + * + * Give priority to the clock_gettime syscall but fall back if + * certain clocks are not available + * for CLOCK_REALTIME fall back to gettimeofday + * for CLOCK_PROCESS_CPUTIME_ID fall back to HP_TIMING + * for CLOCK_THREAD_CPUTIME_ID fall back to pthreads + */ + +int __libc_missing_posix_stdtimers attribute_hidden; +int __libc_missing_posix_cputimers attribute_hidden; + +int +clock_getres (clockid_t clock_id, struct timespec *res) +{ + int retval = -1; + + switch (clock_id) + { +#if defined __NR_clock_gettime + case CLOCK_REALTIME: case CLOCK_MONOTONIC: + { + int e = EINVAL; + + if (!__libc_missing_posix_stdtimers) + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + { + retval = 0; + break; + } + + e = INTERNAL_SYSCALL_ERRNO (r, err); + if (e == ENOSYS) + { + __libc_missing_posix_stdtimers = 1; + e = EINVAL; + } + } + + /* Fallback code. */ + if (e != EINVAL || clock_id != CLOCK_REALTIME) + { + __set_errno (e); + break; + } + } + /* Fall through */ +#else + case CLOCK_REALTIME: #endif + { + long int clk_tck = sysconf (_SC_CLK_TCK); + + if (__builtin_expect (clk_tck != -1, 1)) + { + /* This implementation assumes that the realtime clock has a + resolution higher than 1 second. This is the case for any + reasonable implementation. */ + res->tv_sec = 0; + res->tv_nsec = 1000000000 / clk_tck; + + retval = 0; + } + } + break; + + case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: +#if defined __NR_clock_gettime + if (!__libc_missing_posix_cputimers) + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + { + retval = 0; + break; + } + + if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS) + __libc_missing_posix_cputimers = 1; + } + +#if HP_TIMING_AVAIL + /* Fallback code. */ + static long int nsec; + { + if (__builtin_expect (nsec == 0, 0)) + { + hp_timing_t freq; + + /* This can only happen if we haven't initialized the `freq' + variable yet. Do this now. We don't have to protect this + code against multiple execution since all of them should + lead to the same result. */ + freq = __get_clockfreq (); + if (__builtin_expect (freq == 0, 0)) + /* Something went wrong. */ + break; + nsec = MAX (UINT64_C (1000000000) / freq, 1); + } + /* File in the values. The seconds are always zero (unless we + have a 1Hz machine). */ + res->tv_sec = 0; + res->tv_nsec = nsec; + + retval = 0; + } +#endif +#endif + break; + + default: +#if defined __NR_clock_gettime + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + retval = 0; +#else + __set_errno(EINVAL); +#endif + } + return retval; +} -#ifdef __NR_clock_getres -/* We handled the REALTIME clock here. */ -# define HANDLED_REALTIME 1 #endif -#include Index: libc/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c =================================================================== --- libc.orig/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c 2004-09-28 15:22:02.595913136 -0700 +++ /dev/null1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -/* Copyright (C) 2000, 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 - 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 -#include -#include -#include -#include -#include - - -int -clock_getcpuclockid (pid_t pid, clockid_t *clock_id) -{ - /* We don't allow any process ID but our own. */ - if (pid != 0 && pid != getpid ()) - return EPERM; - - static int itc_usable; - int retval = ENOENT; - - if (__builtin_expect (itc_usable == 0, 0)) - { - int newval = 1; - 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') - newval = -1; - - close (fd); - } - - itc_usable = newval; - } - - if (itc_usable > 0) - { - /* Store the number. */ - *clock_id = CLOCK_PROCESS_CPUTIME_ID; - retval = 0; - } - - return retval; -} Index: libc/sysdeps/unix/sysv/linux/clock_getcpuclockid.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ libc/sysdeps/unix/sysv/linux/clock_getcpuclockid.c 2004-10-05 10:54:25.029458864 -0700 @@ -0,0 +1,68 @@ +/* Copyright (C) 2000, 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 + 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 +#include +#include +#include +#include +#include + +#ifndef __ASSUME__POSIX_TIMERS +int __libc_missing_posix_cputimers attribute_hidden; +int __libc_missing_posix_tested attribute_hidden; +#endif + +int +clock_getcpuclockid (pid_t pid, clockid_t *clock_id) +{ +#ifndef __ASSUME__POSIX_TIMERS + int e = EINVAL; +#endif + /* We don't allow any process ID but our own. */ + if (pid != 0 && pid != getpid ()) + return EPERM; + +#ifndef __ASSUME__POSIX_TIMERS + if (!__libc_missing_posix_cputimers) + { + struct timespec tp; + + if (__libc_missing_posix_tested) goto nocputimer; + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_gettime, err, 2, CLOCK_PROCESS_CPUTIME_ID, &tp); + + __libc_missing_posix_tested = 1; + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + goto has_posix_timers; + + e = INTERNAL_SYSCALL_ERRNO (r, err); + if (e == ENOSYS) + { + __libc_missing_posix_cputimers = 1; + e = EINVAL; + } + } +nocputimer: + __set_errno (e); + return -1; +has_posix_timers: +#endif + + return CLOCK_PROCESS_CPUTIME_ID; +}