[libc-commits] [libc] [libc] Add clock_gettime for Darwin (PR #167160)

via libc-commits libc-commits at lists.llvm.org
Fri Nov 28 06:19:38 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Shreeyash Pandey (bojle)

<details>
<summary>Changes</summary>

This patch adds support for clock_gettime for Darwin. Darwin syscall
'gettimeofday' is used to query the time from the system.

Many headers in llvm-libc-types, namely clockid_t, struct_timespec,
struct_timeval, suseconds_t, time_t_32, time_t_64, are modified to include
header guards as Darwin has its own implementation of primitive types.


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


16 Files Affected:

- (added) libc/include/llvm-libc-macros/darwin/CMakeLists.txt (+5) 
- (added) libc/include/llvm-libc-macros/darwin/time-macros.h (+14) 
- (modified) libc/include/llvm-libc-macros/time-macros.h (+2) 
- (modified) libc/include/llvm-libc-types/clockid_t.h (+6) 
- (modified) libc/include/llvm-libc-types/struct_timespec.h (+6) 
- (modified) libc/include/llvm-libc-types/struct_timeval.h (+6) 
- (modified) libc/include/llvm-libc-types/suseconds_t.h (+6) 
- (modified) libc/include/llvm-libc-types/time_t_32.h (+6) 
- (modified) libc/include/llvm-libc-types/time_t_64.h (+6) 
- (modified) libc/src/__support/OSUtil/darwin/exit.cpp (+1-2) 
- (added) libc/src/__support/time/darwin/CMakeLists.txt (+12) 
- (added) libc/src/__support/time/darwin/clock_gettime.cpp (+42) 
- (added) libc/src/time/darwin/CMakeLists.txt (+10) 
- (added) libc/src/time/darwin/clock_gettime.cpp (+28) 
- (added) libc/test/src/__support/time/darwin/CMakeLists.txt (+8) 
- (added) libc/test/src/__support/time/darwin/clock_gettime.cpp (+20) 


``````````diff
diff --git a/libc/include/llvm-libc-macros/darwin/CMakeLists.txt b/libc/include/llvm-libc-macros/darwin/CMakeLists.txt
new file mode 100644
index 0000000000000..ea08c63c00301
--- /dev/null
+++ b/libc/include/llvm-libc-macros/darwin/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_header(
+  time_macros
+  HDR
+    time-macros.h
+)
diff --git a/libc/include/llvm-libc-macros/darwin/time-macros.h b/libc/include/llvm-libc-macros/darwin/time-macros.h
new file mode 100644
index 0000000000000..477dfa8eda85f
--- /dev/null
+++ b/libc/include/llvm-libc-macros/darwin/time-macros.h
@@ -0,0 +1,14 @@
+//===-- Definition of macros from time.h ---------------------------------===//
+//
+// 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_MACROS_LINUX_TIME_MACROS_H
+#define LLVM_LIBC_MACROS_LINUX_TIME_MACROS_H
+
+#include <_time.h>
+
+#endif // LLVM_LIBC_MACROS_LINUX_TIME_MACROS_H
diff --git a/libc/include/llvm-libc-macros/time-macros.h b/libc/include/llvm-libc-macros/time-macros.h
index 30e0a310a5485..c026df29b1e7f 100644
--- a/libc/include/llvm-libc-macros/time-macros.h
+++ b/libc/include/llvm-libc-macros/time-macros.h
@@ -7,6 +7,8 @@
 #include "linux/time-macros.h"
 #elif defined(__ELF__)
 #include "baremetal/time-macros.h"
+#elif defined(__APPLE__)
+#include "darwin/time-macros.h"
 #else
 #define CLOCKS_PER_SEC 1000000
 #endif
diff --git a/libc/include/llvm-libc-types/clockid_t.h b/libc/include/llvm-libc-types/clockid_t.h
index 4b059599502c4..926948717c664 100644
--- a/libc/include/llvm-libc-types/clockid_t.h
+++ b/libc/include/llvm-libc-types/clockid_t.h
@@ -9,6 +9,12 @@
 #ifndef LLVM_LIBC_TYPES_CLOCKID_T_H
 #define LLVM_LIBC_TYPES_CLOCKID_T_H
 
+#if defined(__APPLE__)
+// Darwin provides its own defintion for clockid_t . Use that to prevent
+// redeclaration errors and correctness.
+#include <_time.h>
+#else
 typedef int clockid_t;
+#endif // __APPLE__
 
 #endif // LLVM_LIBC_TYPES_CLOCKID_T_H
diff --git a/libc/include/llvm-libc-types/struct_timespec.h b/libc/include/llvm-libc-types/struct_timespec.h
index 28b5a571f6790..8993ecc7db8f0 100644
--- a/libc/include/llvm-libc-types/struct_timespec.h
+++ b/libc/include/llvm-libc-types/struct_timespec.h
@@ -9,6 +9,11 @@
 #ifndef LLVM_LIBC_TYPES_STRUCT_TIMESPEC_H
 #define LLVM_LIBC_TYPES_STRUCT_TIMESPEC_H
 
+#if defined(__APPLE__)
+// Darwin provides its own definition for struct timespec. Include it directly
+// to ensure type compatibility and avoid redefinition errors.
+#include <sys/_types/_timespec.h>
+#else
 #include "time_t.h"
 
 struct timespec {
@@ -16,5 +21,6 @@ struct timespec {
   /* TODO: BIG_ENDIAN may require padding. */
   long tv_nsec; /* Nanoseconds.  */
 };
+#endif // __APPLE__
 
 #endif // LLVM_LIBC_TYPES_STRUCT_TIMESPEC_H
diff --git a/libc/include/llvm-libc-types/struct_timeval.h b/libc/include/llvm-libc-types/struct_timeval.h
index 9595d85a46c8f..41f0b4e92932e 100644
--- a/libc/include/llvm-libc-types/struct_timeval.h
+++ b/libc/include/llvm-libc-types/struct_timeval.h
@@ -12,9 +12,15 @@
 #include "suseconds_t.h"
 #include "time_t.h"
 
+#if defined(__APPLE__)
+// Darwin provides its own definition for struct timeval. Include it directly
+// to ensure type compatibility and avoid redefinition errors.
+#include <sys/_types/_timeval.h>
+#else
 struct timeval {
   time_t tv_sec;       // Seconds
   suseconds_t tv_usec; // Micro seconds
 };
+#endif // __APPLE__
 
 #endif // LLVM_LIBC_TYPES_STRUCT_TIMEVAL_H
diff --git a/libc/include/llvm-libc-types/suseconds_t.h b/libc/include/llvm-libc-types/suseconds_t.h
index 8e926e8401f5c..acc1822cb59e1 100644
--- a/libc/include/llvm-libc-types/suseconds_t.h
+++ b/libc/include/llvm-libc-types/suseconds_t.h
@@ -14,6 +14,12 @@
 // types...] and suseconds_t are no greater than the width of type long.
 
 // The kernel expects 64 bit suseconds_t at least on x86_64.
+#if defined(__APPLE__)
+// Darwin provides its own definition for suseconds_t. Include it directly
+// to ensure type compatibility and avoid redefinition errors.
+#include <sys/_types/_suseconds_t.h>
+#else
 typedef long suseconds_t;
+#endif // __APPLE__
 
 #endif // LLVM_LIBC_TYPES_SUSECONDS_T_H
diff --git a/libc/include/llvm-libc-types/time_t_32.h b/libc/include/llvm-libc-types/time_t_32.h
index 2c415f6fa9dca..8d7a81e5ce7f7 100644
--- a/libc/include/llvm-libc-types/time_t_32.h
+++ b/libc/include/llvm-libc-types/time_t_32.h
@@ -9,6 +9,12 @@
 #ifndef LLVM_LIBC_TYPES_TIME_T_32_H
 #define LLVM_LIBC_TYPES_TIME_T_32_H
 
+#if defined(__APPLE__)
+// Darwin provides its own definition for time_t. Include it directly
+// to ensure type compatibility and avoid redefinition errors.
+#include <sys/_types/_time_t.h>
+#else
 typedef __INT32_TYPE__ time_t;
+#endif // __APPLE__
 
 #endif // LLVM_LIBC_TYPES_TIME_T_32_H
diff --git a/libc/include/llvm-libc-types/time_t_64.h b/libc/include/llvm-libc-types/time_t_64.h
index 8f7fd3233646e..c8267abe31289 100644
--- a/libc/include/llvm-libc-types/time_t_64.h
+++ b/libc/include/llvm-libc-types/time_t_64.h
@@ -9,6 +9,12 @@
 #ifndef LLVM_LIBC_TYPES_TIME_T_64_H
 #define LLVM_LIBC_TYPES_TIME_T_64_H
 
+#if defined(__APPLE__)
+// Darwin provides its own definition for time_t. Include it directly
+// to ensure type compatibility and avoid redefinition errors.
+#include <sys/_types/_time_t.h>
+#else
 typedef __INT64_TYPE__ time_t;
+#endif // __APPLE__
 
 #endif // LLVM_LIBC_TYPES_TIME_T_64_H
diff --git a/libc/src/__support/OSUtil/darwin/exit.cpp b/libc/src/__support/OSUtil/darwin/exit.cpp
index 7439db2ef38b0..a5fa4a7522189 100644
--- a/libc/src/__support/OSUtil/darwin/exit.cpp
+++ b/libc/src/__support/OSUtil/darwin/exit.cpp
@@ -15,9 +15,8 @@ namespace LIBC_NAMESPACE_DECL {
 namespace internal {
 
 [[noreturn]] void exit(int status) {
-  for (;;) {
+  for (;;)
     LIBC_NAMESPACE::syscall_impl<long>(SYS_exit, status);
-  }
 }
 
 } // namespace internal
diff --git a/libc/src/__support/time/darwin/CMakeLists.txt b/libc/src/__support/time/darwin/CMakeLists.txt
new file mode 100644
index 0000000000000..a06a41289a41c
--- /dev/null
+++ b/libc/src/__support/time/darwin/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_object_library(
+  clock_gettime
+  SRCS
+    clock_gettime.cpp
+  HDRS
+    ../clock_gettime.h
+  DEPENDS
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.hdr.types.struct_timeval
+    libc.hdr.types.struct_timespec
+)
diff --git a/libc/src/__support/time/darwin/clock_gettime.cpp b/libc/src/__support/time/darwin/clock_gettime.cpp
new file mode 100644
index 0000000000000..aa483aa9a01d2
--- /dev/null
+++ b/libc/src/__support/time/darwin/clock_gettime.cpp
@@ -0,0 +1,42 @@
+//===-- Darwin implementation of internal clock_gettime -------------------===//
+//
+// 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/__support/time/clock_gettime.h"
+#include "hdr/errno_macros.h" // For EINVAL
+#include "hdr/time_macros.h"
+#include "hdr/types/struct_timespec.h"
+#include "hdr/types/struct_timeval.h"
+#include "src/__support/OSUtil/syscall.h" // For syscall_impl
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include <sys/syscall.h> // For SYS_gettimeofday
+#include <sys/time.h>    // For struct timezone
+
+namespace LIBC_NAMESPACE_DECL {
+namespace internal {
+
+ErrorOr<int> clock_gettime(clockid_t clockid, struct timespec *ts) {
+  if (clockid != CLOCK_REALTIME)
+    return Error(EINVAL);
+  struct timeval tv;
+  // The second argument to gettimeofday is a timezone pointer
+  // The third argument is mach_absolute_time
+  // Both of these, we don't need here, so they are 0
+  long ret = LIBC_NAMESPACE::syscall_impl<long>(
+      SYS_gettimeofday, reinterpret_cast<long>(&tv), 0, 0);
+  if (ret != 0)
+    // The syscall returns -1 on error and sets errno.
+    return Error(EINVAL);
+
+  ts->tv_sec = tv.tv_sec;
+  ts->tv_nsec = tv.tv_usec * 1000;
+  return 0;
+}
+
+} // namespace internal
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/darwin/CMakeLists.txt b/libc/src/time/darwin/CMakeLists.txt
new file mode 100644
index 0000000000000..6d68086c72584
--- /dev/null
+++ b/libc/src/time/darwin/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_entrypoint_object(
+  clock_gettime
+  SRCS
+    clock_gettime.cpp
+  HDRS
+    # The public header is part of the parent directory's library.
+  DEPENDS
+    libc.src.__support.time.clock_gettime
+    libc.src.errno.errno
+)
diff --git a/libc/src/time/darwin/clock_gettime.cpp b/libc/src/time/darwin/clock_gettime.cpp
new file mode 100644
index 0000000000000..ecf116bbc5521
--- /dev/null
+++ b/libc/src/time/darwin/clock_gettime.cpp
@@ -0,0 +1,28 @@
+//===---- Darwin 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/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/time/clock_gettime.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, clock_gettime,
+                   (clockid_t clockid, struct timespec *ts)) {
+  auto result = internal::clock_gettime(clockid, ts);
+  if (!result.has_value()) {
+    libc_errno = result.error();
+    return -1;
+  }
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/__support/time/darwin/CMakeLists.txt b/libc/test/src/__support/time/darwin/CMakeLists.txt
new file mode 100644
index 0000000000000..ee1247b354173
--- /dev/null
+++ b/libc/test/src/__support/time/darwin/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_libc_test(
+  clock_gettime
+  SUITE libc-support-time-tests
+  SRCS clock_gettime.cpp
+  DEPENDS
+    libc.src.__support.CPP.expected
+    libc.src.__support.time.darwin.clock_gettime
+)
diff --git a/libc/test/src/__support/time/darwin/clock_gettime.cpp b/libc/test/src/__support/time/darwin/clock_gettime.cpp
new file mode 100644
index 0000000000000..d593c5d02744a
--- /dev/null
+++ b/libc/test/src/__support/time/darwin/clock_gettime.cpp
@@ -0,0 +1,20 @@
+//===-- unit tests for darwin's time utilities --------------------------===//
+//
+// 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/__support/time/clock_gettime.h"
+#include "src/__support/CPP/expected.h"
+#include "test/UnitTest/Test.h"
+
+template <class T, class E>
+using expected = LIBC_NAMESPACE::cpp::expected<T, E>;
+
+TEST(LlvmLibcSupportDarwinClockGetTime, BasicGetTime) {
+  struct timespec ts;
+  auto result = LIBC_NAMESPACE::internal::clock_gettime(CLOCK_REALTIME, &ts);
+  ASSERT_TRUE(result.has_value());
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/167160


More information about the libc-commits mailing list