]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/clock_gettime.c
[BZ #966]
[thirdparty/glibc.git] / sysdeps / unix / clock_gettime.c
1 /* clock_gettime -- Get the current time from a POSIX clockid_t. Unix version.
2 Copyright (C) 1999-2004, 2005 Free Software Foundation, Inc.
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
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20 #include <errno.h>
21 #include <stdint.h>
22 #include <time.h>
23 #include <sys/time.h>
24 #include <libc-internal.h>
25 #include <ldsodefs.h>
26
27
28 #if HP_TIMING_AVAIL
29 /* Clock frequency of the processor. We make it a 64-bit variable
30 because some jokers are already playing with processors with more
31 than 4GHz. */
32 static hp_timing_t freq;
33
34
35 /* This function is defined in the thread library. */
36 extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
37 struct timespec *tp)
38 __attribute__ ((__weak__));
39
40 static int
41 hp_timing_gettime (clockid_t clock_id, struct timespec *tp)
42 {
43 hp_timing_t tsc;
44
45 if (__builtin_expect (freq == 0, 0))
46 {
47 /* This can only happen if we haven't initialized the `freq'
48 variable yet. Do this now. We don't have to protect this
49 code against multiple execution since all of them should
50 lead to the same result. */
51 freq = __get_clockfreq ();
52 if (__builtin_expect (freq == 0, 0))
53 /* Something went wrong. */
54 return -1;
55 }
56
57 if (clock_id != CLOCK_PROCESS_CPUTIME_ID
58 && __pthread_clock_gettime != NULL)
59 return __pthread_clock_gettime (clock_id, freq, tp);
60
61 /* Get the current counter. */
62 HP_TIMING_NOW (tsc);
63
64 /* Compute the offset since the start time of the process. */
65 tsc -= GL(dl_cpuclock_offset);
66
67 /* Compute the seconds. */
68 tp->tv_sec = tsc / freq;
69
70 /* And the nanoseconds. This computation should be stable until
71 we get machines with about 16GHz frequency. */
72 tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq;
73
74 return 0;
75 }
76 #endif
77
78
79 static inline int
80 realtime_gettime (struct timespec *tp)
81 {
82 struct timeval tv;
83 int retval = gettimeofday (&tv, NULL);
84 if (retval == 0)
85 /* Convert into `timespec'. */
86 TIMEVAL_TO_TIMESPEC (&tv, tp);
87 return retval;
88 }
89
90
91 /* Get current value of CLOCK and store it in TP. */
92 int
93 clock_gettime (clockid_t clock_id, struct timespec *tp)
94 {
95 int retval = -1;
96 struct timeval tv;
97
98 switch (clock_id)
99 {
100 #ifdef SYSDEP_GETTIME
101 SYSDEP_GETTIME;
102 #endif
103
104 #ifndef HANDLED_REALTIME
105 case CLOCK_REALTIME:
106 retval = gettimeofday (&tv, NULL);
107 if (retval == 0)
108 TIMEVAL_TO_TIMESPEC (&tv, tp);
109 break;
110 #endif
111
112 default:
113 #ifdef SYSDEP_GETTIME_CPU
114 SYSDEP_GETTIME_CPU;
115 #endif
116 #if HP_TIMING_AVAIL
117 if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
118 == CLOCK_THREAD_CPUTIME_ID)
119 retval = hp_timing_gettime (clock_id, tp);
120 else
121 #endif
122 __set_errno (EINVAL);
123 break;
124
125 #if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
126 case CLOCK_PROCESS_CPUTIME_ID:
127 retval = hp_timing_gettime (clock_id, tp);
128 break;
129 #endif
130 }
131
132 return retval;
133 }