+2014-12-23 Keith Marshall <keithmarshall@users.sourceforge.net>
+
+ Provide more POSIX conforming sleep() functions.
+
+ * include/sys/types.h (useconds_t): Make it explicitly long; int may
+ be okay, but doesn't guarantee enough bits; mark as deprecated, since
+ POSIX has declared it "obsolete", and no longer specifies it.
+
+ * mingwex/usleep.c: Delete file; it provided an implementation of...
+ (usleep): ...this now obsolete function, claiming POSIX.1 issue 6, but
+ its error handling was hopelessly broken; replace it with...
+ * mingwex/nsleep.c: ...this new file; it implements...
+ (__mingw_sleep): ...this generic helper function; it supports sleep
+ capability with interval specification to nanosecond precision.
+
+ * include/unistd.h (__mingw_sleep): Declare prototype; use it as the
+ basis for providing __LIBIMPL__ __CRT_INLINE implementations of...
+ (sleep, nanosleep): ...these current POSIX functions, and also...
+ (usleep): ...this obsolete one; mark it as deprecated.
+
+ * include/parts: New directory; it is intended to host partial header
+ implementations, for content which must be shared among arbitrary sets
+ of multiple standard header files.
+
+ * include/parts/time.h: New file; nominally declaring time.h content.
+ (struct timespec): Declare it; it is currently used within unistd.h,
+ to facilitate the __CRT_INLINE implementation of nanosleep().
+
+ * Makefile.in (libmingwex.a): Remove reference to...
+ (usleep.$OBJEXT): ...this; replace it with a reference to...
+ (nsleep.$OBJEXT): ...this alternative.
+ (mingwrt-includedirs): Add prerequisite to create...
+ ($includedir/parts): ...this new directory; it is populated by...
+ (install-mingwrt-headers): ...this rule; add requisite command.
+
2014-12-13 Keith Marshall <keithmarshall@users.sourceforge.net>
Delete an unnecessary Unicode wrapper file.
#
#libmingwex.a: $(addsuffix .$(OBJEXT), glob membarrier)
libmingwex.a: $(addsuffix .$(OBJEXT), mingw-aligned-malloc mingw-fseek)
-libmingwex.a: $(addsuffix .$(OBJEXT), glob getopt basename dirname usleep)
+libmingwex.a: $(addsuffix .$(OBJEXT), glob getopt basename dirname nsleep)
libmingwex.a: $(addsuffix .$(OBJEXT), mkstemp mkdtemp cryptnam)
libmingwex.a: $(addsuffix .$(OBJEXT), tdelete tfind tsearch twalk)
includedirs: mingwrt-includedirs
install-headers install-mingwrt: install-mingwrt-headers
-${includedir}/sys: includedir
-mingwrt-includedirs: ${includedir}/sys
+${includedir}/sys ${includedir}/parts: includedir
+mingwrt-includedirs: ${includedir}/sys ${includedir}/parts
$(mkinstalldirs) $^
install-mingwrt-headers: mingwrt-includedirs
$(INSTALL_DATA) ${mingwrt_srcdir}/include/*.h ${includedir}
$(INSTALL_DATA) ${mingwrt_srcdir}/include/sys/*.h ${includedir}/sys
+ $(INSTALL_DATA) ${mingwrt_srcdir}/include/parts/*.h ${includedir}/parts
$(INSTALL_DATA) ${mingwrt_srcdir}/profile/*.h ${includedir}
# Install libraries, and supporting free standing object files.
--- /dev/null
+/*
+ * parts/time.h
+ *
+ * Internal header file, declaring types and structures which nominally
+ * originate from time.h, but which POSIX requires to be made visible on
+ * inclusion of certain other headers, without including time.h itself.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2014, MinGW.org Project.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#if _FAKE_TIME_H_SOURCED
+/*
+ * Since we expect this part-header to be sourced exclusively by other
+ * system headers, (nominally time.h), we don't apply any conventional
+ * multiple inclusion guard; rather, we rely on the guard within time.h
+ * itself, but allow other headers to fake it for one-shot inclusion
+ * only...
+ */
+# undef _FAKE_TIME_H_SOURCED
+
+#elif ! defined _TIME_H
+/*
+ * ...otherwise, we fail if the time.h guard is not in place.
+ */
+# error "Never include <parts/time.h> directly; use <time.h> instead"
+#endif
+
+#if defined __need_struct_timespec && ! __struct_timespec_defined
+/*
+ * Structure timespec is mandated by POSIX, for specification of
+ * intervals with the greatest precision supported by the OS kernel.
+ * Although this allows for specification to nanosecond precision, do
+ * not be deluded into any false expectation that such short intervals
+ * can be realized on Windows; on Win9x derivatives, the metronome used
+ * by the process scheduler has a period of ~55 milliseconds, while for
+ * WinNT derivatives, the corresponding period is ~15 milliseconds; thus,
+ * the shortest intervals which can be realistically timed will range
+ * from 0..55 milliseconds on Win9x hosts, and from 0..15 ms on WinNT,
+ * with period values normally distributed around means of ~27.5 ms
+ * and ~7.5 ms, for the two system types respectively.
+ */
+struct timespec
+{
+ /* Period is sum of tv_sec + tv_nsec; use fundamental integer types
+ * to avoid 32-bit vs. 64-bit time_t ambiguity.
+ */
+ long long tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+# define __struct_timespec_defined 1
+#endif
+
+/* $RCSfile$: end of file */
typedef long long off64_t;
#endif
-#if !defined __NO_ISOCEXT
-typedef unsigned int useconds_t;
-#endif /* Not __NO_ISOCEXT */
+#if _POSIX_C_SOURCE
+typedef unsigned long useconds_t __MINGW_ATTRIB_DEPRECATED;
+#endif
#endif /* Not RC_INVOKED */
#ifndef _UNISTD_H
/*
- * This file is part of the Mingw32 package.
+ * unistd.h
*
- * unistd.h maps (roughly) to io.h
+ * Standard header file declaring MinGW's POSIX compatibility features.
+ *
+ * $Id$
+ *
+ * Written by Rob Savoye <rob@cygnus.com>
+ * Modified by Earnie Boyd <earnie@users.sourceforge.net>
+ * Danny Smith <dannysmith@users.sourceforge.net>
+ * Ramiro Polla <ramiro@lisha.ufsc.br>
+ * Gregory McGarry <gregorymcgarry@users.sourceforge.net>
+ * Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 1997, 1999, 2002-2004, 2007-2009, 2014, MinGW.org Project.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#define _UNISTD_H 1
+#pragma GCC system_header
+
+/* All MinGW headers MUST include _mingw.h before anything else,
+ * to ensure proper initialization of feature test macros.
+ */
+#include <_mingw.h>
+
+/* unistd.h maps (roughly) to io.h
* Other headers included by unistd.h may be selectively processed;
* __UNISTD_H_SOURCED__ enables such selective processing.
*/
-#define _UNISTD_H
#define __UNISTD_H_SOURCED__ 1
#include <io.h>
#define SEEK_END 2
#endif
+#if _POSIX_C_SOURCE
+/*
+ * POSIX process/thread suspension functions; all are supported by a
+ * common MinGW API in libmingwex.a, providing for suspension periods
+ * ranging from mean values of ~7.5 milliseconds, (see comments below),
+ * extending up to a maximum of ~136 years.
+ *
+ * Note that, whereas POSIX supports early wake-up of any suspended
+ * process/thread, in response to a signal, this implementation makes
+ * no attempt to emulate this signalling behaviour, (since signals are
+ * not well supported by Windows); thus, unless impeded by an invalid
+ * argument, this implementation always returns an indication as if
+ * the sleeping period ran to completion.
+ */
+_EXTERN_C _cdecl __MINGW_NOTHROW
+int __mingw_sleep( unsigned long, unsigned long );
+
+/* Structure timespec is mandated by POSIX, for specification of
+ * intervals with the greatest precision supported by the OS kernel.
+ * Although this allows for specification to nanosecond precision, do
+ * not be deluded into any false expectation that such short intervals
+ * can be realized on Windows; on Win9x derivatives, the metronome used
+ * by the process scheduler has a period of ~55 milliseconds, while for
+ * WinNT derivatives, the corresponding period is ~15 milliseconds; thus,
+ * the shortest intervals which can be realistically timed will range
+ * from 0..55 milliseconds on Win9x hosts, and from 0..15 ms on WinNT,
+ * with period values normally distributed around means of ~27.5 ms
+ * and ~7.5 ms, for the two system types respectively.
+ */
+#define _FAKE_TIME_H_SOURCED 1
+#define __need_struct_timespec 1
+#include <parts/time.h>
+
_BEGIN_C_DECLS
-#if !defined __NO_ISOCEXT
-#include <sys/types.h> /* For useconds_t. */
+/* The nanosleep() function provides the most general purpose API for
+ * process/thread suspension; it provides for specification of periods
+ * ranging from ~7.5 ms mean, (on WinNT derivatives; ~27.5 ms on Win9x),
+ * extending up to ~136 years, (effectively eternity).
+ */
+_cdecl __MINGW_NOTHROW
+int nanosleep( const struct timespec *, struct timespec * );
-int __cdecl __MINGW_NOTHROW usleep(useconds_t useconds);
-#endif /* Not __NO_ISOCEXT */
+#ifndef __NO_INLINE__
+__CRT_INLINE __LIBIMPL__(( FUNCTION = nanosleep ))
+int nanosleep( const struct timespec *period, struct timespec *residual )
+{
+ if( residual != (void *)(0) )
+ residual->tv_sec = (long long)(residual->tv_nsec = 0);
+ return __mingw_sleep((unsigned)(period->tv_sec), (period->tv_sec < 0LL)
+ ? (unsigned)(-1) : (unsigned)(period->tv_nsec));
+}
+#endif
-/* This is defined both as a real library function, to allow autoconf
- * to verify its existence, and as a potentially inline implementation.
+/* The usleep() function, and its associated useconds_t type specifier
+ * were made obsolete in POSIX.1-2008; declared here, only for backward
+ * compatibility, its continued use is not recommended. (It is limited
+ * to specification of suspension periods ranging from ~7.5 ms mean up
+ * to a maximum of 999,999 microseconds only).
*/
-int ftruncate(int, off_t);
+typedef unsigned long useconds_t __MINGW_ATTRIB_DEPRECATED;
+int _cdecl __MINGW_NOTHROW usleep( useconds_t )__MINGW_ATTRIB_DEPRECATED;
+
+#ifndef __NO_INLINE__
+__CRT_INLINE __LIBIMPL__(( FUNCTION = usleep ))
+int usleep( useconds_t period ){ return __mingw_sleep( 0, 1000 * period ); }
+#endif
+
+/* The sleep() function is, perhaps, the most commonly used of all the
+ * process/thread suspension APIs; it provides support for specification
+ * of suspension periods ranging from 1 second to ~136 years. (However,
+ * POSIX recommends limiting the maximum period to 65535 seconds, to
+ * maintain portability to platforms with only 16-bit ints).
+ */
+unsigned _cdecl __MINGW_NOTHROW sleep( unsigned );
+
+#ifndef __NO_INLINE__
+__CRT_INLINE __LIBIMPL__(( FUNCTION = sleep ))
+unsigned sleep( unsigned period ){ return __mingw_sleep( period, 0 ); }
+#endif
+
+
+/* POSIX ftruncate() function.
+ *
+ * Microsoft's _chsize() function is incorrectly described, on MSDN,
+ * as a preferred replacement for the POSIX chsize() function. There
+ * never was any such POSIX function; the actual POSIX equivalent is
+ * the ftruncate() function.
+ */
+int _cdecl ftruncate( int, off_t );
+
#ifndef __NO_INLINE__
__CRT_INLINE __JMPSTUB__(( FUNCTION = ftruncate, REMAPPED = _chsize ))
-int ftruncate(int __fd, off_t __length)
-{ return _chsize (__fd, __length); }
+int ftruncate( int __fd, off_t __length ){ return _chsize( __fd, __length ); }
#endif
_END_C_DECLS
+#endif /* _POSIX_C_SOURCE */
+
#undef __UNISTD_H_SOURCED__
-#endif /* _UNISTD_H */
+#endif /* ! _UNISTD_H: $RCSfile$: end of file */
--- /dev/null
+/*
+ * nsleep.c
+ *
+ * Core implementation of the __mingw_sleep() API, which facilitates the
+ * provision of (mostly) POSIX compliant sleep(), usleep(), and nanosleep()
+ * functions, (per inline implementations in unistd.h).
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2014, MinGW.org Project.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+
+/* Including windows.h, just to declare Sleep(), seems like overkill; we
+ * prefer to declare it directly, to ensure we get the kernel DLL import,
+ * without the overhead of redirection through a libkernel.a trampoline.
+ */
+__declspec(dllimport) _stdcall void Sleep( unsigned long );
+
+int __mingw_sleep( unsigned long secs, unsigned long nsecs )
+{
+ /* Entry point for general purpose sleep() function API, supporting
+ * the __CRT_INLINE implementations of the three functions identified
+ * in the file description above.
+ */
+ if( (secs | nsecs) > 0UL )
+ {
+ /* At least one of the seconds or nanoseconds components must
+ * be non-zero, to require us to perform any action.
+ */
+ if( nsecs < 1000000000UL )
+ {
+ /* POSIX requires the nanoseconds component of the specified
+ * interval to be less than one full second (1,000,000,000 ns);
+ * we've satisfied that requirement, so we proceed to combine
+ * the seconds and nanoseconds components into a millisecond
+ * representation, as required by the kernel's Sleep() API,
+ * (using a 64-bit representation, to avoid overflow).
+ */
+ unsigned long long interval = (secs > 0UL)
+ ? secs * 1000ULL + ((nsecs > 0UL) ? nsecs / 1000000ULL : 0ULL)
+ : (nsecs + 999999ULL) / 1000000ULL;
+
+ /* It is unlikely that we should ever need this, (but it is
+ * possible, so we proceed defensively)...
+ */
+ while( interval > (unsigned long long)(LONG_MAX) )
+ {
+ /* ...breaking excessively long intervals into cycles of
+ * LONG_MAX milliseconds, (~25 days, and we may be asked
+ * to sleep through up to 2000 cycles, or ~136 years), so
+ * that we avoid any interval value with the high bit set
+ * (lest that be interpreted as "sleep forever").
+ */
+ Sleep( (unsigned long)(LONG_MAX) );
+ interval -= (unsigned long long)(LONG_MAX);
+ }
+ /* Since suspension requests of 25 days are unlikely, in
+ * the majority of cases we should simply skip over the
+ * preceding loop; we must still call Sleep(), either to
+ * satisfy the original request in its entirety, or the
+ * residual from the loop.
+ */
+ Sleep( (unsigned long)(interval) );
+ }
+ else
+ { /* We were given a nanoseconds component value, within the
+ * interval specification, which exceeds one full second; in
+ * this event, POSIX specifies the following failure:
+ */
+ errno = EINVAL;
+ return -1;
+ }
+ }
+ /* On success, or maybe having done nothing at all, we simply
+ * return zero; (note that Windows Sleep() isn't interruptible
+ * in the way that that POSIX sleep() is, so we do not provide
+ * any indication of an uncompleted interval).
+ */
+ return 0;
+}
+
+/* $RCSfile$: end of file */
+++ /dev/null
-/*
- * usleep
- * Implementation according to:
- * The Open Group Base Specifications Issue 6
- * IEEE Std 1003.1, 2004 Edition
- */
-
-/*
- * THIS SOFTWARE IS NOT COPYRIGHTED
- *
- * This source code is offered for use in the public domain. You may
- * use, modify or distribute it freely.
- *
- * This code is distributed in the hope that it will be useful but
- * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
- * DISCLAIMED. This includes but is not limited to warranties of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Contributed by:
- * Ramiro Polla <ramiro@lisha.ufsc.br>
- */
-
-#include <sys/types.h>
-#include <errno.h>
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-int __cdecl usleep(useconds_t useconds)
-{
- if(useconds == 0)
- return 0;
-
- if(useconds >= 1000000)
- return EINVAL;
-
- Sleep((useconds + 999) / 1000);
-
- return 0;
-}