Skip to content
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

[libc] Implement clock_gettime for the monotonic clock on the GPU #99067

Merged
merged 1 commit into from
Jul 16, 2024

Conversation

jhuber6
Copy link
Contributor

@jhuber6 jhuber6 commented Jul 16, 2024

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.

@llvmbot
Copy link
Collaborator

llvmbot commented Jul 16, 2024

@llvm/pr-subscribers-libc

Author: Joseph Huber (jhuber6)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/99067.diff

8 Files Affected:

  • (modified) libc/config/gpu/entrypoints.txt (+1)
  • (modified) libc/docs/gpu/support.rst (+1)
  • (modified) libc/include/llvm-libc-macros/gpu/time-macros.h (+3)
  • (modified) libc/include/time.h.def (+2)
  • (modified) libc/src/time/gpu/CMakeLists.txt (+12)
  • (added) libc/src/time/gpu/clock_gettime.cpp (+33)
  • (modified) libc/test/src/time/CMakeLists.txt (+1-1)
  • (modified) libc/test/src/time/clock_gettime_test.cpp (+7)
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

Copy link

github-actions bot commented Jul 16, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff 3cdbb8d74d6fbd298ad4d7d283a3c7bba008e8ef d52779f59adff528b34fdeb8c8e14a557352b759 --extensions cpp,h -- libc/src/time/gpu/clock_gettime.cpp libc/include/llvm-libc-macros/gpu/time-macros.h libc/test/src/time/clock_gettime_test.cpp
View the diff from clang-format here.
diff --git a/libc/src/time/gpu/clock_gettime.cpp b/libc/src/time/gpu/clock_gettime.cpp
index 7241d5b6e8..de7899a2a1 100644
--- a/libc/src/time/gpu/clock_gettime.cpp
+++ b/libc/src/time/gpu/clock_gettime.cpp
@@ -16,8 +16,7 @@ namespace LIBC_NAMESPACE_DECL {
 
 constexpr uint64_t TICKS_PER_SEC = 1000000000UL;
 
-LLVM_LIBC_FUNCTION(int, clock_gettime,
-                   (clockid_t clockid, timespec *ts)) {
+LLVM_LIBC_FUNCTION(int, clock_gettime, (clockid_t clockid, timespec *ts)) {
   if (clockid != CLOCK_MONOTONIC || !ts)
     return -1;
 

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.
@jhuber6 jhuber6 merged commit 8393ea5 into llvm:main Jul 16, 2024
5 of 6 checks passed
sgundapa pushed a commit to sgundapa/upstream_effort that referenced this pull request Jul 23, 2024
…lvm#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.
yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants