2.3.5-8
[kopensolaris-gnu/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
97   switch (clock_id)
98     {
99 #ifdef SYSDEP_GETTIME
100       SYSDEP_GETTIME;
101 #endif
102
103 #ifndef HANDLED_REALTIME
104     case CLOCK_REALTIME:
105       HANDLE_REALTIME;
106       break;
107 #endif
108
109     default:
110 #ifdef SYSDEP_GETTIME_CPU
111       SYSDEP_GETTIME_CPU;
112 #endif
113 #if HP_TIMING_AVAIL
114       if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
115           == CLOCK_THREAD_CPUTIME_ID)
116         retval = hp_timing_gettime (clock_id, tp);
117       else
118 #endif
119         __set_errno (EINVAL);
120       break;
121
122 #if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
123     case CLOCK_PROCESS_CPUTIME_ID:
124       retval = hp_timing_gettime (clock_id, tp);
125       break;
126 #endif
127     }
128
129   return retval;
130 }