1 /* clock_gettime -- Get current time from a POSIX clockid_t.  Linux version.
2    Copyright (C) 2003, 2004 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, see
17    <http://www.gnu.org/licenses/>.  */
18 
19 #include <errno.h>
20 #include <sysdep.h>
21 #include <time.h>
22 #include <sys/time.h>
23 #include "kernel-posix-cpu-timers.h"
24 
25 #ifdef __VDSO_SUPPORT__
26 #include "ldso.h"
27 #endif
28 
29 #if defined(__UCLIBC_USE_TIME64__)
30 #include "internal/time64_helpers.h"
31 #endif
32 
33 #if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64)
34 #define SYSCALL_GETTIME           \
35   {                               \
36   struct __ts64_struct __ts64;    \
37   retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, &__ts64); \
38   if (tp) {                       \
39     tp->tv_sec = __ts64.tv_sec;   \
40     tp->tv_nsec = __ts64.tv_nsec; \
41   }                               \
42   break;                          \
43   }
44 #else
45 #define SYSCALL_GETTIME \
46   retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
47   break
48 #endif
49 
50 /* The REALTIME and MONOTONIC clock are definitely supported in the kernel.  */
51 #define SYSDEP_GETTIME							      \
52   SYSDEP_GETTIME_CPUTIME						      \
53   case CLOCK_REALTIME:							      \
54   case CLOCK_MONOTONIC:							      \
55     SYSCALL_GETTIME
56 
57 /* We handled the REALTIME clock here.  */
58 #define HANDLED_REALTIME	1
59 #define HANDLED_CPUTIME	1
60 
61 #define SYSDEP_GETTIME_CPU SYSCALL_GETTIME
62 #define SYSDEP_GETTIME_CPUTIME	/* Default catches them too.  */
63 
64 static inline int
realtime_gettime(struct timespec * tp)65 realtime_gettime (struct timespec *tp)
66 {
67   struct timeval tv;
68   int retval = gettimeofday (&tv, NULL);
69   if (retval == 0)
70     /* Convert into `timespec'.  */
71     TIMEVAL_TO_TIMESPEC (&tv, tp);
72   return retval;
73 }
74 
75 int
__libc_clock_gettime(clockid_t clock_id,struct timespec * tp)76 __libc_clock_gettime (clockid_t clock_id, struct timespec *tp)
77 {
78   int retval = -1;
79 #ifndef HANDLED_REALTIME
80   struct timeval tv;
81 #endif
82 
83   switch (clock_id)
84     {
85 #ifdef SYSDEP_GETTIME
86       SYSDEP_GETTIME;
87 #endif
88 
89 #ifndef HANDLED_REALTIME
90     case CLOCK_REALTIME:
91       retval = gettimeofday (&tv, NULL);
92       if (retval == 0)
93 	TIMEVAL_TO_TIMESPEC (&tv, tp);
94       break;
95 #endif
96 
97     default:
98 #ifdef SYSDEP_GETTIME_CPU
99       SYSDEP_GETTIME_CPU;
100 #endif
101 	__set_errno (EINVAL);
102       break;
103     }
104 
105   return retval;
106 }
107 
108 /* Get current value of CLOCK and store it in TP.  */
109 int
clock_gettime(clockid_t clock_id,struct timespec * tp)110 clock_gettime (clockid_t clock_id, struct timespec *tp)
111 {
112 #if defined(__VDSO_SUPPORT__) && defined(ARCH_VDSO_CLOCK_GETTIME)
113   return ARCH_VDSO_CLOCK_GETTIME(clock_id, tp);
114 #else
115   return __libc_clock_gettime(clock_id, tp);
116 #endif
117 }
118