• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * This file has no copyright assigned and is placed in the Public Domain.
3  * This file is part of the w64 mingw-runtime package.
4  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5  */
6 
7 #include <errno.h>
8 #include <time.h>
9 #include <windows.h>
10 #include "pthread.h"
11 #include "pthread_time.h"
12 #include "winpthread_internal.h"
13 
14 #define POW10_3                 1000
15 #define POW10_4                 10000
16 #define POW10_6                 1000000
17 #define POW10_9                 1000000000
18 #define MAX_SLEEP_IN_MS         4294967294UL
19 
20 /**
21  * Sleep for the specified time.
22  * @param  request The desired amount of time to sleep.
23  * @param  remain The remain amount of time to sleep.
24  * @return If the function succeeds, the return value is 0.
25  *         If the function fails, the return value is -1,
26  *         with errno set to indicate the error.
27  */
nanosleep(const struct timespec * request,struct timespec * remain)28 int nanosleep(const struct timespec *request, struct timespec *remain)
29 {
30     unsigned long ms, rc = 0;
31     unsigned __int64 u64, want, real;
32 
33     union {
34         unsigned __int64 ns100;
35         FILETIME ft;
36     }  _start, _end;
37 
38     if (request->tv_sec < 0 || request->tv_nsec < 0 || request->tv_nsec >= POW10_9) {
39         errno = EINVAL;
40         return -1;
41     }
42 
43     if (remain != NULL) GetSystemTimeAsFileTime(&_start.ft);
44 
45     want = u64 = request->tv_sec * POW10_3 + request->tv_nsec / POW10_6;
46     while (u64 > 0 && rc == 0) {
47         if (u64 >= MAX_SLEEP_IN_MS) ms = MAX_SLEEP_IN_MS;
48         else ms = (unsigned long) u64;
49 
50         u64 -= ms;
51         rc = pthread_delay_np_ms(ms);
52     }
53 
54     if (rc != 0) { /* WAIT_IO_COMPLETION (192) */
55         if (remain != NULL) {
56             GetSystemTimeAsFileTime(&_end.ft);
57             real = (_end.ns100 - _start.ns100) / POW10_4;
58 
59             if (real >= want) u64 = 0;
60             else u64 = want - real;
61 
62             remain->tv_sec = u64 / POW10_3;
63             remain->tv_nsec = (long) (u64 % POW10_3) * POW10_6;
64         }
65 
66         errno = EINTR;
67         return -1;
68     }
69 
70     return 0;
71 }
72