Back to index

glibc  2.9
clock_settime.c
Go to the documentation of this file.
00001 /* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <errno.h>
00020 #include <sysdep.h>
00021 
00022 #include "kernel-posix-cpu-timers.h"
00023 #include <kernel-features.h>
00024 
00025 #ifndef HAVE_CLOCK_GETRES_VSYSCALL
00026 # undef INTERNAL_VSYSCALL
00027 # define INTERNAL_VSYSCALL INTERNAL_SYSCALL
00028 # undef INLINE_VSYSCALL
00029 # define INLINE_VSYSCALL INLINE_SYSCALL
00030 #else
00031 # include <bits/libc-vdso.h>
00032 #endif
00033 
00034 #if __ASSUME_POSIX_CPU_TIMERS <= 0 && defined __NR_clock_settime
00035 extern int __libc_missing_posix_timers attribute_hidden;
00036 extern int __libc_missing_posix_cpu_timers attribute_hidden;
00037 
00038 static int
00039 maybe_syscall_settime_cpu (clockid_t clock_id, const struct timespec *tp)
00040 {
00041   int e = EINVAL;
00042 
00043   if (!__libc_missing_posix_cpu_timers)
00044     {
00045       INTERNAL_SYSCALL_DECL (err);
00046       int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp);
00047       if (!INTERNAL_SYSCALL_ERROR_P (r, err))
00048         return 0;
00049 
00050       e = INTERNAL_SYSCALL_ERRNO (r, err);
00051 # ifndef __ASSUME_POSIX_TIMERS
00052       if (e == ENOSYS)
00053        {
00054          __libc_missing_posix_timers = 1;
00055          __libc_missing_posix_cpu_timers = 1;
00056          e = EINVAL;
00057        }
00058       else
00059 # endif
00060        {
00061          if (e == EINVAL)
00062            {
00063              /* Check whether the kernel supports CPU clocks at all.
00064                If not, record it for the future.  */
00065              r = INTERNAL_VSYSCALL (clock_getres, err, 2,
00066                                  MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
00067                                  NULL);
00068              if (INTERNAL_SYSCALL_ERROR_P (r, err))
00069               __libc_missing_posix_cpu_timers = 1;
00070            }
00071        }
00072     }
00073 
00074   return e;
00075 }
00076 #endif
00077 
00078 
00079 #ifdef __ASSUME_POSIX_TIMERS
00080 /* This means the REALTIME clock is definitely supported in the
00081    kernel.  */
00082 # define SYSDEP_SETTIME \
00083   case CLOCK_REALTIME:                                                      \
00084     retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp);               \
00085     break
00086 #elif defined __NR_clock_settime
00087 /* Is the syscall known to exist?  */
00088 extern int __libc_missing_posix_timers attribute_hidden;
00089 
00090 /* The REALTIME clock might be available.  Try the syscall first.  */
00091 # define SYSDEP_SETTIME \
00092   case CLOCK_REALTIME:                                                      \
00093     {                                                                \
00094       int e = EINVAL;                                                       \
00095                                                                      \
00096       if (!__libc_missing_posix_timers)                                     \
00097        {                                                             \
00098          INTERNAL_SYSCALL_DECL (err);                                       \
00099          int r = INTERNAL_SYSCALL (clock_settime, err, 2, clock_id, tp);     \
00100          if (!INTERNAL_SYSCALL_ERROR_P (r, err))                     \
00101            {                                                         \
00102              retval = 0;                                             \
00103              break;                                                  \
00104            }                                                         \
00105                                                                      \
00106          e = INTERNAL_SYSCALL_ERRNO (r, err);                               \
00107          if (e == ENOSYS)                                            \
00108            {                                                         \
00109              __libc_missing_posix_timers = 1;                               \
00110              e = EINVAL;                                             \
00111            }                                                         \
00112        }                                                             \
00113                                                                      \
00114       /* Fallback code.  */                                          \
00115       if (e == EINVAL && clock_id == CLOCK_REALTIME)                        \
00116        HANDLE_REALTIME;                                              \
00117       else                                                           \
00118        {                                                             \
00119          __set_errno (e);                                            \
00120          retval = -1;                                                       \
00121        }                                                             \
00122     }                                                                \
00123     break
00124 #endif
00125 
00126 #ifdef __NR_clock_settime
00127 /* We handled the REALTIME clock here.  */
00128 # define HANDLED_REALTIME   1
00129 #endif
00130 
00131 #if __ASSUME_POSIX_CPU_TIMERS > 0
00132 # define HANDLED_CPUTIME 1
00133 # define SYSDEP_SETTIME_CPU \
00134   retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp)
00135 #elif defined __NR_clock_settime
00136 # define SYSDEP_SETTIME_CPU \
00137   retval = maybe_syscall_settime_cpu (clock_id, tp);                        \
00138   if (retval == 0)                                                   \
00139     break;                                                           \
00140   if (retval != EINVAL || !__libc_missing_posix_cpu_timers)                 \
00141     {                                                                \
00142       __set_errno (retval);                                          \
00143       retval = -1;                                                   \
00144       break;                                                         \
00145     }                                                                \
00146   do { } while (0)
00147 #endif
00148 
00149 #include <sysdeps/unix/clock_settime.c>