diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -530,6 +530,12 @@ target_add_compile_flags_if_supported(${target} PRIVATE -faligned-allocation) endif() + # As part of monotonic clock support on z/OS we need macro _LARGE_TIME_API + # to be defined before any system header is included. + if (ZOS) + add_definitions(-D_LARGE_TIME_API) # Needed for struct timespec64. + endif() + # On all systems the system c++ standard library headers need to be excluded. # MSVC only has -X, which disables all default includes; including the crt. # Thus, we do nothing and hope we don't accidentally include any of the C++ diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -151,6 +151,7 @@ strstream support/android/locale_bionic.h support/fuchsia/xlocale.h + support/ibm/gettod_zos.h support/ibm/limits.h support/ibm/locale_mgmt_aix.h support/ibm/nanosleep.h diff --git a/libcxx/include/support/ibm/gettod_zos.h b/libcxx/include/support/ibm/gettod_zos.h new file mode 100644 --- /dev/null +++ b/libcxx/include/support/ibm/gettod_zos.h @@ -0,0 +1,55 @@ +// -*- 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 _LIBCPP_SUPPORT_IBM_GETTOD_H +#define _LIBCPP_SUPPORT_IBM_GETTOD_H + +#include + +static inline +int gettimeofdayMonotonic(struct timespec64* Output) { + + // The POSIX gettimeofday() function is not available on z/OS. Therefore, + // we will call stcke and other hardware instructions in implement equivalent. + // Note that nanoseconds alone will overflow when reaching new epoch in 2042. + + struct _t { + uint64_t Hi; + uint64_t Lo; + }; + struct _t Value = {0, 0}; + uint64_t CC = 0; + asm(" stcke %0\n" + " ipm %1\n" + " srlg %1,%1,28\n" + : "=m"(Value), "+r"(CC)::); + + if (CC != 0) { + errno = EMVSTODNOTSET; + return CC; + } + uint64_t us = (Value.Hi >> 4); + uint64_t ns = ((Value.Hi & 0x0F) << 8) + (Value.Lo >> 56); + ns = (ns * 1000) >> 12; + us = us - 2208988800000000; + + uint64_t DivPair0 = 0; // dividend (upper half), remainder + uint64_t DivPair1 = us; // dividend (lower half), quotient + uint64_t Divisor = 1000000; + asm(" dlgr %0,%2" + : "+NR:r0"(DivPair0), "+NR:r1"(DivPair1) + : "r"(Divisor) + :); + + Output->tv_sec = DivPair1; + Output->tv_nsec = DivPair0 * 1000 + ns; + return 0; +} + +#endif // _LIBCPP_SUPPORT_IBM_GETTOD_H diff --git a/libcxx/src/chrono.cpp b/libcxx/src/chrono.cpp --- a/libcxx/src/chrono.cpp +++ b/libcxx/src/chrono.cpp @@ -9,6 +9,11 @@ #include "chrono" #include "cerrno" // errno #include "system_error" // __throw_system_error + +#if defined(__MVS__) +#include // gettimeofdayMonotonic +#endif + #include // clock_gettime and CLOCK_{MONOTONIC,REALTIME,MONOTONIC_RAW} #include "include/apple_availability.h" @@ -159,6 +164,16 @@ return steady_clock::time_point(steady_clock::duration(dur)); } +#elif defined(__MVS__) + +static steady_clock::time_point __libcpp_steady_clock_now() { + struct timespec64 ts; + if (0 != gettimeofdayMonotonic(&ts)) + __throw_system_error(errno, "failed to obtain time of day"); + + return steady_clock::time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec)); +} + #elif defined(CLOCK_MONOTONIC) static steady_clock::time_point __libcpp_steady_clock_now() {