Add fetestexceptflag.
[glibc.git] / sysdeps / unix / clock_gettime.c
blobffd6426dece9fadc42a8487012dbcfa6e786b961
1 /* clock_gettime -- Get the current time from a POSIX clockid_t. Unix version.
2 Copyright (C) 1999-2016 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 <errno.h>
20 #include <stdint.h>
21 #include <time.h>
22 #include <sys/time.h>
23 #include <libc-internal.h>
24 #include <ldsodefs.h>
27 #if HP_TIMING_AVAIL
28 /* Clock frequency of the processor. We make it a 64-bit variable
29 because some jokers are already playing with processors with more
30 than 4GHz. */
31 static hp_timing_t freq;
34 /* This function is defined in the thread library. */
35 extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
36 struct timespec *tp)
37 __attribute__ ((__weak__));
39 static int
40 hp_timing_gettime (clockid_t clock_id, struct timespec *tp)
42 hp_timing_t tsc;
44 if (__glibc_unlikely (freq == 0))
46 /* This can only happen if we haven't initialized the `freq'
47 variable yet. Do this now. We don't have to protect this
48 code against multiple execution since all of them should
49 lead to the same result. */
50 freq = __get_clockfreq ();
51 if (__glibc_unlikely (freq == 0))
52 /* Something went wrong. */
53 return -1;
56 if (clock_id != CLOCK_PROCESS_CPUTIME_ID
57 && __pthread_clock_gettime != NULL)
58 return __pthread_clock_gettime (clock_id, freq, tp);
60 /* Get the current counter. */
61 HP_TIMING_NOW (tsc);
63 /* Compute the offset since the start time of the process. */
64 tsc -= GL(dl_cpuclock_offset);
66 /* Compute the seconds. */
67 tp->tv_sec = tsc / freq;
69 /* And the nanoseconds. This computation should be stable until
70 we get machines with about 16GHz frequency. */
71 tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq;
73 return 0;
75 #endif
78 static inline int
79 realtime_gettime (struct timespec *tp)
81 struct timeval tv;
82 int retval = gettimeofday (&tv, NULL);
83 if (retval == 0)
84 /* Convert into `timespec'. */
85 TIMEVAL_TO_TIMESPEC (&tv, tp);
86 return retval;
90 /* Get current value of CLOCK and store it in TP. */
91 int
92 __clock_gettime (clockid_t clock_id, struct timespec *tp)
94 int retval = -1;
96 switch (clock_id)
98 #ifdef SYSDEP_GETTIME
99 SYSDEP_GETTIME;
100 #endif
102 #ifndef HANDLED_REALTIME
103 case CLOCK_REALTIME:
105 struct timeval tv;
106 retval = gettimeofday (&tv, NULL);
107 if (retval == 0)
108 TIMEVAL_TO_TIMESPEC (&tv, tp);
110 break;
111 #endif
113 default:
114 #ifdef SYSDEP_GETTIME_CPU
115 SYSDEP_GETTIME_CPU (clock_id, tp);
116 #endif
117 #if HP_TIMING_AVAIL
118 if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
119 == CLOCK_THREAD_CPUTIME_ID)
120 retval = hp_timing_gettime (clock_id, tp);
121 else
122 #endif
123 __set_errno (EINVAL);
124 break;
126 #if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
127 case CLOCK_PROCESS_CPUTIME_ID:
128 retval = hp_timing_gettime (clock_id, tp);
129 break;
130 #endif
133 return retval;
135 weak_alias (__clock_gettime, clock_gettime)
136 libc_hidden_def (__clock_gettime)