Skip to content

Commit

Permalink
[libc] Implement clock_gettime for the monotonic clock on the GPU
Browse files Browse the repository at this point in the history
Summary:
This patch implements `clock_gettime` using the monotonic clock. This
allows users to get time elapsed at nanosecond resolution. This is
primarily to facilitate compiling the `chrono` library from `libc++`.
For this reason we provide both `CLOCK_MONOTONIC`, which we can implement
with the GPU's global fixed-frequency clock, and `CLOCK_REALTIME` which
we cannot. The latter is provided just to make people who use this
header happy and it will always return failure.
  • Loading branch information
jhuber6 committed Jul 16, 2024
1 parent 3cdbb8d commit 4f97696
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 3 deletions.
1 change: 1 addition & 0 deletions libc/config/gpu/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ set(TARGET_LIBC_ENTRYPOINTS

# time.h entrypoints
libc.src.time.clock
libc.src.time.clock_gettime
libc.src.time.nanosleep

# wchar.h entrypoints
Expand Down
1 change: 1 addition & 0 deletions libc/docs/gpu/support.rst
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ time.h
Function Name Available RPC Required
============= ========= ============
clock |check|
clock_gettime |check|
nanosleep |check|
============= ========= ============

Expand Down
3 changes: 3 additions & 0 deletions libc/include/llvm-libc-macros/gpu/time-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#ifndef LLVM_LIBC_MACROS_GPU_TIME_MACROS_H
#define LLVM_LIBC_MACROS_GPU_TIME_MACROS_H

#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1

#define CLOCKS_PER_SEC 1000000

#endif // LLVM_LIBC_MACROS_GPU_TIME_MACROS_H
2 changes: 2 additions & 0 deletions libc/include/time.h.def
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#include "__llvm-libc-common.h"
#include "llvm-libc-macros/time-macros.h"
#include "llvm-libc-types/clock_t.h"
#include "llvm-libc-types/clockid_t.h"

%%public_api()

Expand Down
12 changes: 12 additions & 0 deletions libc/src/time/gpu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,15 @@ add_entrypoint_object(
libc.src.__support.GPU.utils
.time_utils
)

add_entrypoint_object(
clock_gettime
SRCS
clock_gettime.cpp
HDRS
../clock_gettime.h
DEPENDS
libc.hdr.types.clockid_t
libc.hdr.types.struct_timespec
.time_utils
)
32 changes: 32 additions & 0 deletions libc/src/time/gpu/clock_gettime.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===---------- GPU 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/common.h"
#include "src/__support/macros/config.h"
#include "time_utils.h"

namespace LIBC_NAMESPACE_DECL {

constexpr uint64_t TICKS_PER_SEC = 1000000000UL;

LLVM_LIBC_FUNCTION(int, clock_gettime, (clockid_t clockid, timespec *ts)) {
if (clockid != CLOCK_MONOTONIC || !ts)
return -1;

uint64_t ns_per_tick = TICKS_PER_SEC / GPU_CLOCKS_PER_SEC;
uint64_t ticks = gpu::fixed_frequency_clock();

ts->tv_nsec = (ticks * ns_per_tick) % TICKS_PER_SEC;
ts->tv_sec = (ticks * ns_per_tick) / TICKS_PER_SEC;

return 0;
}

} // namespace LIBC_NAMESPACE_DECL
2 changes: 1 addition & 1 deletion libc/test/src/time/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ add_libc_unittest(
libc.src.time.asctime_r
)

add_libc_unittest(
add_libc_test(
clock_gettime_test
SUITE
libc_time_unittests
Expand Down
11 changes: 9 additions & 2 deletions libc/test/src/time/clock_gettime_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,29 @@
//
//===----------------------------------------------------------------------===//

#include "src/__support/macros/properties/architectures.h"
#include "src/time/clock_gettime.h"
#include "test/UnitTest/Test.h"

#include <time.h>

TEST(LlvmLibcClockGetTime, RealTime) {
struct timespec tp;
timespec tp;
int result;
result = LIBC_NAMESPACE::clock_gettime(CLOCK_REALTIME, &tp);
// The GPU does not implement CLOCK_REALTIME but provides it so programs will
// compile.
#ifdef LIBC_TARGET_ARCH_IS_GPU
ASSERT_EQ(result, -1);
#else
ASSERT_EQ(result, 0);
ASSERT_GT(tp.tv_sec, time_t(0));
#endif
}

#ifdef CLOCK_MONOTONIC
TEST(LlvmLibcClockGetTime, MonotonicTime) {
struct timespec tp1, tp2;
timespec tp1, tp2;
int result;
result = LIBC_NAMESPACE::clock_gettime(CLOCK_MONOTONIC, &tp1);
ASSERT_EQ(result, 0);
Expand Down

0 comments on commit 4f97696

Please sign in to comment.