From b03f12115e6912bd39ad388b486257d83a540ae1 Mon Sep 17 00:00:00 2001 From: Shreeyash Pandey Date: Sat, 8 Nov 2025 23:04:03 +0530 Subject: [PATCH 1/2] [libc] Add clock_gettime for Darwin 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. --- .../llvm-libc-macros/darwin/CMakeLists.txt | 5 +++ .../llvm-libc-macros/darwin/time-macros.h | 14 ++++++ libc/include/llvm-libc-macros/time-macros.h | 2 + libc/include/llvm-libc-types/clockid_t.h | 6 +++ .../include/llvm-libc-types/struct_timespec.h | 6 +++ libc/include/llvm-libc-types/struct_timeval.h | 6 +++ libc/include/llvm-libc-types/suseconds_t.h | 6 +++ libc/include/llvm-libc-types/time_t_32.h | 6 +++ libc/include/llvm-libc-types/time_t_64.h | 6 +++ libc/src/__support/time/darwin/CMakeLists.txt | 12 +++++ .../__support/time/darwin/clock_gettime.cpp | 44 +++++++++++++++++++ libc/src/time/darwin/CMakeLists.txt | 10 +++++ libc/src/time/darwin/clock_gettime.cpp | 29 ++++++++++++ .../src/__support/time/darwin/CMakeLists.txt | 8 ++++ .../__support/time/darwin/clock_gettime.cpp | 20 +++++++++ 15 files changed, 180 insertions(+) create mode 100644 libc/include/llvm-libc-macros/darwin/CMakeLists.txt create mode 100644 libc/include/llvm-libc-macros/darwin/time-macros.h create mode 100644 libc/src/__support/time/darwin/CMakeLists.txt create mode 100644 libc/src/__support/time/darwin/clock_gettime.cpp create mode 100644 libc/src/time/darwin/CMakeLists.txt create mode 100644 libc/src/time/darwin/clock_gettime.cpp create mode 100644 libc/test/src/__support/time/darwin/CMakeLists.txt create mode 100644 libc/test/src/__support/time/darwin/clock_gettime.cpp 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 +#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 +#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 +#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 +#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 +#else typedef __INT64_TYPE__ time_t; +#endif // __APPLE__ #endif // LLVM_LIBC_TYPES_TIME_T_64_H 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..158737a6251a0 --- /dev/null +++ b/libc/src/__support/time/darwin/clock_gettime.cpp @@ -0,0 +1,44 @@ +//===-- 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 // For SYS_gettimeofday +#include // For struct timezone + +namespace LIBC_NAMESPACE_DECL { +namespace internal { + +ErrorOr 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( + SYS_gettimeofday, reinterpret_cast(&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..f717d05451aca --- /dev/null +++ b/libc/src/time/darwin/clock_gettime.cpp @@ -0,0 +1,29 @@ +//===---------- 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 +using expected = LIBC_NAMESPACE::cpp::expected; + +TEST(LlvmLibcSupportDarwinClockGetTime, BasicGetTime) { + struct timespec ts; + auto result = LIBC_NAMESPACE::internal::clock_gettime(CLOCK_REALTIME, &ts); + ASSERT_TRUE(result.has_value()); +} From 2d5ba2f69fd7a431d4b2fe45fc003c1d0b469c44 Mon Sep 17 00:00:00 2001 From: Shreeyash Pandey Date: Tue, 11 Nov 2025 19:56:55 +0530 Subject: [PATCH 2/2] [libc] fix minor nits --- libc/src/__support/OSUtil/darwin/exit.cpp | 3 +-- libc/src/__support/time/darwin/clock_gettime.cpp | 6 ++---- libc/src/time/darwin/clock_gettime.cpp | 5 ++--- 3 files changed, 5 insertions(+), 9 deletions(-) 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(SYS_exit, status); - } } } // namespace internal diff --git a/libc/src/__support/time/darwin/clock_gettime.cpp b/libc/src/__support/time/darwin/clock_gettime.cpp index 158737a6251a0..aa483aa9a01d2 100644 --- a/libc/src/__support/time/darwin/clock_gettime.cpp +++ b/libc/src/__support/time/darwin/clock_gettime.cpp @@ -21,19 +21,17 @@ namespace LIBC_NAMESPACE_DECL { namespace internal { ErrorOr clock_gettime(clockid_t clockid, struct timespec *ts) { - if (clockid != CLOCK_REALTIME) { + 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( SYS_gettimeofday, reinterpret_cast(&tv), 0, 0); - if (ret != 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; diff --git a/libc/src/time/darwin/clock_gettime.cpp b/libc/src/time/darwin/clock_gettime.cpp index f717d05451aca..ecf116bbc5521 100644 --- a/libc/src/time/darwin/clock_gettime.cpp +++ b/libc/src/time/darwin/clock_gettime.cpp @@ -1,11 +1,10 @@ -//===---------- Darwin implementation of the POSIX clock_gettime function -//--===// +//===---- 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"