lkml.org 
[lkml]   [2004]   [Oct]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectPosix compliant cpu clocks V6 [2/3]: Glibc patch
    The following patch makes glibc not provide the above clocks and use the
    kernel clocks instead if either of the following condition is met:

    1. __ASSUME_POSIX_TIMERS is set

    2. A call to probe the posix function is made if the corresponding
    __NR_clock_* is defined. If the call is successful then the kernel clocks
    will be used. Otherwise glibc will fall back to its own implementation of
    the clocks.

    The clock_gettime clock_settime and clock_res calls will use the corresponding
    system calls for other clocks than CLOCK_REALTIME, CLOCK_MONOTONIC,
    CLOCK_THREAD_CPUTIME_ID and CLOCK_PROCESS_CPUTIME_ID.

    Patch needs some additional testing....

    Signed-off-by: Christoph Lameter <clameter@sgi.com>

    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 <errno.h>
    +#include <stdint.h>
    +#include <time.h>
    +#include <sys/time.h>
    +#include <libc-internal.h>
    #include <sysdep.h>
    +#include <ldsodefs.h>

    #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 <sysdeps/unix/clock_gettime.c>
    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 <sysdep.h>
    -
    +#include <errno.h>
    +#include <time.h>
    +#include <sys/time.h>
    +#include <libc-internal.h>
    +#include <ldsodefs.h>
    #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 <sysdeps/unix/clock_settime.c>
    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 <errno.h>
    +#include <stdint.h>
    +#include <time.h>
    +#include <unistd.h>
    +#include <sys/time.h>
    +#include <libc-internal.h>
    #include <sysdep.h>
    +#include <ldsodefs.h>

    #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 <sysdeps/posix/clock_getres.c>
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-03-22 14:06    [W:0.051 / U:32.288 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site