[libcxx-commits] [libcxx] 173b511 - [SystemZ][ZOS] Porting the time functions within libc++ to z/OS

Abhina Sreeskantharajan via libcxx-commits libcxx-commits at lists.llvm.org
Thu Nov 12 08:29:21 PST 2020


Author: Zbigniew Sarbinowski
Date: 2020-11-12T11:29:13-05:00
New Revision: 173b51169b838255aff4d4ff4eb6014b101a9687

URL: https://github.com/llvm/llvm-project/commit/173b51169b838255aff4d4ff4eb6014b101a9687
DIFF: https://github.com/llvm/llvm-project/commit/173b51169b838255aff4d4ff4eb6014b101a9687.diff

LOG: [SystemZ][ZOS] Porting the time functions within libc++ to z/OS

This patch is one part of many steps required to build libc++ and libc++abi libraries on z/OS.  This particular deals with time related functions and consists of the following 3 parts.

1) Initialization of :timeval within libc++ library need to be adjusted to work on z/OS.
The following is z/OS definition from time.h which includes additional aggregate member.
typedef signed int suseconds_t;
struct timeval {
time_t tv_sec;
char tv_usec_pad[4];
suseconds_t tv_usec;
};

In contracts the following is definition from time.h on Linux.

typedef long int __suseconds_t;
struct timeval
{
__time_t tv_sec;
__suseconds_t tv_usec;
};

2) In addition, retrieving ::timespec within libc++ library needs to be adjusted to compensate the difference of some of the members of ::stat depending of the target host.
Here are the 2 members in conflict on z/OS extracted from stat.h.
struct stat {
...
time_t st_atime;
time_t st_mtime;
...
};
In contract here is Linux equivalent from stat.h.
struct stat
{
...
struct timespec st_atim;
struct timespec st_mtim;
...
};

3) On Linux both members are of type timespec whereas on z/OS an object of type timespec need to be constructed first before retrieving it within libc++ library.

The libc++ header file __threading_support calls nanosleep, which is not available on z/OS.
The equivalent functionality will be implemented by using both sleep() and usleep().

Reviewed By: ldionne, #libc

Differential Revision: https://reviews.llvm.org/D87940

Added: 
    libcxx/include/support/ibm/nanosleep.h

Modified: 
    libcxx/include/CMakeLists.txt
    libcxx/include/__threading_support
    libcxx/src/filesystem/filesystem_common.h

Removed: 
    


################################################################################
diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index aab02768e5b7..df169560133f 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -179,6 +179,29 @@ set(files
   wctype.h
   )
 
+if(LIBCXX_INSTALL_SUPPORT_HEADERS)
+  set(files
+    ${files}
+    support/android/locale_bionic.h
+    support/fuchsia/xlocale.h
+    support/ibm/limits.h
+    support/ibm/locale_mgmt_aix.h
+    support/ibm/nanosleep.h
+    support/ibm/support.h
+    support/ibm/xlocale.h
+    support/musl/xlocale.h
+    support/newlib/xlocale.h
+    support/solaris/floatingpoint.h
+    support/solaris/wchar.h
+    support/solaris/xlocale.h
+    support/win32/limits_msvc_win32.h
+    support/win32/locale_win32.h
+    support/xlocale/__nop_locale_mgmt.h
+    support/xlocale/__posix_l_fallback.h
+    support/xlocale/__strtonum_fallback.h
+    )
+endif()
+
 configure_file("__config_site.in"
                "${LIBCXX_BINARY_DIR}/__config_site"
                @ONLY)

diff  --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support
index fe770a81c115..a9ab425d2e89 100644
--- a/libcxx/include/__threading_support
+++ b/libcxx/include/__threading_support
@@ -16,6 +16,10 @@
 #include <iosfwd>
 #include <errno.h>
 
+#ifdef __MVS__
+#include <support/ibm/nanosleep.h>
+#endif
+
 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
 #pragma GCC system_header
 #endif

diff  --git a/libcxx/include/support/ibm/nanosleep.h b/libcxx/include/support/ibm/nanosleep.h
new file mode 100644
index 000000000000..c82f4eb0cd5b
--- /dev/null
+++ b/libcxx/include/support/ibm/nanosleep.h
@@ -0,0 +1,38 @@
+// -*- 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_NANOSLEEP_H
+#define _LIBCPP_SUPPORT_IBM_NANOSLEEP_H
+
+#include <unistd.h>
+
+inline int nanosleep(const struct timespec* req, struct timespec* rem)
+{
+   // The nanosleep() function is not available on z/OS. Therefore, we will call
+   // sleep() to sleep for whole seconds and usleep() to sleep for any remaining
+   // fraction of a second. Any remaining nanoseconds will round up to the next
+   // microsecond.
+
+   useconds_t __micro_sec = (rem->tv_nsec + 999) / 1000;
+   if (__micro_sec > 999999)
+   {
+     ++rem->tv_sec;
+     __micro_sec -= 1000000;
+   }
+   while (rem->tv_sec)
+      rem->tv_sec = sleep(rem->tv_sec);
+   if (__micro_sec) {
+     rem->tv_nsec = __micro_sec * 1000;
+     return usleep(__micro_sec);
+   }
+   rem->tv_nsec = 0;
+   return 0;
+}
+
+#endif // _LIBCPP_SUPPORT_IBM_NANOSLEEP_H

diff  --git a/libcxx/src/filesystem/filesystem_common.h b/libcxx/src/filesystem/filesystem_common.h
index dc55f93da70c..a82f6511368a 100644
--- a/libcxx/src/filesystem/filesystem_common.h
+++ b/libcxx/src/filesystem/filesystem_common.h
@@ -198,7 +198,8 @@ struct ErrorHandler {
 using chrono::duration;
 using chrono::duration_cast;
 
-using TimeSpec = timespec;
+using TimeSpec = struct timespec;
+using TimeVal = struct timeval;
 using StatT = struct stat;
 
 template <class FileTimeT, class TimeT,
@@ -381,26 +382,38 @@ struct time_util : time_util_base<FileTimeT, TimeT> {
 using fs_time = time_util<file_time_type, time_t, TimeSpec>;
 
 #if defined(__APPLE__)
-TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
-TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
+inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
+inline TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
+#elif defined(__MVS__)
+inline TimeSpec extract_mtime(StatT const& st) {
+  TimeSpec TS = {st.st_mtime, 0};
+  return TS;
+}
+inline TimeSpec extract_atime(StatT const& st) {
+  TimeSpec TS = {st.st_atime, 0};
+  return TS;
+}
 #else
-TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
-TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
+inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
+inline TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
 #endif
 
-// allow the utimes implementation to compile even it we're not going
-// to use it.
-
-bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS,
-                  error_code& ec) {
+inline TimeVal make_timeval(TimeSpec const& ts) {
   using namespace chrono;
   auto Convert = [](long nsec) {
-    using int_type = decltype(std::declval< ::timeval>().tv_usec);
+    using int_type = decltype(std::declval<TimeVal>().tv_usec);
     auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count();
     return static_cast<int_type>(dur);
   };
-  struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)},
-                                     {TS[1].tv_sec, Convert(TS[1].tv_nsec)}};
+  TimeVal TV = {};
+  TV.tv_sec = ts.tv_sec;
+  TV.tv_usec = Convert(ts.tv_nsec);
+  return TV;
+}
+
+inline bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS,
+                  error_code& ec) {
+  TimeVal ConvertedTS[2] = {make_timeval(TS[0]), make_timeval(TS[1])};
   if (::utimes(p.c_str(), ConvertedTS) == -1) {
     ec = capture_errno();
     return true;


        


More information about the libcxx-commits mailing list