30 changes: 14 additions & 16 deletions libc/src/time/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ add_entrypoint_object(
HDRS
../time_func.h
DEPENDS
libc.hdr.time_macros
libc.hdr.types.time_t
libc.src.__support.time.clock_gettime
libc.include.time
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)

Expand All @@ -18,11 +18,10 @@ add_entrypoint_object(
HDRS
../clock.h
DEPENDS
libc.hdr.time_macros
libc.hdr.types.clock_t
libc.src.__support.time.units
libc.src.__support.time.clock_gettime
libc.include.time
libc.include.sys_syscall
libc.src.__support.CPP.limits
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)

Expand All @@ -33,10 +32,10 @@ add_entrypoint_object(
HDRS
../nanosleep.h
DEPENDS
libc.hdr.types.struct_timespec
libc.include.time
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.__support.CPP.limits
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)

Expand All @@ -47,9 +46,9 @@ add_entrypoint_object(
HDRS
../clock_gettime.h
DEPENDS
libc.hdr.types.clockid_t
libc.hdr.types.struct_timespec
libc.src.__support.time.clock_gettime
libc.include.time
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)

Expand All @@ -60,9 +59,8 @@ add_entrypoint_object(
HDRS
../gettimeofday.h
DEPENDS
libc.hdr.time_macros
libc.hdr.types.suseconds_t
libc.src.__support.time.clock_gettime
libc.src.__support.time.units
libc.include.time
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
20 changes: 11 additions & 9 deletions libc/src/time/linux/clock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@
//===----------------------------------------------------------------------===//

#include "src/time/clock.h"
#include "hdr/time_macros.h"

#include "src/__support/CPP/limits.h"
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/__support/time/clock_gettime.h"
#include "src/__support/time/units.h"
#include "src/errno/libc_errno.h"
#include "src/time/linux/clockGetTimeImpl.h"

#include <sys/syscall.h> // For syscall numbers.
#include <time.h>

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(clock_t, clock, ()) {
using namespace time_units;
struct timespec ts;
auto result = internal::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
auto result = internal::clock_gettimeimpl(CLOCK_PROCESS_CPUTIME_ID, &ts);
if (!result.has_value()) {
libc_errno = result.error();
return -1;
Expand All @@ -32,15 +34,15 @@ LLVM_LIBC_FUNCTION(clock_t, clock, ()) {
cpp::numeric_limits<clock_t>::max() / CLOCKS_PER_SEC;
if (ts.tv_sec > CLOCK_SECS_MAX)
return clock_t(-1);
if (ts.tv_nsec / 1_s_ns > CLOCK_SECS_MAX - ts.tv_sec)
if (ts.tv_nsec / 1000000000 > CLOCK_SECS_MAX - ts.tv_sec)
return clock_t(-1);

// For the integer computation converting tv_nsec to clocks to work
// correctly, we want CLOCKS_PER_SEC to be less than 1000000000.
static_assert(1_s_ns > CLOCKS_PER_SEC,
"Expected CLOCKS_PER_SEC to be less than 1'000'000'000.");
static_assert(1000000000 > CLOCKS_PER_SEC,
"Expected CLOCKS_PER_SEC to be less than 1000000000.");
return clock_t(ts.tv_sec * CLOCKS_PER_SEC +
ts.tv_nsec / (1_s_ns / CLOCKS_PER_SEC));
ts.tv_nsec / (1000000000 / CLOCKS_PER_SEC));
}

} // namespace LIBC_NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
//===--- clock_gettime linux implementation ---------------------*- C++ -*-===//
//===- 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___SUPPORT_TIME_LINUX_CLOCK_GETTIME_H
#define LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_CLOCK_GETTIME_H
#include "src/__support/time/clock_gettime.h"
#include "src/__support/OSUtil/syscall.h"
#include <sys/syscall.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 <stdint.h> // For int64_t.
#include <sys/syscall.h> // For syscall numbers.
#include <time.h>

namespace LIBC_NAMESPACE {
namespace internal {
ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {

LIBC_INLINE ErrorOr<int> clock_gettimeimpl(clockid_t clockid,
struct timespec *ts) {
#if SYS_clock_gettime
int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_clock_gettime,
static_cast<long>(clockid),
Expand All @@ -36,4 +45,4 @@ ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
} // namespace internal
} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC___SUPPORT_TIME_LINUX_CLOCK_GETTIME_H
#endif // LLVM_LIBC_SRC_TIME_LINUX_CLOCKGETTIMEIMPL_H
9 changes: 7 additions & 2 deletions libc/src/time/linux/clock_gettime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,21 @@
//===----------------------------------------------------------------------===//

#include "src/time/clock_gettime.h"

#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/__support/time/clock_gettime.h"
#include "src/errno/libc_errno.h"
#include "src/time/linux/clockGetTimeImpl.h"

#include <sys/syscall.h> // For syscall numbers.
#include <time.h>

namespace LIBC_NAMESPACE {

// 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_gettime(clockid, 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.
Expand Down
14 changes: 7 additions & 7 deletions libc/src/time/linux/gettimeofday.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,24 @@
//===----------------------------------------------------------------------===//

#include "src/time/gettimeofday.h"
#include "hdr/time_macros.h"
#include "hdr/types/suseconds_t.h"

#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/__support/time/clock_gettime.h"
#include "src/__support/time/units.h"
#include "src/errno/libc_errno.h"
#include "src/time/linux/clockGetTimeImpl.h"

#include <sys/syscall.h> // For syscall numbers.

namespace LIBC_NAMESPACE {

// TODO(michaelrj): Move this into time/linux with the other syscalls.
LLVM_LIBC_FUNCTION(int, gettimeofday,
(struct timeval * tv, [[maybe_unused]] void *unused)) {
using namespace time_units;
if (tv == nullptr)
return 0;

struct timespec ts;
auto result = internal::clock_gettime(CLOCK_REALTIME, &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.
Expand All @@ -34,7 +34,7 @@ LLVM_LIBC_FUNCTION(int, gettimeofday,
}

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

Expand Down
12 changes: 8 additions & 4 deletions libc/src/time/linux/time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@
//
//===----------------------------------------------------------------------===//

#include "hdr/time_macros.h"
#include "src/time/time_func.h"

#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/__support/time/clock_gettime.h"
#include "src/errno/libc_errno.h"
#include "src/time/time_func.h"
#include "src/time/linux/clockGetTimeImpl.h"

#include <sys/syscall.h> // For syscall numbers.
#include <time.h>

namespace LIBC_NAMESPACE {

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;
auto result = internal::clock_gettime(CLOCK_REALTIME, &ts);
auto result = internal::clock_gettimeimpl(CLOCK_REALTIME, &ts);
if (!result.has_value()) {
libc_errno = result.error();
return -1;
Expand Down
4 changes: 2 additions & 2 deletions libc/src/time/nanosleep.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
#ifndef LLVM_LIBC_SRC_TIME_NANOSLEEP_H
#define LLVM_LIBC_SRC_TIME_NANOSLEEP_H

#include "hdr/types/struct_timespec.h"
#include <time.h>

namespace LIBC_NAMESPACE {

int nanosleep(const timespec *req, timespec *rem);
int nanosleep(const struct timespec *req, struct timespec *rem);

} // namespace LIBC_NAMESPACE

Expand Down
2 changes: 1 addition & 1 deletion libc/src/time/time_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef LLVM_LIBC_SRC_TIME_TIME_FUNC_H
#define LLVM_LIBC_SRC_TIME_TIME_FUNC_H

#include "hdr/types/time_t.h"
#include <time.h>

// Note this header file is named time_func.h to avoid conflicts with the
// public header file time.h.
Expand Down