1 //===--- clock_gettime linux implementation ---------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "src/__support/time/clock_gettime.h"
10 #include "hdr/types/clockid_t.h"
11 #include "hdr/types/struct_timespec.h"
12 #include "src/__support/OSUtil/linux/vdso.h"
13 #include "src/__support/OSUtil/syscall.h"
14 #include "src/__support/common.h"
15 #include "src/__support/error_or.h"
16 #include "src/__support/macros/config.h"
17 #include <sys/syscall.h>
18
19 #if defined(SYS_clock_gettime64)
20 #include <linux/time_types.h>
21 #endif
22
23 namespace LIBC_NAMESPACE_DECL {
24 namespace internal {
clock_gettime(clockid_t clockid,timespec * ts)25 ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
26 using namespace vdso;
27 int ret;
28 #if defined(SYS_clock_gettime)
29 TypedSymbol<VDSOSym::ClockGetTime> clock_gettime;
30 if (LIBC_LIKELY(clock_gettime != nullptr))
31 ret = clock_gettime(clockid, ts);
32 else
33 ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime,
34 static_cast<long>(clockid),
35 reinterpret_cast<long>(ts));
36 #elif defined(SYS_clock_gettime64)
37 static_assert(
38 sizeof(time_t) == sizeof(int64_t),
39 "SYS_clock_gettime64 requires struct timespec with 64-bit members.");
40
41 TypedSymbol<VDSOSym::ClockGetTime64> clock_gettime64;
42 __kernel_timespec ts64{};
43 if (LIBC_LIKELY(clock_gettime64 != nullptr))
44 ret = clock_gettime64(clockid, &ts64);
45 else
46 ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime64,
47 static_cast<long>(clockid),
48 reinterpret_cast<long>(&ts64));
49 if (ret == 0) {
50 ts->tv_sec = static_cast<decltype(ts->tv_sec)>(ts64.tv_sec);
51 ts->tv_nsec = static_cast<decltype(ts->tv_nsec)>(ts64.tv_nsec);
52 }
53 #else
54 #error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available."
55 #endif
56 if (ret < 0)
57 return Error(-ret);
58 return ret;
59 }
60
61 } // namespace internal
62 } // namespace LIBC_NAMESPACE_DECL
63