]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/clock_gettime.c
Replace FSF snail mail address with URLs.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / clock_gettime.c
CommitLineData
2f4f3bd4 1/* clock_gettime -- Get current time from a POSIX clockid_t. Linux version.
a77d3c17 2 Copyright (C) 2003,2004,2005,2006,2007,2010,2011 Free Software Foundation, Inc.
ad0e8eb0
UD
3 This file is part of the GNU C Library.
4
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.
9
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.
14
15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
ad0e8eb0
UD
18
19#include <sysdep.h>
2f4f3bd4 20#include <errno.h>
6ba85a6d 21#include <time.h>
2f4f3bd4 22#include "kernel-posix-cpu-timers.h"
6ddd37a4 23#include <kernel-features.h>
ad0e8eb0 24
8c2e201b
UD
25#ifndef HAVE_CLOCK_GETTIME_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
ad0e8eb0 33
a77d3c17
UD
34#ifndef SYSCALL_GETTIME
35# define SYSCALL_GETTIME(id, tp) \
36 INLINE_VSYSCALL (clock_gettime, 2, id, tp)
37#endif
38#ifndef INTERNAL_GETTIME
39# define INTERNAL_GETTIME(id, tp) \
40 INTERNAL_VSYSCALL (clock_gettime, err, 2, id, tp)
41#endif
2f4f3bd4 42
ad0e8eb0 43#ifdef __ASSUME_POSIX_TIMERS
2f4f3bd4 44
ad0e8eb0
UD
45/* This means the REALTIME and MONOTONIC clock are definitely
46 supported in the kernel. */
7edb22ef
UD
47# define SYSDEP_GETTIME \
48 SYSDEP_GETTIME_CPUTIME; \
ad0e8eb0
UD
49 case CLOCK_REALTIME: \
50 case CLOCK_MONOTONIC: \
a77d3c17
UD
51 retval = SYSCALL_GETTIME (clock_id, tp); \
52 break
2f4f3bd4
RM
53
54# define __libc_missing_posix_timers 0
ad0e8eb0
UD
55#elif defined __NR_clock_gettime
56/* Is the syscall known to exist? */
57int __libc_missing_posix_timers attribute_hidden;
58
2f4f3bd4
RM
59static inline int
60maybe_syscall_gettime (clockid_t clock_id, struct timespec *tp)
61{
62 int e = EINVAL;
63
64 if (!__libc_missing_posix_timers)
65 {
66 INTERNAL_SYSCALL_DECL (err);
a77d3c17 67 int r = INTERNAL_GETTIME (clock_id, tp);
2f4f3bd4
RM
68 if (!INTERNAL_SYSCALL_ERROR_P (r, err))
69 return 0;
70
71 e = INTERNAL_SYSCALL_ERRNO (r, err);
72 if (e == ENOSYS)
73 {
74 __libc_missing_posix_timers = 1;
75 e = EINVAL;
76 }
77 }
78
79 return e;
80}
81
ad0e8eb0
UD
82/* The REALTIME and MONOTONIC clock might be available. Try the
83 syscall first. */
7edb22ef
UD
84# define SYSDEP_GETTIME \
85 SYSDEP_GETTIME_CPUTIME; \
ad0e8eb0
UD
86 case CLOCK_REALTIME: \
87 case CLOCK_MONOTONIC: \
89a4419c
UD
88 case CLOCK_MONOTONIC_RAW: \
89 case CLOCK_REALTIME_COARSE: \
90 case CLOCK_MONOTONIC_COARSE: \
2f4f3bd4
RM
91 retval = maybe_syscall_gettime (clock_id, tp); \
92 if (retval == 0) \
93 break; \
94 /* Fallback code. */ \
95 if (retval == EINVAL && clock_id == CLOCK_REALTIME) \
96 retval = realtime_gettime (tp); \
a77d3c17 97 else \
2f4f3bd4
RM
98 { \
99 __set_errno (retval); \
100 retval = -1; \
101 } \
7edb22ef 102 break
ad0e8eb0
UD
103#endif
104
105#ifdef __NR_clock_gettime
106/* We handled the REALTIME clock here. */
107# define HANDLED_REALTIME 1
2f4f3bd4
RM
108# define HANDLED_CPUTIME 1
109
110# if __ASSUME_POSIX_CPU_TIMERS > 0
111
446514f9
AS
112# define SYSDEP_GETTIME_CPU(clock_id, tp) \
113 retval = SYSCALL_GETTIME (clock_id, tp); \
114 break
2f4f3bd4
RM
115# define SYSDEP_GETTIME_CPUTIME /* Default catches them too. */
116
117# else
118
119int __libc_missing_posix_cpu_timers attribute_hidden;
120
121static int
122maybe_syscall_gettime_cpu (clockid_t clock_id, struct timespec *tp)
123{
124 int e = EINVAL;
125
126 if (!__libc_missing_posix_cpu_timers)
127 {
128 INTERNAL_SYSCALL_DECL (err);
a77d3c17 129 int r = INTERNAL_GETTIME (clock_id, tp);
2f4f3bd4
RM
130 if (!INTERNAL_SYSCALL_ERROR_P (r, err))
131 return 0;
132
133 e = INTERNAL_SYSCALL_ERRNO (r, err);
134# ifndef __ASSUME_POSIX_TIMERS
135 if (e == ENOSYS)
136 {
137 __libc_missing_posix_timers = 1;
138 __libc_missing_posix_cpu_timers = 1;
139 e = EINVAL;
140 }
141 else
142# endif
143 {
144 if (e == EINVAL)
145 {
4eb375fe 146# ifdef HAVE_CLOCK_GETRES_VSYSCALL
2f4f3bd4
RM
147 /* Check whether the kernel supports CPU clocks at all.
148 If not, record it for the future. */
8c2e201b 149 r = INTERNAL_VSYSCALL (clock_getres, err, 2,
4eb375fe
UD
150 MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
151 NULL);
152# else
153 /* Check whether the kernel supports CPU clocks at all.
154 If not, record it for the future. */
155 r = INTERNAL_SYSCALL (clock_getres, err, 2,
2f4f3bd4
RM
156 MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
157 NULL);
4eb375fe 158# endif
2f4f3bd4
RM
159 if (INTERNAL_SYSCALL_ERROR_P (r, err))
160 __libc_missing_posix_cpu_timers = 1;
161 }
162 }
163 }
164
165 return e;
166}
167
7edb22ef 168# define SYSDEP_GETTIME_CPU(clock_id, tp) \
2f4f3bd4
RM
169 retval = maybe_syscall_gettime_cpu (clock_id, tp); \
170 if (retval == 0) \
171 break; \
172 if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \
173 { \
174 __set_errno (retval); \
175 retval = -1; \
176 break; \
177 } \
178 retval = -1 /* Otherwise continue on to the HP_TIMING version. */;
179
180static inline int
181maybe_syscall_gettime_cputime (clockid_t clock_id, struct timespec *tp)
182{
183 return maybe_syscall_gettime_cpu
184 (clock_id == CLOCK_THREAD_CPUTIME_ID
185 ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED)
186 : MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
187 tp);
188}
189
190# define SYSDEP_GETTIME_CPUTIME \
191 case CLOCK_PROCESS_CPUTIME_ID: \
192 case CLOCK_THREAD_CPUTIME_ID: \
193 retval = maybe_syscall_gettime_cputime (clock_id, tp); \
194 if (retval == 0) \
195 break; \
196 if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \
197 { \
198 __set_errno (retval); \
199 retval = -1; \
200 break; \
201 } \
202 retval = hp_timing_gettime (clock_id, tp); \
7edb22ef 203 break
2f4f3bd4
RM
204# if !HP_TIMING_AVAIL
205# define hp_timing_gettime(clock_id, tp) (__set_errno (EINVAL), -1)
206# endif
207
208# endif
ad0e8eb0
UD
209#endif
210
211#include <sysdeps/unix/clock_gettime.c>