summaryrefslogtreecommitdiff
path: root/libc/src/time/linux
diff options
context:
space:
mode:
authorMikhail R. Gadelha <mikhail@igalia.com>2023-09-08 13:41:29 -0300
committerGitHub <noreply@github.com>2023-09-08 12:41:29 -0400
commit123bf084029e4d35420a95e47ddd332d24c23a6d (patch)
tree76b933586de946abd6144b7957d044f06479c712 /libc/src/time/linux
parent5f16a3a489bd1730db49f635604bc1d833abed15 (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.txt26
-rw-r--r--libc/src/time/linux/clock.cpp18
-rw-r--r--libc/src/time/linux/clockGetTimeImpl.h47
-rw-r--r--libc/src/time/linux/clock_gettime.cpp35
-rw-r--r--libc/src/time/linux/gettimeofday.cpp41
-rw-r--r--libc/src/time/linux/time.cpp15
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;
}