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.h support/ibm/limits.h support/ibm/locale_mgmt_aix.h support/ibm/nanosleep.h diff --git a/libcxx/include/support/ibm/gettod.h b/libcxx/include/support/ibm/gettod.h new file mode 100644 --- /dev/null +++ b/libcxx/include/support/ibm/gettod.h @@ -0,0 +1,54 @@ +// -*- 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 + +inline int gettimeofday_monotonic(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 = EPERM; + 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 div_pair0 = 0; + uint64_t div_pair1 = us; + uint64_t divisor = 1000000; + asm(" dlgr %0,%2" + : "+NR:r0"(div_pair0), "+NR:r1"(div_pair1) + : "r"(divisor) + :); + + output->tv_sec = div_pair1; + output->tv_nsec = div_pair0 * 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 @@ -20,6 +20,10 @@ # include // for gettimeofday and timeval #endif +#if defined(__MVS__) +# include +#endif + #if !defined(__APPLE__) && _POSIX_TIMERS > 0 # define _LIBCPP_USE_CLOCK_GETTIME #endif @@ -159,6 +163,17 @@ 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 != gettimeofday_monotonic(&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() {