Replace FSF snail mail address with URLs.
[glibc.git] / sysdeps / unix / sysv / linux / clock_getres.c
blobe7e313854389493f037e61b0e8e23d71209f8f7f
1 /* clock_getres -- Get the resolution of a POSIX clockid_t. Linux version.
2 Copyright (C) 2003,2004,2005,2006,2008,2010 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #include <sysdep.h>
20 #include <errno.h>
21 #include <time.h>
22 #include "kernel-posix-cpu-timers.h"
23 #include <kernel-features.h>
25 #ifndef HAVE_CLOCK_GETRES_VSYSCALL
26 # undef INTERNAL_VSYSCALL
27 # define INTERNAL_VSYSCALL INTERNAL_SYSCALL
28 # undef INLINE_VSYSCALL
29 # define INLINE_VSYSCALL INLINE_SYSCALL
30 #else
31 # include <bits/libc-vdso.h>
32 #endif
34 #define SYSCALL_GETRES \
35 retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, res); \
36 break
38 #ifdef __ASSUME_POSIX_TIMERS
40 /* This means the REALTIME and MONOTONIC clock are definitely
41 supported in the kernel. */
42 # define SYSDEP_GETRES \
43 SYSDEP_GETRES_CPUTIME \
44 case CLOCK_REALTIME: \
45 case CLOCK_MONOTONIC: \
46 case CLOCK_MONOTONIC_RAW: \
47 case CLOCK_REALTIME_COARSE: \
48 case CLOCK_MONOTONIC_COARSE: \
49 SYSCALL_GETRES
51 # define __libc_missing_posix_timers 0
52 #elif defined __NR_clock_getres
53 /* Is the syscall known to exist? */
54 extern int __libc_missing_posix_timers attribute_hidden;
56 static inline int
57 maybe_syscall_getres (clockid_t clock_id, struct timespec *res)
59 int e = EINVAL;
61 if (!__libc_missing_posix_timers)
63 INTERNAL_SYSCALL_DECL (err);
64 int r = INTERNAL_VSYSCALL (clock_getres, err, 2, clock_id, res);
65 if (!INTERNAL_SYSCALL_ERROR_P (r, err))
66 return 0;
68 e = INTERNAL_SYSCALL_ERRNO (r, err);
69 if (e == ENOSYS)
71 __libc_missing_posix_timers = 1;
72 e = EINVAL;
76 return e;
79 /* The REALTIME and MONOTONIC clock might be available. Try the
80 syscall first. */
81 # define SYSDEP_GETRES \
82 SYSDEP_GETRES_CPUTIME \
83 case CLOCK_REALTIME: \
84 case CLOCK_MONOTONIC: \
85 case CLOCK_MONOTONIC_RAW: \
86 case CLOCK_REALTIME_COARSE: \
87 case CLOCK_MONOTONIC_COARSE: \
88 retval = maybe_syscall_getres (clock_id, res); \
89 if (retval == 0) \
90 break; \
91 /* Fallback code. */ \
92 if (retval == EINVAL && clock_id == CLOCK_REALTIME) \
93 retval = realtime_getres (res); \
94 else \
95 { \
96 __set_errno (retval); \
97 retval = -1; \
98 } \
99 break;
100 #endif
102 #ifdef __NR_clock_getres
103 /* We handled the REALTIME clock here. */
104 # define HANDLED_REALTIME 1
105 # define HANDLED_CPUTIME 1
107 # if __ASSUME_POSIX_CPU_TIMERS > 0
109 # define SYSDEP_GETRES_CPU SYSCALL_GETRES
110 # define SYSDEP_GETRES_CPUTIME /* Default catches them too. */
112 # else
114 extern int __libc_missing_posix_cpu_timers attribute_hidden;
116 static int
117 maybe_syscall_getres_cpu (clockid_t clock_id, struct timespec *res)
119 int e = EINVAL;
121 if (!__libc_missing_posix_cpu_timers)
123 INTERNAL_SYSCALL_DECL (err);
124 int r = INTERNAL_VSYSCALL (clock_getres, err, 2, clock_id, res);
125 if (!INTERNAL_SYSCALL_ERROR_P (r, err))
126 return 0;
128 e = INTERNAL_SYSCALL_ERRNO (r, err);
129 # ifndef __ASSUME_POSIX_TIMERS
130 if (e == ENOSYS)
132 __libc_missing_posix_timers = 1;
133 __libc_missing_posix_cpu_timers = 1;
134 e = EINVAL;
136 else
137 # endif
139 if (e == EINVAL)
141 /* Check whether the kernel supports CPU clocks at all.
142 If not, record it for the future. */
143 r = INTERNAL_VSYSCALL (clock_getres, err, 2,
144 MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
145 NULL);
146 if (INTERNAL_SYSCALL_ERROR_P (r, err))
147 __libc_missing_posix_cpu_timers = 1;
152 return e;
155 # define SYSDEP_GETRES_CPU \
156 retval = maybe_syscall_getres_cpu (clock_id, res); \
157 if (retval == 0) \
158 break; \
159 if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \
161 __set_errno (retval); \
162 retval = -1; \
163 break; \
165 retval = -1 /* Otherwise continue on to the HP_TIMING version. */;
167 static inline int
168 maybe_syscall_getres_cputime (clockid_t clock_id, struct timespec *res)
170 return maybe_syscall_getres_cpu
171 (clock_id == CLOCK_THREAD_CPUTIME_ID
172 ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED)
173 : MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
174 res);
177 # define SYSDEP_GETRES_CPUTIME \
178 case CLOCK_PROCESS_CPUTIME_ID: \
179 case CLOCK_THREAD_CPUTIME_ID: \
180 retval = maybe_syscall_getres_cputime (clock_id, res); \
181 if (retval == 0) \
182 break; \
183 if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \
185 __set_errno (retval); \
186 retval = -1; \
187 break; \
189 retval = hp_timing_getres (res); \
190 break;
191 # if !HP_TIMING_AVAIL
192 # define hp_timing_getres(res) (__set_errno (EINVAL), -1)
193 # endif
195 # endif
196 #endif
198 #include <sysdeps/posix/clock_getres.c>