# HG changeset patch
# Parent 258fbecbf6660a1aa479c22fe21ab98dfc82d365
Implement basic thread-safe I/O integration hooks.

diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in
--- a/mingwrt/Makefile.in
+++ b/mingwrt/Makefile.in
@@ -418,10 +418,19 @@ libmingwex.a: $(addsuffix .$(OBJEXT), co
   powf powl powi powif powil remainder remainderf remainderl remquo remquof \
   remquol rint rintf rintl round roundf roundl scalbn scalbnf scalbnl signbit \
   signbitf signbitl sqrtf sqrtl tgamma tgammaf tgammal trunc truncf truncl \
   x87cvt x87cvtf x87log x87log1p x87pow)
 
+# Thread-safe file descriptor based I/O extensions in libmingwex.a
+#
+libmingwex.a: $(addsuffix .$(OBJEXT),xfdtemp xfdlseek)
+libmingwex.a: $(addsuffix .$(OBJEXT),xfdcntl xfddup xfddup2)
+libmingwex.a: $(addsuffix .$(OBJEXT),xfdtab xfdcreat xfdopen xfdclose)
+libmingwex.a: $(addsuffix .$(OBJEXT),xfdread xfdwrite xfdpread xfdpwrite)
+xfdpwrite.$(OBJEXT) xfdwrite.$(OBJEXT): xfd%write.$(OBJEXT): xfd%read.c
+	$(CC) -c -D FUNCTION=$*write $(CPPFLAGS) $(ALL_CFLAGS) -o $@ $<
+
 # Replacement I/O functions in libmingwex.a, providing better POSIX
 # compatibility than their Microsoft equivalents.
 #
 vpath %.c ${mingwrt_srcdir}/mingwex/stdio
 libmingwex.a: $(addsuffix .$(OBJEXT), btowc fprintf fseeko64 ofmtctl pformat \
diff --git a/mingwrt/include/io.h b/mingwrt/include/io.h
--- a/mingwrt/include/io.h
+++ b/mingwrt/include/io.h
@@ -498,15 +498,17 @@ int _wfindnexti64 (intptr_t __handle, st
 _CRTIMP __cdecl __MINGW_NOTHROW  __int64 _filelengthi64 (int);
 _CRTIMP __cdecl __MINGW_NOTHROW  __int64 _lseeki64 (int, __int64, int);
 _CRTIMP __cdecl __MINGW_NOTHROW  __int64 _telli64 (int);
 
 #ifndef __NO_MINGW_LFS
+#if defined _NO_OLDNAMES || ! defined _MINGW_THREADSAFE_IO
 __CRT_INLINE __off64_t lseek64 (int, __off64_t, int);
 __CRT_INLINE __JMPSTUB__(( FUNCTION = lseek64, REMAPPED = _lseeki64 ))
 __off64_t lseek64 (int fd, __off64_t offset, int whence)
 { return _lseeki64 (fd, (__int64)(offset), whence); }
-#endif
+#endif	/* _NO_OLDNAMES || !_MINGW_THREADSAFE_IO */
+#endif	/* !__NO_MINGW_LFS */
 
 #endif /* __MSVCRT__ */
 
 #ifndef _NO_OLDNAMES
 
@@ -646,29 +648,97 @@ int _wfindnexti64 (intptr_t __handle, st
 /* Non-underscored versions of non-ANSI functions to improve portability;
  * these are implemented in libmoldname.a, and once again are declared
  * only when <io.h> is included directly.
  */
 #ifndef _UWIN
+#ifdef _MINGW_THREADSAFE_IO
+/* When the user opts in to use MinGW thread-safe I/O, a number of the
+ * file descriptor related libmoldname.a functions are overridden, such
+ * that they are replaced by thread safe alternatives, each of which is
+ * furnished by libmingwex.a
+ */
+#define __XFD_CDECL   __XFD_INLINE __cdecl __MINGW_NOTHROW
+#define __XFD_INLINE  static __inline__ __attribute__((__always_inline__))
+#define __XFD_EXTERN  extern __cdecl __MINGW_NOTHROW
+
+__XFD_EXTERN  int __mingw_xfd_creat (const char *, int);
+__XFD_CDECL int creat (const char *__name, int __pmode)
+{ return __mingw_xfd_creat (__name, __pmode); }
+
+__XFD_EXTERN  int __mingw_xfd_open (const char *, int, ...);
+static __cdecl __MINGW_NOTHROW  open (const char *name, int mode, ...)
+{ __builtin_va_list pmode; __builtin_va_start (pmode, mode);
+  int retval = __mingw_xfd_open (name, mode, __builtin_va_arg (pmode, int));
+  __builtin_va_end (pmode); return retval;
+}
+
+__XFD_EXTERN  ssize_t __mingw_xfd_read (int, void *, size_t);
+__XFD_CDECL ssize_t read (int __fd, void *__buf, size_t __count)
+{ return __mingw_xfd_read (__fd, __buf, __count); }
+
+__XFD_EXTERN  __off64_t __mingw_xfd_lseek (int, __off64_t, int);
+__XFD_CDECL off_t lseek (int __fd, off_t __offset, int __whence)
+{ return (off_t)(__mingw_xfd_lseek (__fd, (off64_t)(__offset), __whence)); }
+__XFD_CDECL __off64_t lseek64 (int __fd, __off64_t __offset, int __whence)
+{ return __mingw_xfd_lseek (__fd, __offset, __whence); }
+
+__XFD_EXTERN  ssize_t __mingw_xfd_write (int, const void *, size_t);
+__XFD_CDECL ssize_t write (int __fd, const void *__buf, size_t __count)
+{ return __mingw_xfd_write (__fd, __buf, __count); }
+
+__XFD_EXTERN  int __mingw_xfd_close (int);
+__XFD_CDECL int close (int __fd) { return __mingw_xfd_close (__fd); }
+
+__XFD_EXTERN  int __mingw_xfd_dup2 (int, int);
+__XFD_CDECL int dup2 (int __fd1, int __fd2) { return __mingw_xfd_dup2 (__fd1, __fd2); }
+
+__XFD_EXTERN  int __mingw_xfd_dup (int);
+__XFD_CDECL int dup (int __fd) { return __mingw_xfd_dup (__fd); }
+
+#if _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200809L
+/* The following POSIX.1 functions were introduced under version 5 of
+ * the extended systems interface options, and formally incorporated in
+ * the base standard as of POSIX.1-2008; they are supported in MinGW,
+ * ONLY when the user opts in to use the thread-safe I/O option.
+ */
+__XFD_EXTERN  ssize_t __mingw_xfd_pread (int, void *, size_t, __off64_t);
+__XFD_CDECL ssize_t pread (int __fd, void *__buf, size_t __count, __off64_t __ofs)
+{ return __mingw_xfd_pread (__fd, __buf, __count, __ofs); }
+
+__XFD_EXTERN  ssize_t __mingw_xfd_pwrite (int, const void *, size_t, __off64_t);
+__XFD_CDECL ssize_t pwrite (int __fd, const void *__buf, size_t __count, __off64_t __ofs)
+{ return __mingw_xfd_pwrite (__fd, __buf, __count, __ofs); }
+#endif	/* XSI-500 || POSIX.1-2008 */
+
+#else	/* !_MINGW_THREADSAFE_IO */
+/* Opt in to use MinGW thread-safe I/O has not been requested; declare
+ * these basic function prototypes, as provided by libmoldname.a
+ */
+_CRTIMP __cdecl __MINGW_NOTHROW  int creat (const char *, int);
+_CRTIMP __cdecl __MINGW_NOTHROW  int open (const char *, int, ...);
+_CRTIMP __cdecl __MINGW_NOTHROW  ssize_t read (int, void *, size_t);
+_CRTIMP __cdecl __MINGW_NOTHROW  ssize_t write (int, const void *, size_t);
+_CRTIMP __cdecl __MINGW_NOTHROW  off_t lseek (int, off_t, int);
+_CRTIMP __cdecl __MINGW_NOTHROW  int close (int);
+_CRTIMP __cdecl __MINGW_NOTHROW  int dup2 (int, int);
+_CRTIMP __cdecl __MINGW_NOTHROW  int dup (int);
+
+#endif	/* !_MINGW_THREADSAFE_IO */
+/* The remaining function prototypes, in this libmoldname.a group, are
+ * defined identically, regardless of MinGW thread-safe I/O opt-in.
+ */
 _CRTIMP __cdecl __MINGW_NOTHROW  int access (const char*, int);
-_CRTIMP __cdecl __MINGW_NOTHROW  int chsize (int, long );
-_CRTIMP __cdecl __MINGW_NOTHROW  int close (int);
-_CRTIMP __cdecl __MINGW_NOTHROW  int creat (const char*, int);
-_CRTIMP __cdecl __MINGW_NOTHROW  int dup (int);
-_CRTIMP __cdecl __MINGW_NOTHROW  int dup2 (int, int);
+_CRTIMP __cdecl __MINGW_NOTHROW  int chsize (int, long);
 _CRTIMP __cdecl __MINGW_NOTHROW  int eof (int);
 _CRTIMP __cdecl __MINGW_NOTHROW  long filelength (int);
 _CRTIMP __cdecl __MINGW_NOTHROW  int isatty (int);
-_CRTIMP __cdecl __MINGW_NOTHROW  long lseek (int, long, int);
-_CRTIMP __cdecl __MINGW_NOTHROW  int open (const char*, int, ...);
-_CRTIMP __cdecl __MINGW_NOTHROW  int read (int, void*, unsigned int);
 _CRTIMP __cdecl __MINGW_NOTHROW  int setmode (int, int);
 _CRTIMP __cdecl __MINGW_NOTHROW  int sopen (const char*, int, int, ...);
 _CRTIMP __cdecl __MINGW_NOTHROW  long tell (int);
 _CRTIMP __cdecl __MINGW_NOTHROW  int umask (int);
 _CRTIMP __cdecl __MINGW_NOTHROW  int unlink (const char*);
-_CRTIMP __cdecl __MINGW_NOTHROW  int write (int, const void*, unsigned int);
-#endif /* !_UWIN */
+#endif	/* !_UWIN */
 
 #ifdef __USE_MINGW_ACCESS
 /* Old versions of MSVCRT.DLL's access() just ignored X_OK, while the
  * version shipped with Vista fails; this inline implementation of the
  * portably named access() function protects against such failure.
diff --git a/mingwrt/include/stdlib.h b/mingwrt/include/stdlib.h
--- a/mingwrt/include/stdlib.h
+++ b/mingwrt/include/stdlib.h
@@ -803,14 +803,21 @@ unsigned __int64 _strtoui64_l(const char
 
 #ifndef _NO_OLDNAMES
 #define MKSTEMP_SETMODE(M)  __mingw_mkstemp( _MKSTEMP_DEFAULT | (M), NULL )
 #endif
 
+#ifdef _MINGW_THREADSAFE_IO
+__cdecl __MINGW_NOTHROW  int __mingw_xfd_mkstemp (char *);
+__CRT_ALIAS __cdecl __MINGW_NOTHROW  int mkstemp (char *__filename_template)
+{ return __mingw_xfd_mkstemp( __filename_template ); }
+
+#else	/* !_MINGW_THREADSAFE_IO */
 __CRT_ALIAS __LIBIMPL__(( FUNCTION = mkstemp ))
 __cdecl __MINGW_NOTHROW  int mkstemp (char *__filename_template)
 { return __mingw_mkstemp( _MKSTEMP_INVOKE, __filename_template ); }
 
+#endif	/* !_MINGW_THREADSAFE_IO */
 #endif	/* _POSIX_C_SOURCE >= 200112L (for mkstemp()) */
 
 /* mkdtemp(3) function support: added as adjunct to feature request #2003.
  * POSIX wants _XOPEN_SOURCE >= 700, (implying _POSIX_C_SOURCE >= 200809L).
  */
