We have 4 functions from printf family that output to FILE stream:
printf, vprintf, fprintf, vfprintf
We have also puts/fputs functions that output to FILE stream and are
always directly from msvcrt.dll.
puts/fputs functions are atomic with Microsoft lock. If we want
mingw-w64 printf functions (__USE_MINGW_ANSI_STDIO) to be atomic against
puts/fputs functions, we must copy lock from Microsoft sources.
Microsoft use _lock_file/_unlock_file lock to stdio functions, so patch
for mingw-w64
printf, vprintf, fprintf, vfprintf
functions are obvious -- _lock_file -> __pformat -> _unlock_file
There is one problem: _lock_file/_unlock_file are exported from
msvcr*.dll starting from version msvcr90.dll. There are no such
functions in msvcrt.dll & msvcr80.dll.
My proposition: we can add obvious patch to mingw-w64 printf functions
family and copy _lock_file/_unlock_file from MS sources and add only to
libmsvcrt.a & libmsvcr80.a.
I attached diff file that is not complete -- there is to do add
mingw_lock.c source to libmsvcrt.a & libmsvcr80.a.
Simplified version of this patch is used without problems in x265
community -- in message
http://forum.doom9.org/showthread.php?p=1731962#post1731962
diff -r -c -N a/stdio/mingw_fprintf.c b/stdio/mingw_fprintf.c
*** a/stdio/mingw_fprintf.c Sat Aug 1 18:19:05 2015
--- b/stdio/mingw_fprintf.c Sat Aug 1 20:23:28 2015
***************
*** 50,56 ****
--- 50,58 ----
{
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 -r -c -N a/stdio/mingw_lock.c b/stdio/mingw_lock.c
*** a/stdio/mingw_lock.c Thu Jan 1 00:00:00 1970
--- b/stdio/mingw_lock.c Sat Aug 1 21:38:55 2015
***************
*** 0 ****
--- 1,89 ----
+ #include <stdio.h>
+ #include <synchapi.h>
+ #include "internal.h"
+
+
+ _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 -r -c -N a/stdio/mingw_printf.c b/stdio/mingw_printf.c
*** a/stdio/mingw_printf.c Sat Aug 1 18:19:05 2015
--- b/stdio/mingw_printf.c Sat Aug 1 20:21:05 2015
***************
*** 50,56 ****
--- 50,58 ----
{
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 -r -c -N a/stdio/mingw_vfprintf.c b/stdio/mingw_vfprintf.c
*** a/stdio/mingw_vfprintf.c Sat Aug 1 18:19:05 2015
--- b/stdio/mingw_vfprintf.c Sat Aug 1 20:14:37 2015
***************
*** 48,52 ****
int __cdecl __vfprintf(FILE *stream, const APICHAR *fmt, va_list argv)
{
! return __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv );
}
--- 48,58 ----
int __cdecl __vfprintf(FILE *stream, const APICHAR *fmt, va_list argv)
{
! register int retval;
!
! _lock_file( stream );
! retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv
);
! _unlock_file( stream );
!
! return retval;
}
diff -r -c -N a/stdio/mingw_vprintf.c b/stdio/mingw_vprintf.c
*** a/stdio/mingw_vprintf.c Sat Aug 1 18:19:05 2015
--- b/stdio/mingw_vprintf.c Sat Aug 1 20:12:35 2015
***************
*** 48,52 ****
int __cdecl __vprintf(const APICHAR *fmt, va_list argv)
{
! return __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv );
}
--- 48,58 ----
int __cdecl __vprintf(const APICHAR *fmt, va_list argv)
{
! register int retval;
!
! _lock_file( stdout );
! retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv
);
! _unlock_file( stdout );
!
! return retval;
}
------------------------------------------------------------------------------
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public