xref: /llvm-project/libcxx/include/__support/ibm/nanosleep.h (revision 9783f28cbb155e4a8d49c12e1c60ce14dcfaf0c7)
1b5175681SLouis Dionne // -*- C++ -*-
2b5175681SLouis Dionne //===----------------------------------------------------------------------===//
3b5175681SLouis Dionne //
4b5175681SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5b5175681SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
6b5175681SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7b5175681SLouis Dionne //
8b5175681SLouis Dionne //===----------------------------------------------------------------------===//
9b5175681SLouis Dionne 
10*b938b870SLouis Dionne #ifndef _LIBCPP___SUPPORT_IBM_NANOSLEEP_H
11*b938b870SLouis Dionne #define _LIBCPP___SUPPORT_IBM_NANOSLEEP_H
12b5175681SLouis Dionne 
13b5175681SLouis Dionne #include <unistd.h>
14b5175681SLouis Dionne 
nanosleep(const struct timespec * __req,struct timespec * __rem)15916093f4SZbigniew Sarbinowski inline int nanosleep(const struct timespec* __req, struct timespec* __rem) {
16b5175681SLouis Dionne   // The nanosleep() function is not available on z/OS. Therefore, we will call
17b5175681SLouis Dionne   // sleep() to sleep for whole seconds and usleep() to sleep for any remaining
18b5175681SLouis Dionne   // fraction of a second. Any remaining nanoseconds will round up to the next
19b5175681SLouis Dionne   // microsecond.
20916093f4SZbigniew Sarbinowski   if (__req->tv_sec < 0 || __req->tv_nsec < 0 || __req->tv_nsec > 999999999) {
21916093f4SZbigniew Sarbinowski     errno = EINVAL;
22916093f4SZbigniew Sarbinowski     return -1;
23916093f4SZbigniew Sarbinowski   }
24422cf2b5SZbigniew Sarbinowski   long __micro_sec = (__req->tv_nsec + 999) / 1000;
25916093f4SZbigniew Sarbinowski   time_t __sec     = __req->tv_sec;
26916093f4SZbigniew Sarbinowski   if (__micro_sec > 999999) {
27916093f4SZbigniew Sarbinowski     ++__sec;
28b5175681SLouis Dionne     __micro_sec -= 1000000;
29b5175681SLouis Dionne   }
30422cf2b5SZbigniew Sarbinowski   __sec = static_cast<time_t>(sleep(static_cast<unsigned int>(__sec)));
31916093f4SZbigniew Sarbinowski   if (__sec) {
32916093f4SZbigniew Sarbinowski     if (__rem) {
33916093f4SZbigniew Sarbinowski       // Updating the remaining time to sleep in case of unsuccessful call to sleep().
34916093f4SZbigniew Sarbinowski       __rem->tv_sec  = __sec;
35916093f4SZbigniew Sarbinowski       __rem->tv_nsec = __micro_sec * 1000;
36b5175681SLouis Dionne     }
37916093f4SZbigniew Sarbinowski     errno = EINTR;
38916093f4SZbigniew Sarbinowski     return -1;
39916093f4SZbigniew Sarbinowski   }
40916093f4SZbigniew Sarbinowski   if (__micro_sec) {
41422cf2b5SZbigniew Sarbinowski     int __rt = usleep(static_cast<unsigned int>(__micro_sec));
42916093f4SZbigniew Sarbinowski     if (__rt != 0 && __rem) {
43916093f4SZbigniew Sarbinowski       // The usleep() does not provide the amount of remaining time upon its failure,
44916093f4SZbigniew Sarbinowski       // so the time slept will be ignored.
45916093f4SZbigniew Sarbinowski       __rem->tv_sec  = 0;
46916093f4SZbigniew Sarbinowski       __rem->tv_nsec = __micro_sec * 1000;
47916093f4SZbigniew Sarbinowski       // The errno is already set.
48916093f4SZbigniew Sarbinowski       return -1;
49916093f4SZbigniew Sarbinowski     }
50916093f4SZbigniew Sarbinowski     return __rt;
51916093f4SZbigniew Sarbinowski   }
52b5175681SLouis Dionne   return 0;
53b5175681SLouis Dionne }
54b5175681SLouis Dionne 
55*b938b870SLouis Dionne #endif // _LIBCPP___SUPPORT_IBM_NANOSLEEP_H
56