diff options
| author | Mikhail R. Gadelha <mikhail@igalia.com> | 2023-09-08 13:41:29 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-08 12:41:29 -0400 |
| commit | 123bf084029e4d35420a95e47ddd332d24c23a6d (patch) | |
| tree | 76b933586de946abd6144b7957d044f06479c712 /libc/src/time/linux | |
| parent | 5f16a3a489bd1730db49f635604bc1d833abed15 (diff) | |
[libc] Unify gettime implementations (#65383)
Similar to D159208, this patch unifies the calls to a syscall, in this
patch it is the syscall SYS_clock_gettime/SYS_clock_gettime64.
This patch also fixes calls to SYS_clock_gettime64 by creating a
timespec64 object, passing it to the syscall and rewriting the timespec
given by the caller with timespec64 object's contents. This fixes cases
where timespec has a 4 bytes long time_t member, but SYS_clock_gettime
is not available (e.g., rv32).
Diffstat (limited to 'libc/src/time/linux')
| -rw-r--r-- | libc/src/time/linux/CMakeLists.txt | 26 | ||||
| -rw-r--r-- | libc/src/time/linux/clock.cpp | 18 | ||||
| -rw-r--r-- | libc/src/time/linux/clockGetTimeImpl.h | 47 | ||||
| -rw-r--r-- | libc/src/time/linux/clock_gettime.cpp | 35 | ||||
| -rw-r--r-- | libc/src/time/linux/gettimeofday.cpp | 41 | ||||
| -rw-r--r-- | libc/src/time/linux/time.cpp | 15 |
6 files changed, 158 insertions, 24 deletions
diff --git a/libc/src/time/linux/CMakeLists.txt b/libc/src/time/linux/CMakeLists.txt index 8b4976847f82..df79bf598626 100644 --- a/libc/src/time/linux/CMakeLists.txt +++ b/libc/src/time/linux/CMakeLists.txt @@ -38,3 +38,29 @@ add_entrypoint_object( libc.src.__support.OSUtil.osutil libc.src.errno.errno ) + +add_entrypoint_object( + clock_gettime + SRCS + clock_gettime.cpp + HDRS + ../clock_gettime.h + DEPENDS + libc.include.time + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + +add_entrypoint_object( + gettimeofday + SRCS + gettimeofday.cpp + HDRS + ../gettimeofday.h + DEPENDS + libc.include.time + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) diff --git a/libc/src/time/linux/clock.cpp b/libc/src/time/linux/clock.cpp index 2b19f8e9c54c..cf27f5c29957 100644 --- a/libc/src/time/linux/clock.cpp +++ b/libc/src/time/linux/clock.cpp @@ -12,6 +12,7 @@ #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" #include "src/errno/libc_errno.h" +#include "src/time/linux/clockGetTimeImpl.h" #include <sys/syscall.h> // For syscall numbers. #include <time.h> @@ -20,19 +21,10 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(clock_t, clock, ()) { struct timespec ts; -#if SYS_clock_gettime - int ret = __llvm_libc::syscall_impl<int>( - SYS_clock_gettime, CLOCK_PROCESS_CPUTIME_ID, reinterpret_cast<long>(&ts)); -#elif defined(SYS_clock_gettime64) - int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime64, - CLOCK_PROCESS_CPUTIME_ID, - reinterpret_cast<long>(&ts)); -#else -#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available." -#endif - if (ret < 0) { - libc_errno = -ret; - return clock_t(-1); + auto result = internal::clock_gettimeimpl(CLOCK_PROCESS_CPUTIME_ID, &ts); + if (!result.has_value()) { + libc_errno = result.error(); + return -1; } // The above syscall gets the CPU time in seconds plus nanoseconds. diff --git a/libc/src/time/linux/clockGetTimeImpl.h b/libc/src/time/linux/clockGetTimeImpl.h new file mode 100644 index 000000000000..a5b7d659c7c1 --- /dev/null +++ b/libc/src/time/linux/clockGetTimeImpl.h @@ -0,0 +1,47 @@ +//===- Linux implementation of the POSIX clock_gettime function -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H +#define LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/__support/error_or.h" +#include "src/errno/libc_errno.h" + +#include <sys/syscall.h> // For syscall numbers. +#include <time.h> + +namespace __llvm_libc { +namespace internal { + +LIBC_INLINE ErrorOr<int> clock_gettimeimpl(clockid_t clockid, + struct timespec *ts) { +#if SYS_clock_gettime + int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime, + static_cast<long>(clockid), + reinterpret_cast<long>(ts)); +#elif defined(SYS_clock_gettime64) + struct timespec64 ts64; + int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime64, + static_cast<long>(clockid), + reinterpret_cast<long>(&ts64)); + ts->tv_sec = static_cast<time_t>(ts64.tv_sec); + ts->tv_nsec = static_cast<long>(ts64.tv_nsec); +#else +#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available." +#endif + if (ret < 0) + return Error(-ret); + return ret; +} + +} // namespace internal +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H diff --git a/libc/src/time/linux/clock_gettime.cpp b/libc/src/time/linux/clock_gettime.cpp new file mode 100644 index 000000000000..33ec04eb3527 --- /dev/null +++ b/libc/src/time/linux/clock_gettime.cpp @@ -0,0 +1,35 @@ +//===---------- Linux implementation of the POSIX clock_gettime function --===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/time/clock_gettime.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/errno/libc_errno.h" +#include "src/time/linux/clockGetTimeImpl.h" + +#include <sys/syscall.h> // For syscall numbers. +#include <time.h> + +namespace __llvm_libc { + +// TODO(michaelrj): Move this into time/linux with the other syscalls. +LLVM_LIBC_FUNCTION(int, clock_gettime, + (clockid_t clockid, struct timespec *ts)) { + auto result = internal::clock_gettimeimpl(clockid, ts); + + // A negative return value indicates an error with the magnitude of the + // value being the error code. + if (!result.has_value()) { + libc_errno = result.error(); + return -1; + } + return 0; +} + +} // namespace __llvm_libc diff --git a/libc/src/time/linux/gettimeofday.cpp b/libc/src/time/linux/gettimeofday.cpp new file mode 100644 index 000000000000..2df642997416 --- /dev/null +++ b/libc/src/time/linux/gettimeofday.cpp @@ -0,0 +1,41 @@ +//===-- Implementation of gettimeofday function ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/time/gettimeofday.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/errno/libc_errno.h" +#include "src/time/linux/clockGetTimeImpl.h" + +#include <sys/syscall.h> // For syscall numbers. + +namespace __llvm_libc { + +// TODO(michaelrj): Move this into time/linux with the other syscalls. +LLVM_LIBC_FUNCTION(int, gettimeofday, + (struct timeval * tv, [[maybe_unused]] void *unused)) { + if (tv == nullptr) + return 0; + + struct timespec ts; + auto result = internal::clock_gettimeimpl(CLOCK_REALTIME, &ts); + + // A negative return value indicates an error with the magnitude of the + // value being the error code. + if (!result.has_value()) { + libc_errno = result.error(); + return -1; + } + + tv->tv_sec = ts.tv_sec; + tv->tv_usec = static_cast<suseconds_t>(ts.tv_nsec / 1000); + return 0; +} + +} // namespace __llvm_libc diff --git a/libc/src/time/linux/time.cpp b/libc/src/time/linux/time.cpp index 34cca42adf5b..4dbcabc89635 100644 --- a/libc/src/time/linux/time.cpp +++ b/libc/src/time/linux/time.cpp @@ -11,6 +11,7 @@ #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" #include "src/errno/libc_errno.h" +#include "src/time/linux/clockGetTimeImpl.h" #include <sys/syscall.h> // For syscall numbers. #include <time.h> @@ -20,17 +21,9 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(time_t, time, (time_t * tp)) { // TODO: Use the Linux VDSO to fetch the time and avoid the syscall. struct timespec ts; -#if SYS_clock_gettime - int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime, CLOCK_REALTIME, - reinterpret_cast<long>(&ts)); -#elif defined(SYS_clock_gettime64) - int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime64, CLOCK_REALTIME, - reinterpret_cast<long>(&ts)); -#else -#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available." -#endif - if (ret < 0) { - libc_errno = -ret; + auto result = internal::clock_gettimeimpl(CLOCK_REALTIME, &ts); + if (!result.has_value()) { + libc_errno = result.error(); return -1; } |
