OSDN Git Service

Adjust repository version following WSL-5.2.2 release.
[mingw/mingw-org-wsl.git] / mingwrt / mingwex / nsleep.c
1 /*
2  * nsleep.c
3  *
4  * Core implementation of the __mingw_sleep() API, which facilitates the
5  * provision of (mostly) POSIX compliant sleep(), usleep(), and nanosleep()
6  * functions, (per inline implementations in unistd.h).
7  *
8  * $Id$
9  *
10  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
11  * Copyright (C) 2014, MinGW.org Project.
12  *
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the "Software"),
16  * to deal in the Software without restriction, including without limitation
17  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18  * and/or sell copies of the Software, and to permit persons to whom the
19  * Software is furnished to do so, subject to the following conditions:
20  *
21  * The above copyright notice, this permission notice, and the following
22  * disclaimer shall be included in all copies or substantial portions of
23  * the Software.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
28  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
31  * DEALINGS IN THE SOFTWARE.
32  *
33  */
34 #include <errno.h>
35 #include <limits.h>
36 #include <unistd.h>
37
38 /* Including windows.h, just to declare Sleep(), seems like overkill; we
39  * prefer to declare it directly, to ensure we get the kernel DLL import,
40  * without the overhead of redirection through a libkernel.a trampoline.
41  */
42 __declspec(dllimport) _stdcall void Sleep( unsigned long );
43
44 int __mingw_sleep( unsigned long secs, unsigned long nsecs )
45 {
46   /* Entry point for general purpose sleep() function API, supporting
47    * the __CRT_INLINE implementations of the three functions identified
48    * in the file description above.
49    */
50   if( (secs | nsecs) > 0UL )
51   {
52     /* At least one of the seconds or nanoseconds components must
53      * be non-zero, to require us to perform any action.
54      */
55     if( nsecs < 1000000000UL )
56     {
57       /* POSIX requires the nanoseconds component of the specified
58        * interval to be less than one full second (1,000,000,000 ns);
59        * we've satisfied that requirement, so we proceed to combine
60        * the seconds and nanoseconds components into a millisecond
61        * representation, as required by the kernel's Sleep() API,
62        * (using a 64-bit representation, to avoid overflow).
63        */
64       unsigned long long interval = (secs > 0UL)
65         ? secs * 1000ULL + ((nsecs > 0UL) ? nsecs / 1000000ULL : 0ULL)
66         : (nsecs + 999999ULL) / 1000000ULL;
67
68       /* It is unlikely that we should ever need this, (but it is
69        * possible, so we proceed defensively)...
70        */
71       while( interval > (unsigned long long)(LONG_MAX) )
72       {
73         /* ...breaking excessively long intervals into cycles of
74          * LONG_MAX milliseconds, (~25 days, and we may be asked
75          * to sleep through up to 2000 cycles, or ~136 years), so
76          * that we avoid any interval value with the high bit set
77          * (lest that be interpreted as "sleep forever").
78          */
79         Sleep( (unsigned long)(LONG_MAX) );
80         interval -= (unsigned long long)(LONG_MAX);
81       }
82       /* Since suspension requests of 25 days are unlikely, in
83        * the majority of cases we should simply skip over the
84        * preceding loop; we must still call Sleep(), either to
85        * satisfy the original request in its entirety, or the
86        * residual from the loop.
87        */
88       Sleep( (unsigned long)(interval) );
89     }
90     else
91     { /* We were given a nanoseconds component value, within the
92        * interval specification, which exceeds one full second; in
93        * this event, POSIX specifies the following failure:
94        */
95       errno = EINVAL;
96       return -1;
97     }
98   }
99   /* On success, or maybe having done nothing at all, we simply
100    * return zero; (note that Windows Sleep() isn't interruptible
101    * in the way that that POSIX sleep() is, so we do not provide
102    * any indication of an uncompleted interval).
103    */
104   return 0;
105 }
106
107 /* $RCSfile$: end of file */