[x264-devel] [PATCH] Fix race condition in win32 threading init
Andrey Turkin
andrey.turkin at gmail.com
Thu Mar 2 11:03:13 CET 2017
x264_threading_init must not return until threading is fully initialized. The code is mostly borrowed from FFmpeg codebase and adapted to handle init failure case.
---
common/osdep.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 51 insertions(+), 13 deletions(-)
diff --git a/common/osdep.c b/common/osdep.c
index 9bc926a1..f07d446a 100644
--- a/common/osdep.c
+++ b/common/osdep.c
@@ -40,6 +40,12 @@
#endif
#include <time.h>
+#if _WIN32_WINNT < 0x0600 && defined(__MINGW32__)
+#undef MemoryBarrier
+#define MemoryBarrier __sync_synchronize
+#endif
+
+
#if PTW32_STATIC_LIB
/* this is a global in pthread-win32 to indicate if it has been initialized or not */
extern int ptw32_processInitialized;
@@ -74,23 +80,55 @@ static void x264_threading_destroy( void )
int x264_threading_init( void )
{
- /* if already init, then do nothing */
- if( InterlockedCompareExchange( &x264_threading_is_init, 1, 0 ) )
- return 0;
+ switch( InterlockedCompareExchange( &x264_threading_is_init, 1, 0 ) )
+ {
+ case 0:
+ /* this thread has to initialize threading */
#if PTW32_STATIC_LIB
- /* if static pthread-win32 is already initialized, then do nothing */
- if( ptw32_processInitialized )
- return 0;
- if( !pthread_win32_process_attach_np() )
- return -1;
+ /* if static pthread-win32 is already initialized, then do nothing */
+ if( !ptw32_processInitialized )
+ {
+ if( !pthread_win32_process_attach_np() )
+ {
+ InterlockedExchange( &x264_threading_is_init, 3 );
+ return -1;
+ }
+ /* register cleanup to run at process termination */
+ atexit( x264_threading_destroy );
+ }
#else
- if( x264_win32_threading_init() )
- return -1;
+ if( x264_win32_threading_init() )
+ {
+ InterlockedExchange( &x264_threading_is_init, 3 );
+ return -1;
+ }
+ /* register cleanup to run at process termination */
+ atexit( x264_threading_destroy );
#endif
- /* register cleanup to run at process termination */
- atexit( x264_threading_destroy );
+ InterlockedExchange( &x264_threading_is_init, 2 );
+ return 0;
- return 0;
+ case 1:
+ /* other thread is running init */
+ for( ;; )
+ {
+ MemoryBarrier();
+ if( x264_threading_is_init == 2 )
+ return 0;
+ if( x264_threading_is_init == 3 )
+ return -1;
+ Sleep( 0 );
+ }
+
+ case 2:
+ /* already initialized */
+ return 0;
+
+ case 3:
+ /* initialize failed */
+ default:
+ return -1;
+ }
}
#endif
--
2.11.0
More information about the x264-devel
mailing list