[libc-commits] [libc] [libc] Implement `clock_gettime` for the monotonic clock on the GPU (PR #99067)

Joseph Huber via libc-commits libc-commits at lists.llvm.org
Tue Jul 16 12:50:55 PDT 2024


https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/99067

>From 8e4d424ec47fb54823416eec9521f726b687c0bf Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Tue, 16 Jul 2024 12:38:13 -0500
Subject: [PATCH 1/3] [libc] Implement `clock_gettime` for the monotonic clock
 on the GPU

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.
---
 libc/config/gpu/entrypoints.txt               |  1 +
 libc/docs/gpu/support.rst                     |  1 +
 .../llvm-libc-macros/gpu/time-macros.h        |  3 ++
 libc/include/time.h.def                       |  2 ++
 libc/src/time/gpu/CMakeLists.txt              | 12 +++++++
 libc/src/time/gpu/clock_gettime.cpp           | 33 +++++++++++++++++++
 libc/test/src/time/CMakeLists.txt             |  2 +-
 libc/test/src/time/clock_gettime_test.cpp     |  7 ++++
 8 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 libc/src/time/gpu/clock_gettime.cpp

diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt
index 63228216c85ec..457018beaf0a3 100644
--- a/libc/config/gpu/entrypoints.txt
+++ b/libc/config/gpu/entrypoints.txt
@@ -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
diff --git a/libc/docs/gpu/support.rst b/libc/docs/gpu/support.rst
index 6e2c8c7e93987..89ea4d588a16f 100644
--- a/libc/docs/gpu/support.rst
+++ b/libc/docs/gpu/support.rst
@@ -242,6 +242,7 @@ time.h
 Function Name  Available  RPC Required
 =============  =========  ============
 clock          |check|
+clock_gettime  |check|
 nanosleep      |check|
 =============  =========  ============
 
diff --git a/libc/include/llvm-libc-macros/gpu/time-macros.h b/libc/include/llvm-libc-macros/gpu/time-macros.h
index c3dc812f90a3b..7142a3e1b2764 100644
--- a/libc/include/llvm-libc-macros/gpu/time-macros.h
+++ b/libc/include/llvm-libc-macros/gpu/time-macros.h
@@ -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
diff --git a/libc/include/time.h.def b/libc/include/time.h.def
index 2355e8822fad7..3776dfcadad28 100644
--- a/libc/include/time.h.def
+++ b/libc/include/time.h.def
@@ -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()
 
diff --git a/libc/src/time/gpu/CMakeLists.txt b/libc/src/time/gpu/CMakeLists.txt
index 088271d881911..c9b4562815801 100644
--- a/libc/src/time/gpu/CMakeLists.txt
+++ b/libc/src/time/gpu/CMakeLists.txt
@@ -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
+)
diff --git a/libc/src/time/gpu/clock_gettime.cpp b/libc/src/time/gpu/clock_gettime.cpp
new file mode 100644
index 0000000000000..fd36b7fcb05e2
--- /dev/null
+++ b/libc/src/time/gpu/clock_gettime.cpp
@@ -0,0 +1,33 @@
+//===---------- 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, struct 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
diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index 51cacef0a62fe..78cfe8f301615 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -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
diff --git a/libc/test/src/time/clock_gettime_test.cpp b/libc/test/src/time/clock_gettime_test.cpp
index 6367ae7145a47..8ae2a503e0926 100644
--- a/libc/test/src/time/clock_gettime_test.cpp
+++ b/libc/test/src/time/clock_gettime_test.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/macros/properties/architectures.h"
 #include "src/time/clock_gettime.h"
 #include "test/UnitTest/Test.h"
 
@@ -15,8 +16,14 @@ TEST(LlvmLibcClockGetTime, RealTime) {
   struct 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

>From 5e6da5b66b65c29aff7ae49245e9a3371bf6d092 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Tue, 16 Jul 2024 14:50:22 -0500
Subject: [PATCH 2/3] Update libc/src/time/gpu/clock_gettime.cpp

---
 libc/src/time/gpu/clock_gettime.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/time/gpu/clock_gettime.cpp b/libc/src/time/gpu/clock_gettime.cpp
index fd36b7fcb05e2..7241d5b6e82d2 100644
--- a/libc/src/time/gpu/clock_gettime.cpp
+++ b/libc/src/time/gpu/clock_gettime.cpp
@@ -17,7 +17,7 @@ namespace LIBC_NAMESPACE_DECL {
 constexpr uint64_t TICKS_PER_SEC = 1000000000UL;
 
 LLVM_LIBC_FUNCTION(int, clock_gettime,
-                   (clockid_t clockid, struct timespec *ts)) {
+                   (clockid_t clockid, timespec *ts)) {
   if (clockid != CLOCK_MONOTONIC || !ts)
     return -1;
 

>From d52779f59adff528b34fdeb8c8e14a557352b759 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Tue, 16 Jul 2024 14:50:48 -0500
Subject: [PATCH 3/3] Update libc/test/src/time/clock_gettime_test.cpp

---
 libc/test/src/time/clock_gettime_test.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/test/src/time/clock_gettime_test.cpp b/libc/test/src/time/clock_gettime_test.cpp
index 8ae2a503e0926..f0964640ffdf0 100644
--- a/libc/test/src/time/clock_gettime_test.cpp
+++ b/libc/test/src/time/clock_gettime_test.cpp
@@ -13,7 +13,6 @@
 #include <time.h>
 
 TEST(LlvmLibcClockGetTime, RealTime) {
-  struct 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



More information about the libc-commits mailing list