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).
10 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
11 * Copyright (C) 2014, MinGW.org Project.
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:
21 * The above copyright notice, this permission notice, and the following
22 * disclaimer shall be included in all copies or substantial portions of
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.
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.
42 __declspec(dllimport) _stdcall void Sleep( unsigned long );
44 int __mingw_sleep( unsigned long secs, unsigned long nsecs )
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.
50 if( (secs | nsecs) > 0UL )
52 /* At least one of the seconds or nanoseconds components must
53 * be non-zero, to require us to perform any action.
55 if( nsecs < 1000000000UL )
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).
64 unsigned long long interval = (secs > 0UL)
65 ? secs * 1000ULL + ((nsecs > 0UL) ? nsecs / 1000000ULL : 0ULL)
66 : (nsecs + 999999ULL) / 1000000ULL;
68 /* It is unlikely that we should ever need this, (but it is
69 * possible, so we proceed defensively)...
71 while( interval > (unsigned long long)(LONG_MAX) )
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").
79 Sleep( (unsigned long)(LONG_MAX) );
80 interval -= (unsigned long long)(LONG_MAX);
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.
88 Sleep( (unsigned long)(interval) );
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:
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).
107 /* $RCSfile$: end of file */