xref: /llvm-project/libcxx/include/__cxx03/__support/ibm/nanosleep.h (revision ce7771902dc50d900de639d499a60486b83f70e0)
1e78f53d1SNikolas Klauser // -*- C++ -*-
2e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===//
3e78f53d1SNikolas Klauser //
4e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
6e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7e78f53d1SNikolas Klauser //
8e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===//
9e78f53d1SNikolas Klauser 
10*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___SUPPORT_IBM_NANOSLEEP_H
11*ce777190SNikolas Klauser #define _LIBCPP___CXX03___SUPPORT_IBM_NANOSLEEP_H
12e78f53d1SNikolas Klauser 
1373fbae83SNikolas Klauser #include <__cxx03/unistd.h>
14e78f53d1SNikolas Klauser 
15e78f53d1SNikolas Klauser inline int nanosleep(const struct timespec* __req, struct timespec* __rem) {
16e78f53d1SNikolas Klauser   // The nanosleep() function is not available on z/OS. Therefore, we will call
17e78f53d1SNikolas Klauser   // sleep() to sleep for whole seconds and usleep() to sleep for any remaining
18e78f53d1SNikolas Klauser   // fraction of a second. Any remaining nanoseconds will round up to the next
19e78f53d1SNikolas Klauser   // microsecond.
20e78f53d1SNikolas Klauser   if (__req->tv_sec < 0 || __req->tv_nsec < 0 || __req->tv_nsec > 999999999) {
21e78f53d1SNikolas Klauser     errno = EINVAL;
22e78f53d1SNikolas Klauser     return -1;
23e78f53d1SNikolas Klauser   }
24e78f53d1SNikolas Klauser   long __micro_sec = (__req->tv_nsec + 999) / 1000;
25e78f53d1SNikolas Klauser   time_t __sec     = __req->tv_sec;
26e78f53d1SNikolas Klauser   if (__micro_sec > 999999) {
27e78f53d1SNikolas Klauser     ++__sec;
28e78f53d1SNikolas Klauser     __micro_sec -= 1000000;
29e78f53d1SNikolas Klauser   }
30e78f53d1SNikolas Klauser   __sec = static_cast<time_t>(sleep(static_cast<unsigned int>(__sec)));
31e78f53d1SNikolas Klauser   if (__sec) {
32e78f53d1SNikolas Klauser     if (__rem) {
33e78f53d1SNikolas Klauser       // Updating the remaining time to sleep in case of unsuccessful call to sleep().
34e78f53d1SNikolas Klauser       __rem->tv_sec  = __sec;
35e78f53d1SNikolas Klauser       __rem->tv_nsec = __micro_sec * 1000;
36e78f53d1SNikolas Klauser     }
37e78f53d1SNikolas Klauser     errno = EINTR;
38e78f53d1SNikolas Klauser     return -1;
39e78f53d1SNikolas Klauser   }
40e78f53d1SNikolas Klauser   if (__micro_sec) {
41e78f53d1SNikolas Klauser     int __rt = usleep(static_cast<unsigned int>(__micro_sec));
42e78f53d1SNikolas Klauser     if (__rt != 0 && __rem) {
43e78f53d1SNikolas Klauser       // The usleep() does not provide the amount of remaining time upon its failure,
44e78f53d1SNikolas Klauser       // so the time slept will be ignored.
45e78f53d1SNikolas Klauser       __rem->tv_sec  = 0;
46e78f53d1SNikolas Klauser       __rem->tv_nsec = __micro_sec * 1000;
47e78f53d1SNikolas Klauser       // The errno is already set.
48e78f53d1SNikolas Klauser       return -1;
49e78f53d1SNikolas Klauser     }
50e78f53d1SNikolas Klauser     return __rt;
51e78f53d1SNikolas Klauser   }
52e78f53d1SNikolas Klauser   return 0;
53e78f53d1SNikolas Klauser }
54e78f53d1SNikolas Klauser 
55*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___SUPPORT_IBM_NANOSLEEP_H
56