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