From af569cdbb89b9ab67a65ecc4128e81061ce494c1 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Mon, 4 Sep 2023 11:45:33 -0300 Subject: [PATCH 1/2] [libc] Unify gettime implmenetations 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). --- libc/src/time/clock_gettime.cpp | 20 +++-------- libc/src/time/gettimeofday.cpp | 26 ++++++-------- libc/src/time/linux/clock.cpp | 18 +++------- libc/src/time/linux/clockGetTimeImpl.h | 47 ++++++++++++++++++++++++++ libc/src/time/linux/time.cpp | 15 +++----- 5 files changed, 71 insertions(+), 55 deletions(-) create mode 100644 libc/src/time/linux/clockGetTimeImpl.h diff --git a/libc/src/time/clock_gettime.cpp b/libc/src/time/clock_gettime.cpp index 94818c03768cc..33ec04eb35274 100644 --- a/libc/src/time/clock_gettime.cpp +++ b/libc/src/time/clock_gettime.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 // For syscall numbers. #include @@ -19,26 +20,15 @@ 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 *tp)) { -#if SYS_clock_gettime - int ret = __llvm_libc::syscall_impl(SYS_clock_gettime, - static_cast(clockid), - reinterpret_cast(tp)); -#elif defined(SYS_clock_gettime64) - int ret = __llvm_libc::syscall_impl(SYS_clock_gettime64, - static_cast(clockid), - reinterpret_cast(tp)); -#else -#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available." -#endif + (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 (ret < 0) { - libc_errno = -ret; + if (!result.has_value()) { + libc_errno = result.error(); return -1; } - return 0; } diff --git a/libc/src/time/gettimeofday.cpp b/libc/src/time/gettimeofday.cpp index 8d44e630cc13b..2df6429974164 100644 --- a/libc/src/time/gettimeofday.cpp +++ b/libc/src/time/gettimeofday.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 // For syscall numbers. @@ -21,26 +22,19 @@ LLVM_LIBC_FUNCTION(int, gettimeofday, (struct timeval * tv, [[maybe_unused]] void *unused)) { if (tv == nullptr) return 0; - struct timespec tp; -#if SYS_clock_gettime - int ret = __llvm_libc::syscall_impl(SYS_clock_gettime, - static_cast(CLOCK_REALTIME), - reinterpret_cast(&tp)); -#elif defined(SYS_clock_gettime64) - int ret = __llvm_libc::syscall_impl(SYS_clock_gettime64, - static_cast(CLOCK_REALTIME), - reinterpret_cast(&tp)); -#else -#error "SYS_clock_gettime and SYS_clock_gettime64 syscalls not available." -#endif + + 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 (ret < 0) { - libc_errno = -ret; + if (!result.has_value()) { + libc_errno = result.error(); return -1; } - tv->tv_sec = tp.tv_sec; - tv->tv_usec = static_cast(tp.tv_nsec / 1000); + + tv->tv_sec = ts.tv_sec; + tv->tv_usec = static_cast(ts.tv_nsec / 1000); return 0; } diff --git a/libc/src/time/linux/clock.cpp b/libc/src/time/linux/clock.cpp index 2b19f8e9c54ce..cf27f5c299571 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 // For syscall numbers. #include @@ -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( - SYS_clock_gettime, CLOCK_PROCESS_CPUTIME_ID, reinterpret_cast(&ts)); -#elif defined(SYS_clock_gettime64) - int ret = __llvm_libc::syscall_impl(SYS_clock_gettime64, - CLOCK_PROCESS_CPUTIME_ID, - reinterpret_cast(&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 0000000000000..a5b7d659c7c14 --- /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 // For syscall numbers. +#include + +namespace __llvm_libc { +namespace internal { + +LIBC_INLINE ErrorOr clock_gettimeimpl(clockid_t clockid, + struct timespec *ts) { +#if SYS_clock_gettime + int ret = __llvm_libc::syscall_impl(SYS_clock_gettime, + static_cast(clockid), + reinterpret_cast(ts)); +#elif defined(SYS_clock_gettime64) + struct timespec64 ts64; + int ret = __llvm_libc::syscall_impl(SYS_clock_gettime64, + static_cast(clockid), + reinterpret_cast(&ts64)); + ts->tv_sec = static_cast(ts64.tv_sec); + ts->tv_nsec = static_cast(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/time.cpp b/libc/src/time/linux/time.cpp index 34cca42adf5ba..4dbcabc896351 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 // For syscall numbers. #include @@ -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(SYS_clock_gettime, CLOCK_REALTIME, - reinterpret_cast(&ts)); -#elif defined(SYS_clock_gettime64) - int ret = __llvm_libc::syscall_impl(SYS_clock_gettime64, CLOCK_REALTIME, - reinterpret_cast(&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; } From c880f1c5e2c46a5f54d93d9453091814eb5e6606 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 7 Sep 2023 11:00:42 -0300 Subject: [PATCH 2/2] Moved gettimeofday and clock_gettime to linux dir --- libc/src/time/CMakeLists.txt | 41 +++++++-------------- libc/src/time/linux/CMakeLists.txt | 26 +++++++++++++ libc/src/time/{ => linux}/clock_gettime.cpp | 0 libc/src/time/{ => linux}/gettimeofday.cpp | 0 4 files changed, 40 insertions(+), 27 deletions(-) rename libc/src/time/{ => linux}/clock_gettime.cpp (100%) rename libc/src/time/{ => linux}/gettimeofday.cpp (100%) diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt index 5a0b3ab31cf0f..210f3b23432b4 100644 --- a/libc/src/time/CMakeLists.txt +++ b/libc/src/time/CMakeLists.txt @@ -35,19 +35,6 @@ add_entrypoint_object( libc.include.time ) -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( difftime SRCS @@ -58,20 +45,6 @@ add_entrypoint_object( libc.include.time ) -add_entrypoint_object( - gettimeofday - SRCS - gettimeofday.cpp - HDRS - gettimeofday.h - DEPENDS - .clock_gettime - libc.include.time - libc.include.sys_syscall - libc.src.__support.OSUtil.osutil - libc.src.errno.errno -) - add_entrypoint_object( gmtime SRCS @@ -126,3 +99,17 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.nanosleep ) + +add_entrypoint_object( + clock_gettime + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.clock_gettime +) + +add_entrypoint_object( + gettimeofday + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.gettimeofday +) diff --git a/libc/src/time/linux/CMakeLists.txt b/libc/src/time/linux/CMakeLists.txt index 8b4976847f82a..df79bf5986261 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/clock_gettime.cpp b/libc/src/time/linux/clock_gettime.cpp similarity index 100% rename from libc/src/time/clock_gettime.cpp rename to libc/src/time/linux/clock_gettime.cpp diff --git a/libc/src/time/gettimeofday.cpp b/libc/src/time/linux/gettimeofday.cpp similarity index 100% rename from libc/src/time/gettimeofday.cpp rename to libc/src/time/linux/gettimeofday.cpp