[libcxx-commits] [PATCH] D87940: [SystemZ][ZOS] Porting the time functions within libc++ to z/OS

Zbigniew Sarbinowski via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Fri Sep 18 13:41:22 PDT 2020


zibi created this revision.
zibi added reviewers: uweigand, Kai, SeanP, xingxue, ldionne.
zibi added a project: libc++.
Herald added subscribers: libcxx-commits, dexonsmith.
Herald added a reviewer: libc++.
zibi requested review of this revision.

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().


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87940

Files:
  libcxx/include/__threading_support
  libcxx/src/filesystem/filesystem_common.h


Index: libcxx/src/filesystem/filesystem_common.h
===================================================================
--- libcxx/src/filesystem/filesystem_common.h
+++ libcxx/src/filesystem/filesystem_common.h
@@ -382,6 +382,15 @@
 #if defined(__APPLE__)
 TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
 TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
+#elif defined(__MVS__)
+TimeSpec extract_mtime(StatT const& st) {
+  TimeSpec TS = {st.st_mtime, 0};
+  return TS;
+}
+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; }
@@ -398,8 +407,14 @@
     auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count();
     return static_cast<int_type>(dur);
   };
+#if defined(__MVS__)
+  struct ::timeval ConvertedTS[2] = {
+      {TS[0].tv_sec, {}, Convert(TS[0].tv_nsec)},
+      {TS[1].tv_sec, {}, Convert(TS[1].tv_nsec)}};
+#else
   struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)},
                                      {TS[1].tv_sec, Convert(TS[1].tv_nsec)}};
+#endif
   if (::utimes(p.c_str(), ConvertedTS) == -1) {
     ec = capture_errno();
     return true;
Index: libcxx/include/__threading_support
===================================================================
--- libcxx/include/__threading_support
+++ libcxx/include/__threading_support
@@ -15,6 +15,10 @@
 #include <iosfwd>
 #include <errno.h>
 
+#ifdef __MVS__
+#include <unistd.h>
+#endif
+
 #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
 #pragma GCC system_header
 #endif
@@ -532,7 +536,25 @@
 void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
 {
    __libcpp_timespec_t __ts = __thread_detail::__convert_to_timespec(__ns);
+#if defined(__MVS__)
+   // The nanosleep() is not available on z/OS. Therefore,
+   // we will call sleep() to sleep for a whole seconds
+   // and usleep() to sleep for a fraction of a second.
+   // Any remaining nano seconds will round up to the next micro second.
+
+   useconds_t __micro_sec = (__ts.tv_nsec + 999) / 1000;
+   if (__micro_sec > 999999)
+   {
+   __ts.tv_sec++;
+   __micro_sec = 0;
+   }
+   while (__ts.tv_sec)
+      __ts.tv_sec = sleep(__ts.tv_sec);
+   if (__micro_sec)
+      usleep(__micro_sec);
+#else
    while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR);
+#endif
 }
 
 // Thread local storage


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87940.292886.patch
Type: text/x-patch
Size: 2547 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20200918/b950516b/attachment-0001.bin>


More information about the libcxx-commits mailing list