diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -517,6 +517,12 @@ # because they are provided by the dylib itself. target_add_compile_flags_if_supported(${target} PRIVATE -faligned-allocation) + # 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 @@ -146,6 +146,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/support.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,46 @@ +// -*- 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 +#include +#include +#include +#include + +inline int __gettod(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 { + unsigned long hi; + unsigned long lo; + }; + struct _t value = {0, 0}; + unsigned long cc = 0; + asm(" stcke %0\n" + " ipm %1\n" + " srlg %1,%1,28\n" + : "=m"(value), "+r"(cc)::); + if (cc != 0) + return cc; + unsigned long long ms = (value.hi >> 4); + unsigned long long ns = ((value.hi & 0x0F) << 8) + (value.lo >> 56); + ns = (ns * 1000) >> 12; + ms = ms - 2208988800000000; + output->tv_sec = ms / 1000000; + output->tv_nsec = (ms % 1000000) * 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 @@ -156,6 +156,18 @@ return steady_clock::time_point(steady_clock::duration(counter.QuadPart * nano::den / freq.QuadPart)); } +#elif defined(__MVS__) +#include + +static steady_clock::time_point __libcpp_steady_clock_now() { + struct timespec64 ts; + if (0 != __gettod(&ts)) + __throw_system_error(errno, "failed to obtained 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() {