Now _lock_file/_unlock_file are in stdio/mingw_lock.c (new) file.

printf_full.diff works out of the box but I edited makefile.am & makefile.in by hands which is wrong. I tested this patch with 64 and 32-bit GCC 5.2 with link to msvcrt.dll/msvcr100.dll/msvcr120.dll -- all is working.

printf.diff is only with *.c files and needs (proper) modification to makefile.am/makefile.in -- stdio/mingw_lock.c should go to libmsvcrt.a and to libmsvcr80.a

I attached new version of test-stdio.c because when I test with 32-bit GCC and link to msvcr120.dll there is no "ftime" function, so I changed to "_ftime64".

W dniu 2015-08-02 o 10:04, JonY pisze:
On 8/2/2015 09:15, Mateusz wrote:
I'm not diff expert, but I tried "git diff" -- maybe now is better. Due
to problem with new file I copy context of "mingw_lock.c" to smallest
"ftello.c" -- surprisingly make install works and with new
"libmingwex.a" I can compile "test-stdio.c" file and it is working.

Could you/Kai show example of performance drop with this patch?

Personally, I think the patch is nearly OK, but the lock/unlock
functions should go into its own files, not something hard to correct.

Kai, anything?



------------------------------------------------------------------------------


_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

diff --git a/mingw-w64-crt/stdio/mingw_fprintf.c 
b/mingw-w64-crt/stdio/mingw_fprintf.c
index 011a634..438941f 100644
--- a/mingw-w64-crt/stdio/mingw_fprintf.c
+++ b/mingw-w64-crt/stdio/mingw_fprintf.c
@@ -50,7 +50,9 @@ int __cdecl __fprintf(FILE *stream, const APICHAR *fmt, ...)
 {
   register int retval;
   va_list argv; va_start( argv, fmt );
+  _lock_file( stream );
   retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv 
);
+  _unlock_file( stream );
   va_end( argv );
   return retval;
 }
diff --git a/mingw-w64-crt/stdio/mingw_lock.c b/mingw-w64-crt/stdio/mingw_lock.c
new file mode 100644
index 0000000..e62fe03
--- /dev/null
+++ b/mingw-w64-crt/stdio/mingw_lock.c
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <synchapi.h>
+#include "internal.h"
+
+/***
+ * Copy of MS functions _lock_file, _unlock_file which are missing from
+ * msvcrt.dll and msvcr80.dll. They are needed to atomic/lock stdio
+ * functions (printf, fprintf, vprintf, vfprintf). We need exactly the same
+ * lock that MS uses in msvcrt.dll because we can mix mingw-w64 code with
+ * original MS functions (puts, fputs for example).
+***/ 
+
+
+_CRTIMP void __cdecl _lock(int locknum);
+_CRTIMP void __cdecl _unlock(int locknum);
+#define _STREAM_LOCKS   16
+#define _IOLOCKED       0x8000
+
+
+/***
+* _lock_file - Lock a FILE
+*
+*Purpose:
+*       Assert the lock for a stdio-level file
+*
+*Entry:
+*       pf = __piob[] entry (pointer to a FILE or _FILEX)
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __cdecl _lock_file( FILE *pf )
+{
+    /*
+     * The way the FILE (pointed to by pf) is locked depends on whether
+     * it is part of _iob[] or not
+     */
+    if ( (pf >= (&__iob_func()[0])) && (pf <= (&__iob_func()[_IOB_ENTRIES-1])) 
)
+    {
+        /*
+         * FILE lies in _iob[] so the lock lies in _locktable[].
+         */
+        _lock( _STREAM_LOCKS + (int)(pf - (&__iob_func()[0])) );
+        /* We set _IOLOCKED to indicate we locked the stream */
+        pf->_flag |= _IOLOCKED;
+    }
+    else
+        /*
+         * Not part of _iob[]. Therefore, *pf is a _FILEX and the
+         * lock field of the struct is an initialized critical
+         * section.
+         */
+        EnterCriticalSection( &(((_FILEX *)pf)->lock) );
+}
+
+
+/***
+* _unlock_file - Unlock a FILE
+*
+*Purpose:
+*       Release the lock for a stdio-level file
+*
+*Entry:
+*       pf = __piob[] entry (pointer to a FILE or _FILEX)
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __cdecl _unlock_file( FILE *pf )
+{
+    /*
+     * The way the FILE (pointed to by pf) is unlocked depends on whether
+     * it is part of _iob[] or not
+     */
+    if ( (pf >= (&__iob_func()[0])) && (pf <= (&__iob_func()[_IOB_ENTRIES-1])) 
)
+    {
+        /*
+         * FILE lies in _iob[] so the lock lies in _locktable[].
+         * We reset _IOLOCKED to indicate we unlock the stream.
+         */
+        pf->_flag &= ~_IOLOCKED;
+        _unlock( _STREAM_LOCKS + (int)(pf - (&__iob_func()[0])) );
+    }
+    else
+        /*
+         * Not part of _iob[]. Therefore, *pf is a _FILEX and the
+         * lock field of the struct is an initialized critical
+         * section.
+         */
+        LeaveCriticalSection( &(((_FILEX *)pf)->lock) );
+}
diff --git a/mingw-w64-crt/stdio/mingw_printf.c 
b/mingw-w64-crt/stdio/mingw_printf.c
index 5d23b02..fbd2e7d 100644
--- a/mingw-w64-crt/stdio/mingw_printf.c
+++ b/mingw-w64-crt/stdio/mingw_printf.c
@@ -50,7 +50,9 @@ int __cdecl __printf(const APICHAR *fmt, ...)
 {
   register int retval;
   va_list argv; va_start( argv, fmt );
+  _lock_file( stdout );
   retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv 
);
+  _unlock_file( stdout );
   va_end( argv );
   return retval;
 }
diff --git a/mingw-w64-crt/stdio/mingw_vfprintf.c 
b/mingw-w64-crt/stdio/mingw_vfprintf.c
index 68a0008..01ad01b 100644
--- a/mingw-w64-crt/stdio/mingw_vfprintf.c
+++ b/mingw-w64-crt/stdio/mingw_vfprintf.c
@@ -48,5 +48,11 @@ int __cdecl __vfprintf (FILE *, const APICHAR *, va_list) 
__MINGW_NOTHROW;
 
 int __cdecl __vfprintf(FILE *stream, const APICHAR *fmt, va_list argv)
 {
-  return __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv );
+  register int retval;
+
+  _lock_file( stream );
+  retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv 
);
+  _unlock_file( stream );
+
+  return retval;
 }
diff --git a/mingw-w64-crt/stdio/mingw_vprintf.c 
b/mingw-w64-crt/stdio/mingw_vprintf.c
index c60431a..4098d49 100644
--- a/mingw-w64-crt/stdio/mingw_vprintf.c
+++ b/mingw-w64-crt/stdio/mingw_vprintf.c
@@ -48,5 +48,11 @@ int __cdecl __vprintf (const APICHAR *, va_list) 
__MINGW_NOTHROW;
 
 int __cdecl __vprintf(const APICHAR *fmt, va_list argv)
 {
-  return __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv );
+  register int retval;
+
+  _lock_file( stdout );
+  retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv 
);
+  _unlock_file( stdout );
+
+  return retval;
 }
diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 30cc247..a137750 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -196,7 +196,8 @@ src_msvcrt=\
   secapi/strerror_s.c \
   secapi/vsprintf_s.c \
   secapi/wmemcpy_s.c \
-  secapi/wmemmove_s.c
+  secapi/wmemmove_s.c \
+  stdio/mingw_lock.c
 
 src_msvcrt32=\
   $(src_msvcrt) \
diff --git a/mingw-w64-crt/Makefile.in b/mingw-w64-crt/Makefile.in
index 162879c..26047f3 100644
--- a/mingw-w64-crt/Makefile.in
+++ b/mingw-w64-crt/Makefile.in
@@ -1155,7 +1155,7 @@ am__lib32_libmsvcrt_a_SOURCES_DIST = 
misc/invalid_parameter_handler.c \
        secapi/_wstrtime_s.c secapi/_wmktemp_s.c secapi/_wstrdate_s.c \
        secapi/asctime_s.c secapi/memcpy_s.c secapi/memmove_s.c \
        secapi/rand_s.c secapi/sprintf_s.c secapi/strerror_s.c \
-       secapi/vsprintf_s.c secapi/wmemcpy_s.c secapi/wmemmove_s.c \
+       secapi/vsprintf_s.c secapi/wmemcpy_s.c secapi/wmemmove_s.c 
stdio/mingw_lock.c \
        misc/lc_locale_func.c lib32/msvcrt.def.in
 am__objects_23 =  \
        misc/lib32_libmsvcrt_a-invalid_parameter_handler.$(OBJEXT) \
@@ -1200,7 +1200,8 @@ am__objects_23 =  \
        secapi/lib32_libmsvcrt_a-strerror_s.$(OBJEXT) \
        secapi/lib32_libmsvcrt_a-vsprintf_s.$(OBJEXT) \
        secapi/lib32_libmsvcrt_a-wmemcpy_s.$(OBJEXT) \
-       secapi/lib32_libmsvcrt_a-wmemmove_s.$(OBJEXT)
+       secapi/lib32_libmsvcrt_a-wmemmove_s.$(OBJEXT) \
+       stdio/lib32_libmsvcrt_a-mingw_lock.$(OBJEXT)
 am__objects_24 = $(am__objects_23) \
        misc/lib32_libmsvcrt_a-lc_locale_func.$(OBJEXT)
 @LIB32_TRUE@@W32API_FALSE@am_lib32_libmsvcrt_a_OBJECTS =  \
@@ -2322,7 +2323,7 @@ am__lib64_libmsvcrt_a_SOURCES_DIST = 
misc/invalid_parameter_handler.c \
        secapi/_wstrtime_s.c secapi/_wmktemp_s.c secapi/_wstrdate_s.c \
        secapi/asctime_s.c secapi/memcpy_s.c secapi/memmove_s.c \
        secapi/rand_s.c secapi/sprintf_s.c secapi/strerror_s.c \
-       secapi/vsprintf_s.c secapi/wmemcpy_s.c secapi/wmemmove_s.c \
+       secapi/vsprintf_s.c secapi/wmemcpy_s.c secapi/wmemmove_s.c 
stdio/mingw_lock.c \
        lib64/msvcrt.def.in
 am__objects_59 =  \
        misc/lib64_libmsvcrt_a-invalid_parameter_handler.$(OBJEXT) \
@@ -2367,7 +2368,8 @@ am__objects_59 =  \
        secapi/lib64_libmsvcrt_a-strerror_s.$(OBJEXT) \
        secapi/lib64_libmsvcrt_a-vsprintf_s.$(OBJEXT) \
        secapi/lib64_libmsvcrt_a-wmemcpy_s.$(OBJEXT) \
-       secapi/lib64_libmsvcrt_a-wmemmove_s.$(OBJEXT)
+       secapi/lib64_libmsvcrt_a-wmemmove_s.$(OBJEXT) \
+       stdio/lib64_libmsvcrt_a-mingw_lock.$(OBJEXT)
 @LIB64_TRUE@@W32API_FALSE@am_lib64_libmsvcrt_a_OBJECTS =  \
 @LIB64_TRUE@@W32API_FALSE@     $(am__objects_59)
 lib64_libmsvcrt_a_OBJECTS = $(am_lib64_libmsvcrt_a_OBJECTS)
@@ -5190,7 +5192,8 @@ src_msvcrt = \
   secapi/strerror_s.c \
   secapi/vsprintf_s.c \
   secapi/wmemcpy_s.c \
-  secapi/wmemmove_s.c
+  secapi/wmemmove_s.c \
+  stdio/mingw_lock.c
 
 src_msvcrt32 = \
   $(src_msvcrt) \
@@ -9265,6 +9268,8 @@ secapi/lib32_libmsvcrt_a-wmemcpy_s.$(OBJEXT): 
secapi/$(am__dirstamp) \
        secapi/$(DEPDIR)/$(am__dirstamp)
 secapi/lib32_libmsvcrt_a-wmemmove_s.$(OBJEXT): secapi/$(am__dirstamp) \
        secapi/$(DEPDIR)/$(am__dirstamp)
+stdio/lib32_libmsvcrt_a-mingw_lock.$(OBJEXT): stdio/$(am__dirstamp) \
+       stdio/$(DEPDIR)/$(am__dirstamp)
 misc/lib32_libmsvcrt_a-lc_locale_func.$(OBJEXT): misc/$(am__dirstamp) \
        misc/$(DEPDIR)/$(am__dirstamp)
 
@@ -10906,6 +10911,8 @@ secapi/lib64_libmsvcrt_a-wmemcpy_s.$(OBJEXT): 
secapi/$(am__dirstamp) \
        secapi/$(DEPDIR)/$(am__dirstamp)
 secapi/lib64_libmsvcrt_a-wmemmove_s.$(OBJEXT): secapi/$(am__dirstamp) \
        secapi/$(DEPDIR)/$(am__dirstamp)
+stdio/lib64_libmsvcrt_a-mingw_lock.$(OBJEXT): stdio/$(am__dirstamp) \
+       stdio/$(DEPDIR)/$(am__dirstamp)
 
 lib64/libmsvcrt.a: $(lib64_libmsvcrt_a_OBJECTS) 
$(lib64_libmsvcrt_a_DEPENDENCIES) $(EXTRA_lib64_libmsvcrt_a_DEPENDENCIES) 
lib64/$(am__dirstamp)
        $(AM_V_at)-rm -f lib64/libmsvcrt.a
@@ -15458,6 +15465,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/lib32_libmsvcrt_a-vsprintf_s.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/lib32_libmsvcrt_a-wmemcpy_s.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/lib32_libmsvcrt_a-wmemmove_s.Po@am__quote@
+@AMDEP_TRUE@@am__include@ 
@am__quote@stdio/$(DEPDIR)/lib32_libmsvcrt_a-mingw_lock.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/lib64_libmsvcrt_a-_access_s.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/lib64_libmsvcrt_a-_cgets_s.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/lib64_libmsvcrt_a-_cgetws_s.Po@am__quote@
@@ -15498,6 +15506,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/lib64_libmsvcrt_a-vsprintf_s.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/lib64_libmsvcrt_a-wmemcpy_s.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/lib64_libmsvcrt_a-wmemmove_s.Po@am__quote@
+@AMDEP_TRUE@@am__include@ 
@am__quote@stdio/$(DEPDIR)/lib64_libmsvcrt_a-mingw_lock.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/libarm32_libmsvcrt_a-_access_s.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/libarm32_libmsvcrt_a-_cgets_s.Po@am__quote@
 @AMDEP_TRUE@@am__include@ 
@am__quote@secapi/$(DEPDIR)/libarm32_libmsvcrt_a-_cgetws_s.Po@am__quote@
@@ -25451,6 +25460,20 @@ secapi/lib32_libmsvcrt_a-wmemmove_s.obj: 
secapi/wmemmove_s.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(lib32_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c 
-o secapi/lib32_libmsvcrt_a-wmemmove_s.obj `if test -f 'secapi/wmemmove_s.c'; 
then $(CYGPATH_W) 'secapi/wmemmove_s.c'; else $(CYGPATH_W) 
'$(srcdir)/secapi/wmemmove_s.c'; fi`
 
+stdio/lib32_libmsvcrt_a-mingw_lock.o: stdio/mingw_lock.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(lib32_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT 
stdio/lib32_libmsvcrt_a-mingw_lock.o -MD -MP -MF 
stdio/$(DEPDIR)/lib32_libmsvcrt_a-mingw_lock.Tpo -c -o 
stdio/lib32_libmsvcrt_a-mingw_lock.o `test -f 'stdio/mingw_lock.c' || echo 
'$(srcdir)/'`stdio/mingw_lock.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) 
stdio/$(DEPDIR)/lib32_libmsvcrt_a-mingw_lock.Tpo 
stdio/$(DEPDIR)/lib32_libmsvcrt_a-mingw_lock.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='stdio/mingw_lock.c' 
object='stdio/lib32_libmsvcrt_a-mingw_lock.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(lib32_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c 
-o stdio/lib32_libmsvcrt_a-mingw_lock.o `test -f 'stdio/mingw_lock.c' || echo 
'$(srcdir)/'`stdio/mingw_lock.c
+
+stdio/lib32_libmsvcrt_a-mingw_lock.obj: stdio/mingw_lock.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(lib32_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT 
stdio/lib32_libmsvcrt_a-mingw_lock.obj -MD -MP -MF 
stdio/$(DEPDIR)/lib32_libmsvcrt_a-mingw_lock.Tpo -c -o 
stdio/lib32_libmsvcrt_a-mingw_lock.obj `if test -f 'stdio/mingw_lock.c'; then 
$(CYGPATH_W) 'stdio/mingw_lock.c'; else $(CYGPATH_W) 
'$(srcdir)/stdio/mingw_lock.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) 
stdio/$(DEPDIR)/lib32_libmsvcrt_a-mingw_lock.Tpo 
stdio/$(DEPDIR)/lib32_libmsvcrt_a-mingw_lock.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='stdio/mingw_lock.c' 
object='stdio/lib32_libmsvcrt_a-mingw_lock.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(lib32_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c 
-o stdio/lib32_libmsvcrt_a-mingw_lock.obj `if test -f 'stdio/mingw_lock.c'; 
then $(CYGPATH_W) 'stdio/mingw_lock.c'; else $(CYGPATH_W) 
'$(srcdir)/stdio/mingw_lock.c'; fi`
+
 misc/lib32_libmsvcrt_a-lc_locale_func.o: misc/lc_locale_func.c
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(lib32_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT 
misc/lib32_libmsvcrt_a-lc_locale_func.o -MD -MP -MF 
misc/$(DEPDIR)/lib32_libmsvcrt_a-lc_locale_func.Tpo -c -o 
misc/lib32_libmsvcrt_a-lc_locale_func.o `test -f 'misc/lc_locale_func.c' || 
echo '$(srcdir)/'`misc/lc_locale_func.c
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) 
misc/$(DEPDIR)/lib32_libmsvcrt_a-lc_locale_func.Tpo 
misc/$(DEPDIR)/lib32_libmsvcrt_a-lc_locale_func.Po
@@ -34733,6 +34756,20 @@ secapi/lib64_libmsvcrt_a-wmemmove_s.obj: 
secapi/wmemmove_s.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(lib64_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c 
-o secapi/lib64_libmsvcrt_a-wmemmove_s.obj `if test -f 'secapi/wmemmove_s.c'; 
then $(CYGPATH_W) 'secapi/wmemmove_s.c'; else $(CYGPATH_W) 
'$(srcdir)/secapi/wmemmove_s.c'; fi`
 
+stdio/lib64_libmsvcrt_a-mingw_lock.o: stdio/mingw_lock.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(lib64_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT 
stdio/lib64_libmsvcrt_a-mingw_lock.o -MD -MP -MF 
stdio/$(DEPDIR)/lib64_libmsvcrt_a-mingw_lock.Tpo -c -o 
stdio/lib64_libmsvcrt_a-mingw_lock.o `test -f 'stdio/mingw_lock.c' || echo 
'$(srcdir)/'`stdio/mingw_lock.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) 
stdio/$(DEPDIR)/lib64_libmsvcrt_a-mingw_lock.Tpo 
stdio/$(DEPDIR)/lib64_libmsvcrt_a-mingw_lock.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='stdio/mingw_lock.c' 
object='stdio/lib64_libmsvcrt_a-mingw_lock.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(lib64_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c 
-o stdio/lib64_libmsvcrt_a-mingw_lock.o `test -f 'stdio/mingw_lock.c' || echo 
'$(srcdir)/'`stdio/mingw_lock.c
+
+stdio/lib64_libmsvcrt_a-mingw_lock.obj: stdio/mingw_lock.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(lib64_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT 
stdio/lib64_libmsvcrt_a-mingw_lock.obj -MD -MP -MF 
stdio/$(DEPDIR)/lib64_libmsvcrt_a-mingw_lock.Tpo -c -o 
stdio/lib64_libmsvcrt_a-mingw_lock.obj `if test -f 'stdio/mingw_lock.c'; then 
$(CYGPATH_W) 'stdio/mingw_lock.c'; else $(CYGPATH_W) 
'$(srcdir)/stdio/mingw_lock.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) 
stdio/$(DEPDIR)/lib64_libmsvcrt_a-mingw_lock.Tpo 
stdio/$(DEPDIR)/lib64_libmsvcrt_a-mingw_lock.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='stdio/mingw_lock.c' 
object='stdio/lib64_libmsvcrt_a-mingw_lock.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) 
$(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) 
$(INCLUDES) $(lib64_libmsvcrt_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c 
-o stdio/lib64_libmsvcrt_a-mingw_lock.obj `if test -f 'stdio/mingw_lock.c'; 
then $(CYGPATH_W) 'stdio/mingw_lock.c'; else $(CYGPATH_W) 
'$(srcdir)/stdio/mingw_lock.c'; fi`
+
 libsrc/lib64_libportabledeviceguids_a-portabledeviceguids.o: 
libsrc/portabledeviceguids.c
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) 
$(lib64_libportabledeviceguids_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 
-MT libsrc/lib64_libportabledeviceguids_a-portabledeviceguids.o -MD -MP -MF 
libsrc/$(DEPDIR)/lib64_libportabledeviceguids_a-portabledeviceguids.Tpo -c -o 
libsrc/lib64_libportabledeviceguids_a-portabledeviceguids.o `test -f 
'libsrc/portabledeviceguids.c' || echo '$(srcdir)/'`libsrc/portabledeviceguids.c
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) 
libsrc/$(DEPDIR)/lib64_libportabledeviceguids_a-portabledeviceguids.Tpo 
libsrc/$(DEPDIR)/lib64_libportabledeviceguids_a-portabledeviceguids.Po
diff --git a/mingw-w64-crt/stdio/mingw_fprintf.c 
b/mingw-w64-crt/stdio/mingw_fprintf.c
index 011a634..438941f 100644
--- a/mingw-w64-crt/stdio/mingw_fprintf.c
+++ b/mingw-w64-crt/stdio/mingw_fprintf.c
@@ -50,7 +50,9 @@ int __cdecl __fprintf(FILE *stream, const APICHAR *fmt, ...)
 {
   register int retval;
   va_list argv; va_start( argv, fmt );
+  _lock_file( stream );
   retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv 
);
+  _unlock_file( stream );
   va_end( argv );
   return retval;
 }
diff --git a/mingw-w64-crt/stdio/mingw_lock.c b/mingw-w64-crt/stdio/mingw_lock.c
new file mode 100644
index 0000000..e62fe03
--- /dev/null
+++ b/mingw-w64-crt/stdio/mingw_lock.c
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <synchapi.h>
+#include "internal.h"
+
+/***
+ * Copy of MS functions _lock_file, _unlock_file which are missing from
+ * msvcrt.dll and msvcr80.dll. They are needed to atomic/lock stdio
+ * functions (printf, fprintf, vprintf, vfprintf). We need exactly the same
+ * lock that MS uses in msvcrt.dll because we can mix mingw-w64 code with
+ * original MS functions (puts, fputs for example).
+***/ 
+
+
+_CRTIMP void __cdecl _lock(int locknum);
+_CRTIMP void __cdecl _unlock(int locknum);
+#define _STREAM_LOCKS   16
+#define _IOLOCKED       0x8000
+
+
+/***
+* _lock_file - Lock a FILE
+*
+*Purpose:
+*       Assert the lock for a stdio-level file
+*
+*Entry:
+*       pf = __piob[] entry (pointer to a FILE or _FILEX)
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __cdecl _lock_file( FILE *pf )
+{
+    /*
+     * The way the FILE (pointed to by pf) is locked depends on whether
+     * it is part of _iob[] or not
+     */
+    if ( (pf >= (&__iob_func()[0])) && (pf <= (&__iob_func()[_IOB_ENTRIES-1])) 
)
+    {
+        /*
+         * FILE lies in _iob[] so the lock lies in _locktable[].
+         */
+        _lock( _STREAM_LOCKS + (int)(pf - (&__iob_func()[0])) );
+        /* We set _IOLOCKED to indicate we locked the stream */
+        pf->_flag |= _IOLOCKED;
+    }
+    else
+        /*
+         * Not part of _iob[]. Therefore, *pf is a _FILEX and the
+         * lock field of the struct is an initialized critical
+         * section.
+         */
+        EnterCriticalSection( &(((_FILEX *)pf)->lock) );
+}
+
+
+/***
+* _unlock_file - Unlock a FILE
+*
+*Purpose:
+*       Release the lock for a stdio-level file
+*
+*Entry:
+*       pf = __piob[] entry (pointer to a FILE or _FILEX)
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void __cdecl _unlock_file( FILE *pf )
+{
+    /*
+     * The way the FILE (pointed to by pf) is unlocked depends on whether
+     * it is part of _iob[] or not
+     */
+    if ( (pf >= (&__iob_func()[0])) && (pf <= (&__iob_func()[_IOB_ENTRIES-1])) 
)
+    {
+        /*
+         * FILE lies in _iob[] so the lock lies in _locktable[].
+         * We reset _IOLOCKED to indicate we unlock the stream.
+         */
+        pf->_flag &= ~_IOLOCKED;
+        _unlock( _STREAM_LOCKS + (int)(pf - (&__iob_func()[0])) );
+    }
+    else
+        /*
+         * Not part of _iob[]. Therefore, *pf is a _FILEX and the
+         * lock field of the struct is an initialized critical
+         * section.
+         */
+        LeaveCriticalSection( &(((_FILEX *)pf)->lock) );
+}
diff --git a/mingw-w64-crt/stdio/mingw_printf.c 
b/mingw-w64-crt/stdio/mingw_printf.c
index 5d23b02..fbd2e7d 100644
--- a/mingw-w64-crt/stdio/mingw_printf.c
+++ b/mingw-w64-crt/stdio/mingw_printf.c
@@ -50,7 +50,9 @@ int __cdecl __printf(const APICHAR *fmt, ...)
 {
   register int retval;
   va_list argv; va_start( argv, fmt );
+  _lock_file( stdout );
   retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv 
);
+  _unlock_file( stdout );
   va_end( argv );
   return retval;
 }
diff --git a/mingw-w64-crt/stdio/mingw_vfprintf.c 
b/mingw-w64-crt/stdio/mingw_vfprintf.c
index 68a0008..01ad01b 100644
--- a/mingw-w64-crt/stdio/mingw_vfprintf.c
+++ b/mingw-w64-crt/stdio/mingw_vfprintf.c
@@ -48,5 +48,11 @@ int __cdecl __vfprintf (FILE *, const APICHAR *, va_list) 
__MINGW_NOTHROW;
 
 int __cdecl __vfprintf(FILE *stream, const APICHAR *fmt, va_list argv)
 {
-  return __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv );
+  register int retval;
+
+  _lock_file( stream );
+  retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv 
);
+  _unlock_file( stream );
+
+  return retval;
 }
diff --git a/mingw-w64-crt/stdio/mingw_vprintf.c 
b/mingw-w64-crt/stdio/mingw_vprintf.c
index c60431a..4098d49 100644
--- a/mingw-w64-crt/stdio/mingw_vprintf.c
+++ b/mingw-w64-crt/stdio/mingw_vprintf.c
@@ -48,5 +48,11 @@ int __cdecl __vprintf (const APICHAR *, va_list) 
__MINGW_NOTHROW;
 
 int __cdecl __vprintf(const APICHAR *fmt, va_list argv)
 {
-  return __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv );
+  register int retval;
+
+  _lock_file( stdout );
+  retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv 
);
+  _unlock_file( stdout );
+
+  return retval;
 }
#define __USE_MINGW_ANSI_STDIO 1

#include <stdio.h>
#include <process.h>
#include <windows.h>
#include <sys/timeb.h>

#define ITERATIONS 100

int nIterations = ITERATIONS;

void Thread_printf( void* str )
{
    int i;
    char buf[ 88 ];

    Sleep( 100 );

    for( i = 0; i < nIterations; ++i )
    {
        printf( "%d: %s %s %s %s %s %s %s\n", i, (char*)str, (char*)str, 
(char*)str, (char*)str, (char*)str, (char*)str, (char*)str );
        sprintf( buf, "%d= %s %s %s %s %s %s %s", i, (char*)str, (char*)str, 
(char*)str, (char*)str, (char*)str, (char*)str, (char*)str );
        puts( buf );
    }
}

#define THREADS 8
#define MAX_THREADS 512

int nThreads = THREADS;

/*
  If we run this app without args, it will create 8 threads and each thread 
make 100 iterations of printf function.
  We can run this test.exe [nIterations] [nThreads] for more iterations/threads.
  For speed test we can run
  test.exe 100000 64 >outFile.txt
  Result should be (on screen or in file) with each line clean (not mixed).
  On my i5 3450S I can create only up to 64 threads.
*/

int main( int argc, char* argv[] )
{
    HANDLE h[ MAX_THREADS ];
    char buf[ MAX_THREADS ][12];
    int i;
    struct __timeb64 tb;
    __int64 startTime, endTime;

    _ftime64( &tb );
    startTime = (__int64)tb.time * 1000 + tb.millitm; 

    if( argc > 1 )
        nIterations = atoi( argv[ 1 ] );
    if( nIterations < 1 )
        nIterations = ITERATIONS;

    if( argc > 2 )
        nThreads = atoi( argv[ 2 ] );
    if( nThreads > MAX_THREADS )
        nThreads = MAX_THREADS;
    else if( nThreads < 1 )
        nThreads = 1;

    for( i = 0; i < nThreads; i++ )
        sprintf( buf[ i ], "Thread_%d", i );

    for( i = 0; i < nThreads; i++ )
        h[ i ] = (HANDLE)_beginthread( &Thread_printf, 0, buf[ i ] );

    WaitForMultipleObjects( nThreads, h, TRUE, INFINITE );

    _ftime64( &tb );
    endTime = (__int64)tb.time * 1000 + tb.millitm;
    
    endTime -= startTime;
    fprintf( stderr, "nIterations = %d, nThreads = %d, Time: %0.2f s\n", 
nIterations, nThreads, (double)endTime / 1000.0 ); 

    return 0;
}
------------------------------------------------------------------------------
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to