Skip to content

[libc] Unify gettime implementations #65383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 14 additions & 27 deletions libc/src/time/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
)
26 changes: 26 additions & 0 deletions libc/src/time/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
18 changes: 5 additions & 13 deletions libc/src/time/linux/clock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,47 @@
//===---------- Linux implementation of the POSIX clock_gettime function --===//
//===- 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
//
//===----------------------------------------------------------------------===//

#include "src/time/clock_gettime.h"
#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 {

// TODO(michaelrj): Move this into time/linux with the other syscalls.
LLVM_LIBC_FUNCTION(int, clock_gettime,
(clockid_t clockid, struct timespec *tp)) {
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>(tp));
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>(tp));
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

// A negative return value indicates an error with the magnitude of the
// value being the error code.
if (ret < 0) {
libc_errno = -ret;
return -1;
}

return 0;
if (ret < 0)
return Error(-ret);
return ret;
}

} // namespace internal
} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H
35 changes: 35 additions & 0 deletions libc/src/time/linux/clock_gettime.cpp
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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<int>(SYS_clock_gettime,
static_cast<long>(CLOCK_REALTIME),
reinterpret_cast<long>(&tp));
#elif defined(SYS_clock_gettime64)
int ret = __llvm_libc::syscall_impl<int>(SYS_clock_gettime64,
static_cast<long>(CLOCK_REALTIME),
reinterpret_cast<long>(&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<suseconds_t>(tp.tv_nsec / 1000);

tv->tv_sec = ts.tv_sec;
tv->tv_usec = static_cast<suseconds_t>(ts.tv_nsec / 1000);
return 0;
}

Expand Down
15 changes: 4 additions & 11 deletions libc/src/time/linux/time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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;
}

Expand Down