Skip to content

Commit 8393ea5

Browse files
authored
[libc] Implement clock_gettime for the monotonic clock on the GPU (#99067)
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.
1 parent f7cee44 commit 8393ea5

File tree

8 files changed

+61
-3
lines changed

8 files changed

+61
-3
lines changed

libc/config/gpu/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ set(TARGET_LIBC_ENTRYPOINTS
218218

219219
# time.h entrypoints
220220
libc.src.time.clock
221+
libc.src.time.clock_gettime
221222
libc.src.time.nanosleep
222223

223224
# wchar.h entrypoints

libc/docs/gpu/support.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ time.h
242242
Function Name Available RPC Required
243243
============= ========= ============
244244
clock |check|
245+
clock_gettime |check|
245246
nanosleep |check|
246247
============= ========= ============
247248

libc/include/llvm-libc-macros/gpu/time-macros.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#ifndef LLVM_LIBC_MACROS_GPU_TIME_MACROS_H
1010
#define LLVM_LIBC_MACROS_GPU_TIME_MACROS_H
1111

12+
#define CLOCK_REALTIME 0
13+
#define CLOCK_MONOTONIC 1
14+
1215
#define CLOCKS_PER_SEC 1000000
1316

1417
#endif // LLVM_LIBC_MACROS_GPU_TIME_MACROS_H

libc/include/time.h.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
#include "__llvm-libc-common.h"
1313
#include "llvm-libc-macros/time-macros.h"
14+
#include "llvm-libc-types/clock_t.h"
15+
#include "llvm-libc-types/clockid_t.h"
1416

1517
%%public_api()
1618

libc/src/time/gpu/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,15 @@ add_entrypoint_object(
3232
libc.src.__support.GPU.utils
3333
.time_utils
3434
)
35+
36+
add_entrypoint_object(
37+
clock_gettime
38+
SRCS
39+
clock_gettime.cpp
40+
HDRS
41+
../clock_gettime.h
42+
DEPENDS
43+
libc.hdr.types.clockid_t
44+
libc.hdr.types.struct_timespec
45+
.time_utils
46+
)

libc/src/time/gpu/clock_gettime.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===---------- GPU implementation of the POSIX clock_gettime function ----===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/time/clock_gettime.h"
10+
11+
#include "src/__support/common.h"
12+
#include "src/__support/macros/config.h"
13+
#include "time_utils.h"
14+
15+
namespace LIBC_NAMESPACE_DECL {
16+
17+
constexpr uint64_t TICKS_PER_SEC = 1000000000UL;
18+
19+
LLVM_LIBC_FUNCTION(int, clock_gettime, (clockid_t clockid, timespec *ts)) {
20+
if (clockid != CLOCK_MONOTONIC || !ts)
21+
return -1;
22+
23+
uint64_t ns_per_tick = TICKS_PER_SEC / GPU_CLOCKS_PER_SEC;
24+
uint64_t ticks = gpu::fixed_frequency_clock();
25+
26+
ts->tv_nsec = (ticks * ns_per_tick) % TICKS_PER_SEC;
27+
ts->tv_sec = (ticks * ns_per_tick) / TICKS_PER_SEC;
28+
29+
return 0;
30+
}
31+
32+
} // namespace LIBC_NAMESPACE_DECL

libc/test/src/time/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ add_libc_unittest(
3030
libc.src.time.asctime_r
3131
)
3232

33-
add_libc_unittest(
33+
add_libc_test(
3434
clock_gettime_test
3535
SUITE
3636
libc_time_unittests

libc/test/src/time/clock_gettime_test.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,29 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "src/__support/macros/properties/architectures.h"
910
#include "src/time/clock_gettime.h"
1011
#include "test/UnitTest/Test.h"
1112

1213
#include <time.h>
1314

1415
TEST(LlvmLibcClockGetTime, RealTime) {
15-
struct timespec tp;
16+
timespec tp;
1617
int result;
1718
result = LIBC_NAMESPACE::clock_gettime(CLOCK_REALTIME, &tp);
19+
// The GPU does not implement CLOCK_REALTIME but provides it so programs will
20+
// compile.
21+
#ifdef LIBC_TARGET_ARCH_IS_GPU
22+
ASSERT_EQ(result, -1);
23+
#else
1824
ASSERT_EQ(result, 0);
1925
ASSERT_GT(tp.tv_sec, time_t(0));
26+
#endif
2027
}
2128

2229
#ifdef CLOCK_MONOTONIC
2330
TEST(LlvmLibcClockGetTime, MonotonicTime) {
24-
struct timespec tp1, tp2;
31+
timespec tp1, tp2;
2532
int result;
2633
result = LIBC_NAMESPACE::clock_gettime(CLOCK_MONOTONIC, &tp1);
2734
ASSERT_EQ(result, 0);

0 commit comments

Comments
 (0)