[x264-devel] [PATCH] Fix race condition in win32 threading init
Sérgio Basto
sergio at serjux.com
Thu Apr 20 16:30:02 CEST 2017
JFTR
Delivery-Date: Thu, 20 Apr 2017 09:00:10 +0100
On Qui, 2017-02-23 at 12:54 +0300, Andrey Turkin wrote:
> 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
>
--
Sérgio M. B.
More information about the x264-devel
mailing list