diff options
| author | Michael Kruse <llvm-project@meinersbur.de> | 2025-01-03 10:22:51 +0100 |
|---|---|---|
| committer | Michael Kruse <llvm-project@meinersbur.de> | 2025-01-03 10:22:51 +0100 |
| commit | 38500d63e14ce340236840f60d356cdefb56a52c (patch) | |
| tree | 17edbec446ce9b50d2f215a483b83afb293a635d /libc/src/time | |
| parent | 1a3d5daaef7a6a63448a497da3eff7fc9e23df26 (diff) | |
| parent | 27f30029741ecf023baece7b3dde1ff9011ffefc (diff) | |
Merge branch 'main' into users/meinersbur/flang_runtime_split-headersusers/meinersbur/flang_runtime_split-headers
Diffstat (limited to 'libc/src/time')
| -rw-r--r-- | libc/src/time/CMakeLists.txt | 17 | ||||
| -rw-r--r-- | libc/src/time/clock_getres.h | 21 | ||||
| -rw-r--r-- | libc/src/time/gpu/CMakeLists.txt | 36 | ||||
| -rw-r--r-- | libc/src/time/gpu/clock.cpp | 2 | ||||
| -rw-r--r-- | libc/src/time/gpu/clock_gettime.cpp | 19 | ||||
| -rw-r--r-- | libc/src/time/gpu/nanosleep.cpp | 4 | ||||
| -rw-r--r-- | libc/src/time/gpu/time_utils.cpp | 22 | ||||
| -rw-r--r-- | libc/src/time/gpu/time_utils.h | 43 | ||||
| -rw-r--r-- | libc/src/time/gpu/timespec_get.cpp | 1 | ||||
| -rw-r--r-- | libc/src/time/linux/CMakeLists.txt | 21 | ||||
| -rw-r--r-- | libc/src/time/linux/clock.cpp | 2 | ||||
| -rw-r--r-- | libc/src/time/linux/clock_gettime.cpp | 2 | ||||
| -rw-r--r-- | libc/src/time/linux/gettimeofday.cpp | 2 | ||||
| -rw-r--r-- | libc/src/time/linux/timespec_get.cpp | 2 | ||||
| -rw-r--r-- | libc/src/time/time.cpp (renamed from libc/src/time/linux/time.cpp) | 8 | ||||
| -rw-r--r-- | libc/src/time/windows/CMakeLists.txt | 13 | ||||
| -rw-r--r-- | libc/src/time/windows/clock_getres.cpp | 110 |
17 files changed, 194 insertions, 131 deletions
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt index f18e74a15e6f..ae835dcc7427 100644 --- a/libc/src/time/CMakeLists.txt +++ b/libc/src/time/CMakeLists.txt @@ -106,9 +106,15 @@ add_entrypoint_object( add_entrypoint_object( time - ALIAS + SRCS + time.cpp + HDRS + time_func.h DEPENDS - .${LIBC_TARGET_OS}.time + libc.hdr.time_macros + libc.hdr.types.time_t + libc.src.__support.time.clock_gettime + libc.src.errno.errno ) add_entrypoint_object( @@ -145,3 +151,10 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.gettimeofday ) + +add_entrypoint_object( + clock_getres + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.clock_getres +) diff --git a/libc/src/time/clock_getres.h b/libc/src/time/clock_getres.h new file mode 100644 index 000000000000..c1c581c53599 --- /dev/null +++ b/libc/src/time/clock_getres.h @@ -0,0 +1,21 @@ +//===-- Implementation header of clock_getres -------------------*- C++ -*-===// +// +// 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_SRC_TIME_CLOCK_GETRES_H +#define LLVM_LIBC_SRC_TIME_CLOCK_GETRES_H + +#include "hdr/types/clockid_t.h" +#include "hdr/types/struct_timespec.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +int clock_getres(clockid_t clockid, timespec *tp); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_TIME_CLOCK_GETRES_H diff --git a/libc/src/time/gpu/CMakeLists.txt b/libc/src/time/gpu/CMakeLists.txt index 8da5d3a22f5a..31a60595d68f 100644 --- a/libc/src/time/gpu/CMakeLists.txt +++ b/libc/src/time/gpu/CMakeLists.txt @@ -1,14 +1,3 @@ -add_object_library( - time_utils - SRCS - time_utils.cpp - HDRS - time_utils.h - DEPENDS - libc.hdr.types.clock_t - libc.hdr.time_macros -) - add_entrypoint_object( clock SRCS @@ -18,7 +7,8 @@ add_entrypoint_object( DEPENDS libc.include.time libc.src.__support.GPU.utils - .time_utils + libc.src.__support.time.clock_gettime + libc.src.__support.time.gpu.time_utils ) add_entrypoint_object( @@ -30,29 +20,31 @@ add_entrypoint_object( DEPENDS libc.include.time libc.src.__support.GPU.utils - .time_utils + libc.src.__support.time.gpu.time_utils ) add_entrypoint_object( - clock_gettime + timespec_get SRCS - clock_gettime.cpp + timespec_get.cpp HDRS - ../clock_gettime.h + ../timespec_get.h DEPENDS - libc.hdr.types.clockid_t + libc.hdr.time_macros libc.hdr.types.struct_timespec - .time_utils + libc.src.__support.time.gpu.time_utils ) add_entrypoint_object( - timespec_get + clock_gettime SRCS - timespec_get.cpp + clock_gettime.cpp HDRS - ../timespec_get.h + ../clock_gettime.h DEPENDS libc.hdr.time_macros + libc.hdr.types.clockid_t libc.hdr.types.struct_timespec - .time_utils + libc.src.__support.time.gpu.time_utils + libc.src.__support.time.clock_gettime ) diff --git a/libc/src/time/gpu/clock.cpp b/libc/src/time/gpu/clock.cpp index 4cdb1d505aed..add5b2725ef8 100644 --- a/libc/src/time/gpu/clock.cpp +++ b/libc/src/time/gpu/clock.cpp @@ -8,7 +8,7 @@ #include "src/time/clock.h" #include "src/__support/macros/config.h" -#include "src/time/gpu/time_utils.h" +#include "src/__support/time/gpu/time_utils.h" namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/time/gpu/clock_gettime.cpp b/libc/src/time/gpu/clock_gettime.cpp index de7899a2a17c..81547ef7f1ca 100644 --- a/libc/src/time/gpu/clock_gettime.cpp +++ b/libc/src/time/gpu/clock_gettime.cpp @@ -10,23 +10,16 @@ #include "src/__support/common.h" #include "src/__support/macros/config.h" -#include "time_utils.h" +#include "src/__support/time/clock_gettime.h" +#include "src/__support/time/gpu/time_utils.h" namespace LIBC_NAMESPACE_DECL { -constexpr uint64_t TICKS_PER_SEC = 1000000000UL; - LLVM_LIBC_FUNCTION(int, clock_gettime, (clockid_t clockid, 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; + ErrorOr<int> result = internal::clock_gettime(clockid, ts); + if (result) + return result.value(); + return result.error(); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/gpu/nanosleep.cpp b/libc/src/time/gpu/nanosleep.cpp index 3f4a609dd40e..a92f660f225c 100644 --- a/libc/src/time/gpu/nanosleep.cpp +++ b/libc/src/time/gpu/nanosleep.cpp @@ -9,12 +9,10 @@ #include "src/time/nanosleep.h" #include "src/__support/macros/config.h" -#include "time_utils.h" +#include "src/__support/time/gpu/time_utils.h" namespace LIBC_NAMESPACE_DECL { -constexpr uint64_t TICKS_PER_SEC = 1000000000UL; - LLVM_LIBC_FUNCTION(int, nanosleep, (const struct timespec *req, struct timespec *rem)) { if (!GPU_CLOCKS_PER_SEC || !req) diff --git a/libc/src/time/gpu/time_utils.cpp b/libc/src/time/gpu/time_utils.cpp deleted file mode 100644 index 38e09f600f36..000000000000 --- a/libc/src/time/gpu/time_utils.cpp +++ /dev/null @@ -1,22 +0,0 @@ -//===-- Generic utilities for GPU timing ----------------------------------===// -// -// 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 "time_utils.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -#if defined(LIBC_TARGET_ARCH_IS_AMDGPU) -// This is expected to be initialized by the runtime if the default value is -// insufficient. -// TODO: Once we have another use-case for this we should put it in a common -// device environment struct. -gpu::Constant<uint64_t> __llvm_libc_clock_freq = clock_freq; -#endif - -} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/gpu/time_utils.h b/libc/src/time/gpu/time_utils.h deleted file mode 100644 index c631a38d91ba..000000000000 --- a/libc/src/time/gpu/time_utils.h +++ /dev/null @@ -1,43 +0,0 @@ -//===-- Generic utilities for GPU timing ----------------------------------===// -// -// 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_SRC_TIME_GPU_TIME_UTILS_H -#define LLVM_LIBC_SRC_TIME_GPU_TIME_UTILS_H - -#include "hdr/time_macros.h" -#include "hdr/types/clock_t.h" -#include "src/__support/GPU/utils.h" -#include "src/__support/macros/config.h" - -namespace LIBC_NAMESPACE_DECL { - -#if defined(LIBC_TARGET_ARCH_IS_AMDGPU) -// AMDGPU does not have a single set frequency. Different architectures and -// cards can have different values. The actualy frequency needs to be read from -// the kernel driver and will be between 25 MHz and 100 MHz on most cards. All -// cards following the GFX9 ISAs use a 100 MHz clock so we will default to that. -constexpr uint64_t clock_freq = 100000000UL; - -// We provide an externally visible symbol such that the runtime can set -// this to the correct value. -extern "C" { -[[gnu::visibility("protected")]] -extern gpu::Constant<uint64_t> __llvm_libc_clock_freq; -} -#define GPU_CLOCKS_PER_SEC static_cast<clock_t>(__llvm_libc_clock_freq) - -#elif defined(LIBC_TARGET_ARCH_IS_NVPTX) -// NPVTX uses a single 1 GHz fixed frequency clock for all target architectures. -#define GPU_CLOCKS_PER_SEC static_cast<clock_t>(1000000000UL) -#else -#error "Unsupported target" -#endif - -} // namespace LIBC_NAMESPACE_DECL - -#endif // LLVM_LIBC_SRC_TIME_GPU_TIME_UTILS_H diff --git a/libc/src/time/gpu/timespec_get.cpp b/libc/src/time/gpu/timespec_get.cpp index f4ef328a8312..0dd128444aa8 100644 --- a/libc/src/time/gpu/timespec_get.cpp +++ b/libc/src/time/gpu/timespec_get.cpp @@ -10,6 +10,7 @@ #include "hdr/time_macros.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/__support/time/gpu/time_utils.h" namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/time/linux/CMakeLists.txt b/libc/src/time/linux/CMakeLists.txt index 31fd7d1e64c8..314623f9f425 100644 --- a/libc/src/time/linux/CMakeLists.txt +++ b/libc/src/time/linux/CMakeLists.txt @@ -1,17 +1,4 @@ add_entrypoint_object( - time - SRCS - time.cpp - HDRS - ../time_func.h - DEPENDS - libc.hdr.time_macros - libc.hdr.types.time_t - libc.src.__support.time.linux.clock_gettime - libc.src.errno.errno -) - -add_entrypoint_object( timespec_get SRCS timespec_get.cpp @@ -20,7 +7,7 @@ add_entrypoint_object( DEPENDS libc.hdr.time_macros libc.hdr.types.struct_timespec - libc.src.__support.time.linux.clock_gettime + libc.src.__support.time.clock_gettime libc.src.errno.errno ) @@ -34,7 +21,7 @@ add_entrypoint_object( libc.hdr.time_macros libc.hdr.types.clock_t libc.src.__support.time.units - libc.src.__support.time.linux.clock_gettime + libc.src.__support.time.clock_gettime libc.src.__support.CPP.limits libc.src.errno.errno ) @@ -62,7 +49,7 @@ add_entrypoint_object( DEPENDS libc.hdr.types.clockid_t libc.hdr.types.struct_timespec - libc.src.__support.time.linux.clock_gettime + libc.src.__support.time.clock_gettime libc.src.errno.errno ) @@ -75,7 +62,7 @@ add_entrypoint_object( DEPENDS libc.hdr.time_macros libc.hdr.types.suseconds_t - libc.src.__support.time.linux.clock_gettime + libc.src.__support.time.clock_gettime libc.src.__support.time.units libc.src.errno.errno ) diff --git a/libc/src/time/linux/clock.cpp b/libc/src/time/linux/clock.cpp index f43e1bcad6a3..ee4fa82b4f89 100644 --- a/libc/src/time/linux/clock.cpp +++ b/libc/src/time/linux/clock.cpp @@ -11,7 +11,7 @@ #include "src/__support/CPP/limits.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" -#include "src/__support/time/linux/clock_gettime.h" +#include "src/__support/time/clock_gettime.h" #include "src/__support/time/units.h" #include "src/errno/libc_errno.h" diff --git a/libc/src/time/linux/clock_gettime.cpp b/libc/src/time/linux/clock_gettime.cpp index a2b20a6dbc98..743c644d65d0 100644 --- a/libc/src/time/linux/clock_gettime.cpp +++ b/libc/src/time/linux/clock_gettime.cpp @@ -9,7 +9,7 @@ #include "src/time/clock_gettime.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" -#include "src/__support/time/linux/clock_gettime.h" +#include "src/__support/time/clock_gettime.h" #include "src/errno/libc_errno.h" namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/time/linux/gettimeofday.cpp b/libc/src/time/linux/gettimeofday.cpp index 19d9988ae73a..e8ddf482fc98 100644 --- a/libc/src/time/linux/gettimeofday.cpp +++ b/libc/src/time/linux/gettimeofday.cpp @@ -11,7 +11,7 @@ #include "hdr/types/suseconds_t.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" -#include "src/__support/time/linux/clock_gettime.h" +#include "src/__support/time/clock_gettime.h" #include "src/__support/time/units.h" #include "src/errno/libc_errno.h" diff --git a/libc/src/time/linux/timespec_get.cpp b/libc/src/time/linux/timespec_get.cpp index ba9f8eb2e442..cf5174523aa4 100644 --- a/libc/src/time/linux/timespec_get.cpp +++ b/libc/src/time/linux/timespec_get.cpp @@ -10,7 +10,7 @@ #include "hdr/time_macros.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" -#include "src/__support/time/linux/clock_gettime.h" +#include "src/__support/time/clock_gettime.h" #include "src/errno/libc_errno.h" namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/time/linux/time.cpp b/libc/src/time/time.cpp index 20fb86e8e29d..4a0b614a68ef 100644 --- a/libc/src/time/linux/time.cpp +++ b/libc/src/time/time.cpp @@ -9,14 +9,14 @@ #include "hdr/time_macros.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" -#include "src/__support/time/linux/clock_gettime.h" +#include "src/__support/time/clock_gettime.h" #include "src/errno/libc_errno.h" #include "src/time/time_func.h" namespace LIBC_NAMESPACE_DECL { - -LLVM_LIBC_FUNCTION(time_t, time, (time_t * tp)) { - // TODO: Use the Linux VDSO to fetch the time and avoid the syscall. +// avoid inconsitent clang-format behavior +using time_ptr_t = time_t *; +LLVM_LIBC_FUNCTION(time_t, time, (time_ptr_t tp)) { struct timespec ts; auto result = internal::clock_gettime(CLOCK_REALTIME, &ts); if (!result.has_value()) { diff --git a/libc/src/time/windows/CMakeLists.txt b/libc/src/time/windows/CMakeLists.txt new file mode 100644 index 000000000000..6f242cd168f5 --- /dev/null +++ b/libc/src/time/windows/CMakeLists.txt @@ -0,0 +1,13 @@ +add_entrypoint_object( + clock_getres + SRCS + clock_getres.cpp + DEPENDS + libc.src.__support.time.windows.performance_counter + libc.src.__support.time.units + libc.src.__support.common + libc.src.__support.macros.optimization + libc.hdr.time_macros + libc.hdr.types.time_t + libc.hdr.types.struct_timespec +) diff --git a/libc/src/time/windows/clock_getres.cpp b/libc/src/time/windows/clock_getres.cpp new file mode 100644 index 000000000000..b8c0c82aa641 --- /dev/null +++ b/libc/src/time/windows/clock_getres.cpp @@ -0,0 +1,110 @@ +//===-- Windows implementation of clock_getres ------------------*- C++ -*-===// +// +// 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 "hdr/errno_macros.h" +#include "hdr/time_macros.h" +#include "hdr/types/clockid_t.h" +#include "hdr/types/struct_timespec.h" + +#include "src/__support/CPP/limits.h" +#include "src/__support/common.h" +#include "src/__support/macros/optimization.h" +#include "src/__support/time/units.h" +#include "src/__support/time/windows/performance_counter.h" +#include "src/errno/libc_errno.h" +#include "src/time/clock_getres.h" + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include <Windows.h> + +// add in dependencies for GetSystemTimeAdjustmentPrecise +#pragma comment(lib, "mincore.lib") + +namespace LIBC_NAMESPACE_DECL { +LLVM_LIBC_FUNCTION(int, clock_getres, (clockid_t id, struct timespec *res)) { + using namespace time_units; + // POSIX allows nullptr to be passed as res, in which case the function should + // do nothing. + if (res == nullptr) + return 0; + constexpr unsigned long long HNS_PER_SEC = 1_s_ns / 100ULL; + constexpr unsigned long long SEC_LIMIT = + cpp::numeric_limits<decltype(res->tv_sec)>::max(); + // For CLOCK_MONOTONIC, we are using performance counter + // https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps + // Hence, the resolution is given by the performance counter frequency. + // For CLOCK_REALTIME, the precision is given by + // GetSystemTimeAdjustmentPrecise + // (https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeadjustmentprecise) + // For CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID, the precision is + // given by GetSystemTimeAdjustment + // (https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeadjustment) + switch (id) { + default: + libc_errno = EINVAL; + return -1; + + case CLOCK_MONOTONIC: { + long long freq = performance_counter::get_ticks_per_second(); + __builtin_assume(freq != 0); + // division of 1 second by frequency, rounded up. + long long tv_sec = static_cast<long long>(freq == 1); + long long tv_nsec = + LIBC_LIKELY(freq != 1) ? 1ll + ((1_s_ns - 1ll) / freq) : 0ll; + // not possible to overflow tv_sec, tv_nsec + res->tv_sec = static_cast<decltype(res->tv_sec)>(tv_sec); + res->tv_nsec = static_cast<decltype(res->tv_nsec)>(tv_nsec); + break; + } + + case CLOCK_REALTIME: { + [[clang::uninitialized]] DWORD64 time_adjustment; + [[clang::uninitialized]] DWORD64 time_increment; + [[clang::uninitialized]] BOOL time_adjustment_disabled; + if (!::GetSystemTimeAdjustmentPrecise(&time_adjustment, &time_increment, + &time_adjustment_disabled)) { + libc_errno = EINVAL; + return -1; + } + DWORD64 tv_sec = time_increment / HNS_PER_SEC; + DWORD64 tv_nsec = (time_increment % HNS_PER_SEC) * 100ULL; + if (LIBC_UNLIKELY(tv_sec > SEC_LIMIT)) { + libc_errno = EOVERFLOW; + return -1; + } + res->tv_sec = static_cast<decltype(res->tv_sec)>(tv_sec); + res->tv_nsec = static_cast<decltype(res->tv_nsec)>(tv_nsec); + break; + } + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_THREAD_CPUTIME_ID: { + [[clang::uninitialized]] DWORD time_adjustment; + [[clang::uninitialized]] DWORD time_increment; + [[clang::uninitialized]] BOOL time_adjustment_disabled; + if (!::GetSystemTimeAdjustment(&time_adjustment, &time_increment, + &time_adjustment_disabled)) { + libc_errno = EINVAL; + return -1; + } + DWORD hns_per_sec = static_cast<DWORD>(HNS_PER_SEC); + DWORD sec_limit = static_cast<DWORD>(SEC_LIMIT); + DWORD tv_sec = time_increment / hns_per_sec; + DWORD tv_nsec = (time_increment % hns_per_sec) * 100UL; + if (LIBC_UNLIKELY(tv_sec > sec_limit)) { + libc_errno = EOVERFLOW; + return -1; + } + res->tv_sec = static_cast<decltype(res->tv_sec)>(tv_sec); + res->tv_nsec = static_cast<decltype(res->tv_nsec)>(tv_nsec); + break; + } + } + return 0; +} +} // namespace LIBC_NAMESPACE_DECL |
