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

Reply via email to