-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[libcxx] Support for using timespec_get #117362
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
Conversation
clock_gettime is a POSIX API that may not be available on platforms like baremetal; timespec_get is the C11 equivalent. This change adds support for using timespec_get instead of clock_gettime to improve compatibility with non-POSIX platforms. For now, this is only enabled with LLVM libc which implemented timespec_get in llvm#116102, but in the future this can be expanded to other platforms.
@llvm/pr-subscribers-libcxx @llvm/pr-subscribers-clang Author: Petr Hosek (petrhosek) Changesclock_gettime is a POSIX API that may not be available on platforms like baremetal; timespec_get is the C11 equivalent. This change adds support for using timespec_get instead of clock_gettime to improve compatibility with non-POSIX platforms. For now, this is only enabled with LLVM libc which implemented timespec_get in #116102, but in the future this can be expanded to other platforms. Related to #84879. Full diff: https://github.com/llvm/llvm-project/pull/117362.diff 3 Files Affected:
diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake
index 5af98c7b3b3fba..9355f2dfa8ee84 100644
--- a/clang/cmake/caches/Fuchsia-stage2.cmake
+++ b/clang/cmake/caches/Fuchsia-stage2.cmake
@@ -329,7 +329,7 @@ foreach(target armv6m-none-eabi;armv7m-none-eabi;armv8m.main-none-eabi)
foreach(lang C;CXX;ASM)
# TODO: The preprocessor defines workaround various issues in libc and libc++ integration.
# These should be addressed and removed over time.
- set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "--target=${target} -mthumb -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" \"-Dtimeval=struct timeval{int tv_sec; int tv_usec;}\" \"-Dgettimeofday(tv, tz)\" -D_LIBCPP_PRINT=1")
+ set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "--target=${target} -mthumb -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" -D_LIBCPP_PRINT=1")
if(${target} STREQUAL "armv8m.main-none-eabi")
set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "${RUNTIMES_${target}_CMAKE_${lang}_local_flags} -mfloat-abi=softfp -march=armv8m.main+fp+dsp -mcpu=cortex-m33" CACHE STRING "")
endif()
@@ -385,7 +385,7 @@ foreach(target riscv32-unknown-elf)
foreach(lang C;CXX;ASM)
# TODO: The preprocessor defines workaround various issues in libc and libc++ integration.
# These should be addressed and removed over time.
- set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -march=rv32imafc -mabi=ilp32f -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" \"-Dtimeval=struct timeval{int tv_sec; int tv_usec;}\" \"-Dgettimeofday(tv, tz)\" -D_LIBCPP_PRINT=1" CACHE STRING "")
+ set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -march=rv32imafc -mabi=ilp32f -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" -D_LIBCPP_PRINT=1" CACHE STRING "")
endforeach()
foreach(type SHARED;MODULE;EXE)
set(RUNTIMES_${target}_CMAKE_${type}_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "")
diff --git a/libcxx/src/chrono.cpp b/libcxx/src/chrono.cpp
index f17ea5542bd99d..8e9ad82befcf32 100644
--- a/libcxx/src/chrono.cpp
+++ b/libcxx/src/chrono.cpp
@@ -31,6 +31,10 @@
# include <sys/time.h> // for gettimeofday and timeval
#endif
+#if defined(__LLVM_LIBC__)
+# define _LIBCPP_HAS_TIMESPEC_GET
+#endif
+
// OpenBSD and GPU do not have a fully conformant suite of POSIX timers, but
// it does have clock_gettime and CLOCK_MONOTONIC which is all we need.
#if defined(__APPLE__) || defined(__gnu_hurd__) || defined(__OpenBSD__) || defined(__AMDGPU__) || \
@@ -115,6 +119,15 @@ static system_clock::time_point __libcpp_system_clock_now() {
return system_clock::time_point(duration_cast<system_clock::duration>(d - nt_to_unix_epoch));
}
+#elif defined(_LIBCPP_HAS_TIMESPEC_GET)
+
+static system_clock::time_point __libcpp_system_clock_now() {
+ struct timespec ts;
+ if (timespec_get(&ts, TIME_UTC) != TIME_UTC)
+ __throw_system_error(errno, "timespec_get(TIME_UTC) failed");
+ return system_clock::time_point(seconds(ts.tv_sec) + microseconds(ts.tv_nsec / 1000));
+}
+
#elif defined(_LIBCPP_HAS_CLOCK_GETTIME)
static system_clock::time_point __libcpp_system_clock_now() {
@@ -213,6 +226,15 @@ static steady_clock::time_point __libcpp_steady_clock_now() noexcept {
return steady_clock::time_point(nanoseconds(_zx_clock_get_monotonic()));
}
+# elif defined(_LIBCPP_HAS_TIMESPEC_GET)
+
+static steady_clock::time_point __libcpp_steady_clock_now() {
+ struct timespec ts;
+ if (timespec_get(&ts, TIME_MONOTONIC) != TIME_MONOTONIC)
+ __throw_system_error(errno, "timespec_get(TIME_MONOTONIC) failed");
+ return steady_clock::time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
+}
+
# elif defined(_LIBCPP_HAS_CLOCK_GETTIME)
static steady_clock::time_point __libcpp_steady_clock_now() {
diff --git a/libcxx/src/filesystem/filesystem_clock.cpp b/libcxx/src/filesystem/filesystem_clock.cpp
index 473a54a00f013a..b15ef4ea61632a 100644
--- a/libcxx/src/filesystem/filesystem_clock.cpp
+++ b/libcxx/src/filesystem/filesystem_clock.cpp
@@ -29,6 +29,10 @@
# include <sys/time.h> // for gettimeofday and timeval
#endif
+#if defined(__LLVM_LIBC__)
+# define _LIBCPP_HAS_TIMESPEC_GET
+#endif
+
#if defined(__APPLE__) || defined(__gnu_hurd__) || defined(__AMDGPU__) || defined(__NVPTX__) || \
(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0)
# define _LIBCPP_HAS_CLOCK_GETTIME
@@ -46,6 +50,12 @@ _FilesystemClock::time_point _FilesystemClock::now() noexcept {
GetSystemTimeAsFileTime(&time);
detail::TimeSpec tp = detail::filetime_to_timespec(time);
return time_point(__secs(tp.tv_sec) + chrono::duration_cast<duration>(__nsecs(tp.tv_nsec)));
+#elif defined(_LIBCPP_HAS_TIMESPEC_GET)
+ typedef chrono::duration<rep, nano> __nsecs;
+ struct timespec ts;
+ if (timespec_get(&ts, TIME_UTC) != TIME_UTC)
+ __throw_system_error(errno, "timespec_get(TIME_UTC) failed");
+ return time_point(__secs(ts.tv_sec) + chrono::duration_cast<duration>(__nsecs(ts.tv_nsec)));
#elif defined(_LIBCPP_HAS_CLOCK_GETTIME)
typedef chrono::duration<rep, nano> __nsecs;
struct timespec tp;
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The libc++ part LGTM. I don't really understand the Fuchsia-stage2.cmake
changes but I'm not sure I need to.
However, please rebase this on top of main
and make sure that the CI is green before you merge.
Gentle ping |
clock_gettime is a POSIX API that may not be available on platforms like baremetal; timespec_get is the C11 equivalent. This change adds support for using timespec_get instead of clock_gettime to improve compatibility with non-POSIX platforms. For now, this is only enabled with LLVM libc which implemented timespec_get in #116102, but in the future this can be expanded to other platforms.
Related to #84879.