xref: /llvm-project/libc/src/__support/time/linux/clock_gettime.cpp (revision e6cf5d2863b77895ae7183952514bedd9e8dde16)
11b413c8aSSchrodinger ZHU Yifan //===--- clock_gettime linux implementation ---------------------*- C++ -*-===//
21b413c8aSSchrodinger ZHU Yifan //
31b413c8aSSchrodinger ZHU Yifan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41b413c8aSSchrodinger ZHU Yifan // See https://llvm.org/LICENSE.txt for license information.
51b413c8aSSchrodinger ZHU Yifan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61b413c8aSSchrodinger ZHU Yifan //
71b413c8aSSchrodinger ZHU Yifan //===----------------------------------------------------------------------===//
81b413c8aSSchrodinger ZHU Yifan 
9*e6cf5d28SSchrodinger ZHU Yifan #include "src/__support/time/clock_gettime.h"
101b413c8aSSchrodinger ZHU Yifan #include "hdr/types/clockid_t.h"
111b413c8aSSchrodinger ZHU Yifan #include "hdr/types/struct_timespec.h"
121b413c8aSSchrodinger ZHU Yifan #include "src/__support/OSUtil/linux/vdso.h"
131b413c8aSSchrodinger ZHU Yifan #include "src/__support/OSUtil/syscall.h"
141b413c8aSSchrodinger ZHU Yifan #include "src/__support/common.h"
151b413c8aSSchrodinger ZHU Yifan #include "src/__support/error_or.h"
161b413c8aSSchrodinger ZHU Yifan #include "src/__support/macros/config.h"
171b413c8aSSchrodinger ZHU Yifan #include <sys/syscall.h>
181b413c8aSSchrodinger ZHU Yifan 
191b413c8aSSchrodinger ZHU Yifan #if defined(SYS_clock_gettime64)
201b413c8aSSchrodinger ZHU Yifan #include <linux/time_types.h>
211b413c8aSSchrodinger ZHU Yifan #endif
221b413c8aSSchrodinger ZHU Yifan 
231b413c8aSSchrodinger ZHU Yifan namespace LIBC_NAMESPACE_DECL {
241b413c8aSSchrodinger ZHU Yifan namespace internal {
251b413c8aSSchrodinger ZHU Yifan ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
261b413c8aSSchrodinger ZHU Yifan   using namespace vdso;
271b413c8aSSchrodinger ZHU Yifan   int ret;
281b413c8aSSchrodinger ZHU Yifan #if defined(SYS_clock_gettime)
291b413c8aSSchrodinger ZHU Yifan   TypedSymbol<VDSOSym::ClockGetTime> clock_gettime;
301b413c8aSSchrodinger ZHU Yifan   if (LIBC_LIKELY(clock_gettime != nullptr))
311b413c8aSSchrodinger ZHU Yifan     ret = clock_gettime(clockid, ts);
321b413c8aSSchrodinger ZHU Yifan   else
331b413c8aSSchrodinger ZHU Yifan     ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime,
341b413c8aSSchrodinger ZHU Yifan                                             static_cast<long>(clockid),
351b413c8aSSchrodinger ZHU Yifan                                             reinterpret_cast<long>(ts));
361b413c8aSSchrodinger ZHU Yifan #elif defined(SYS_clock_gettime64)
371b413c8aSSchrodinger ZHU Yifan   static_assert(
381b413c8aSSchrodinger ZHU Yifan       sizeof(time_t) == sizeof(int64_t),
391b413c8aSSchrodinger ZHU Yifan       "SYS_clock_gettime64 requires struct timespec with 64-bit members.");
401b413c8aSSchrodinger ZHU Yifan 
411b413c8aSSchrodinger ZHU Yifan   TypedSymbol<VDSOSym::ClockGetTime64> clock_gettime64;
421b413c8aSSchrodinger ZHU Yifan   __kernel_timespec ts64{};
431b413c8aSSchrodinger ZHU Yifan   if (LIBC_LIKELY(clock_gettime64 != nullptr))
441b413c8aSSchrodinger ZHU Yifan     ret = clock_gettime64(clockid, &ts64);
451b413c8aSSchrodinger ZHU Yifan   else
461b413c8aSSchrodinger ZHU Yifan     ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime64,
471b413c8aSSchrodinger ZHU Yifan                                             static_cast<long>(clockid),
481b413c8aSSchrodinger ZHU Yifan                                             reinterpret_cast<long>(&ts64));
491b413c8aSSchrodinger ZHU Yifan   if (ret == 0) {
501b413c8aSSchrodinger ZHU Yifan     ts->tv_sec = static_cast<decltype(ts->tv_sec)>(ts64.tv_sec);
511b413c8aSSchrodinger ZHU Yifan     ts->tv_nsec = static_cast<decltype(ts->tv_nsec)>(ts64.tv_nsec);
521b413c8aSSchrodinger ZHU Yifan   }
531b413c8aSSchrodinger ZHU Yifan #else
541b413c8aSSchrodinger ZHU Yifan #error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available."
551b413c8aSSchrodinger ZHU Yifan #endif
561b413c8aSSchrodinger ZHU Yifan   if (ret < 0)
571b413c8aSSchrodinger ZHU Yifan     return Error(-ret);
581b413c8aSSchrodinger ZHU Yifan   return ret;
591b413c8aSSchrodinger ZHU Yifan }
601b413c8aSSchrodinger ZHU Yifan 
611b413c8aSSchrodinger ZHU Yifan } // namespace internal
621b413c8aSSchrodinger ZHU Yifan } // namespace LIBC_NAMESPACE_DECL
63