Back to index

glibc  2.9
clock_getres.c
Go to the documentation of this file.
00001 /* clock_getres -- Get the resolution of a POSIX clockid_t.  Linux version.
00002    Copyright (C) 2003,2004,2005,2006, 2008 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <sysdep.h>
00021 #include <errno.h>
00022 #include <time.h>
00023 #include "kernel-posix-cpu-timers.h"
00024 #include <kernel-features.h>
00025 
00026 #ifndef HAVE_CLOCK_GETRES_VSYSCALL
00027 # undef INTERNAL_VSYSCALL
00028 # define INTERNAL_VSYSCALL INTERNAL_SYSCALL
00029 # undef INLINE_VSYSCALL
00030 # define INLINE_VSYSCALL INLINE_SYSCALL
00031 #else
00032 # include <bits/libc-vdso.h>
00033 #endif
00034 
00035 #define SYSCALL_GETRES \
00036   retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, res); \
00037   break
00038 
00039 #ifdef __ASSUME_POSIX_TIMERS
00040 
00041 /* This means the REALTIME and MONOTONIC clock are definitely
00042    supported in the kernel.  */
00043 # define SYSDEP_GETRES                                                      \
00044   SYSDEP_GETRES_CPUTIME                                                     \
00045   case CLOCK_REALTIME:                                                      \
00046   case CLOCK_MONOTONIC:                                                     \
00047     SYSCALL_GETRES
00048 
00049 # define __libc_missing_posix_timers 0
00050 #elif defined __NR_clock_getres
00051 /* Is the syscall known to exist?  */
00052 extern int __libc_missing_posix_timers attribute_hidden;
00053 
00054 static inline int
00055 maybe_syscall_getres (clockid_t clock_id, struct timespec *res)
00056 {
00057   int e = EINVAL;
00058 
00059   if (!__libc_missing_posix_timers)
00060     {
00061       INTERNAL_SYSCALL_DECL (err);
00062       int r = INTERNAL_VSYSCALL (clock_getres, err, 2, clock_id, res);
00063       if (!INTERNAL_SYSCALL_ERROR_P (r, err))
00064        return 0;
00065 
00066       e = INTERNAL_SYSCALL_ERRNO (r, err);
00067       if (e == ENOSYS)
00068        {
00069          __libc_missing_posix_timers = 1;
00070          e = EINVAL;
00071        }
00072     }
00073 
00074   return e;
00075 }
00076 
00077 /* The REALTIME and MONOTONIC clock might be available.  Try the
00078    syscall first.  */
00079 # define SYSDEP_GETRES                                                      \
00080   SYSDEP_GETRES_CPUTIME                                                     \
00081   case CLOCK_REALTIME:                                                      \
00082   case CLOCK_MONOTONIC:                                                     \
00083     retval = maybe_syscall_getres (clock_id, res);                          \
00084     if (retval == 0)                                                 \
00085       break;                                                         \
00086     /* Fallback code.  */                                            \
00087     if (retval == EINVAL && clock_id == CLOCK_REALTIME)                     \
00088       retval = realtime_getres (res);                                       \
00089     else                                                             \
00090       {                                                                     \
00091        __set_errno (retval);                                                \
00092        retval = -1;                                                  \
00093       }                                                                     \
00094     break;
00095 #endif
00096 
00097 #ifdef __NR_clock_getres
00098 /* We handled the REALTIME clock here.  */
00099 # define HANDLED_REALTIME   1
00100 # define HANDLED_CPUTIME    1
00101 
00102 # if __ASSUME_POSIX_CPU_TIMERS > 0
00103 
00104 #  define SYSDEP_GETRES_CPU SYSCALL_GETRES
00105 #  define SYSDEP_GETRES_CPUTIME    /* Default catches them too.  */
00106 
00107 # else
00108 
00109 extern int __libc_missing_posix_cpu_timers attribute_hidden;
00110 
00111 static int
00112 maybe_syscall_getres_cpu (clockid_t clock_id, struct timespec *res)
00113 {
00114   int e = EINVAL;
00115 
00116   if (!__libc_missing_posix_cpu_timers)
00117     {
00118       INTERNAL_SYSCALL_DECL (err);
00119       int r = INTERNAL_VSYSCALL (clock_getres, err, 2, clock_id, res);
00120       if (!INTERNAL_SYSCALL_ERROR_P (r, err))
00121        return 0;
00122 
00123       e = INTERNAL_SYSCALL_ERRNO (r, err);
00124 #  ifndef __ASSUME_POSIX_TIMERS
00125       if (e == ENOSYS)
00126        {
00127          __libc_missing_posix_timers = 1;
00128          __libc_missing_posix_cpu_timers = 1;
00129          e = EINVAL;
00130        }
00131       else
00132 #  endif
00133        {
00134          if (e == EINVAL)
00135            {
00136              /* Check whether the kernel supports CPU clocks at all.
00137                If not, record it for the future.  */
00138              r = INTERNAL_VSYSCALL (clock_getres, err, 2,
00139                                 MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
00140                                 NULL);
00141              if (INTERNAL_SYSCALL_ERROR_P (r, err))
00142               __libc_missing_posix_cpu_timers = 1;
00143            }
00144        }
00145     }
00146 
00147   return e;
00148 }
00149 
00150 #  define SYSDEP_GETRES_CPU                                          \
00151   retval = maybe_syscall_getres_cpu (clock_id, res);                        \
00152   if (retval == 0)                                                   \
00153     break;                                                           \
00154   if (retval != EINVAL || !__libc_missing_posix_cpu_timers)                 \
00155     {                                                                \
00156       __set_errno (retval);                                          \
00157       retval = -1;                                                   \
00158       break;                                                         \
00159     }                                                                \
00160   retval = -1 /* Otherwise continue on to the HP_TIMING version.  */;
00161 
00162 static inline int
00163 maybe_syscall_getres_cputime (clockid_t clock_id, struct timespec *res)
00164 {
00165   return maybe_syscall_getres_cpu
00166     (clock_id == CLOCK_THREAD_CPUTIME_ID
00167      ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED)
00168      : MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
00169      res);
00170 }
00171 
00172 #  define SYSDEP_GETRES_CPUTIME                                             \
00173     case CLOCK_PROCESS_CPUTIME_ID:                                   \
00174     case CLOCK_THREAD_CPUTIME_ID:                                    \
00175       retval = maybe_syscall_getres_cputime (clock_id, res);                \
00176       if (retval == 0)                                                      \
00177        break;                                                        \
00178       if (retval != EINVAL || !__libc_missing_posix_cpu_timers)                    \
00179        {                                                             \
00180          __set_errno (retval);                                              \
00181          retval = -1;                                                       \
00182          break;                                                      \
00183        }                                                             \
00184       retval = hp_timing_getres (res);                                      \
00185       break;
00186 #  if !HP_TIMING_AVAIL
00187 #   define hp_timing_getres(res) (__set_errno (EINVAL), -1)
00188 #  endif
00189 
00190 # endif
00191 #endif
00192 
00193 #include <sysdeps/posix/clock_getres.c>