]> granicus.if.org Git - libx264/commitdiff
Fix data race
authorAnton Mitrofanov <BugMaster@narod.ru>
Sun, 24 May 2020 13:35:00 +0000 (16:35 +0300)
committerAnton Mitrofanov <BugMaster@narod.ru>
Wed, 10 Jun 2020 15:07:03 +0000 (18:07 +0300)
Closes videolan/x264#16.
Bug report by Zu-Ming Jiang.

common/frame.c
common/frame.h
encoder/analyse.c

index 7a3af7217097bae58596d68f00d64b50b9c0ebe7..9e6fbc0d411195be0b09272f21626b449a000601 100644 (file)
@@ -685,12 +685,14 @@ void x264_frame_cond_broadcast( x264_frame_t *frame, int i_lines_completed )
     x264_pthread_mutex_unlock( &frame->mutex );
 }
 
-void x264_frame_cond_wait( x264_frame_t *frame, int i_lines_completed )
+int x264_frame_cond_wait( x264_frame_t *frame, int i_lines_completed )
 {
+    int completed;
     x264_pthread_mutex_lock( &frame->mutex );
-    while( frame->i_lines_completed < i_lines_completed )
+    while( (completed = frame->i_lines_completed) < i_lines_completed && i_lines_completed >= 0 )
         x264_pthread_cond_wait( &frame->cv, &frame->mutex );
     x264_pthread_mutex_unlock( &frame->mutex );
+    return completed;
 }
 
 void x264_threadslice_cond_broadcast( x264_t *h, int pass )
index 125ec6417410b378f36dd7cd416bed95133e8a2c..35b7436927844f76636a7e59ee1e26a5658d11b2 100644 (file)
@@ -251,7 +251,7 @@ void          x264_deblock_init( uint32_t cpu, x264_deblock_function_t *pf, int
 #define x264_frame_cond_broadcast x264_template(frame_cond_broadcast)
 void          x264_frame_cond_broadcast( x264_frame_t *frame, int i_lines_completed );
 #define x264_frame_cond_wait x264_template(frame_cond_wait)
-void          x264_frame_cond_wait( x264_frame_t *frame, int i_lines_completed );
+int           x264_frame_cond_wait( x264_frame_t *frame, int i_lines_completed );
 #define x264_frame_new_slice x264_template(frame_new_slice)
 int           x264_frame_new_slice( x264_t *h, x264_frame_t *frame );
 
index 4d7d6428e705b342f488b6249f08f8afad931a79..2a86fbf44682b13b374c9a794d95616a282e77bd 100644 (file)
@@ -359,8 +359,8 @@ static void mb_analyse_init( x264_t *h, x264_mb_analysis_t *a, int qp )
                 for( int i = (h->sh.i_type == SLICE_TYPE_B); i >= 0; i-- )
                     for( int j = 0; j < h->i_ref[i]; j++ )
                     {
-                        x264_frame_cond_wait( h->fref[i][j]->orig, thresh );
-                        thread_mvy_range = X264_MIN( thread_mvy_range, h->fref[i][j]->orig->i_lines_completed - pix_y );
+                        int completed = x264_frame_cond_wait( h->fref[i][j]->orig, thresh );
+                        thread_mvy_range = X264_MIN( thread_mvy_range, completed - pix_y );
                     }
 
                 if( h->param.b_deterministic )
@@ -3869,7 +3869,7 @@ static void analyse_update_cache( x264_t *h, x264_mb_analysis_t *a  )
             int ref = h->mb.cache.ref[l][x264_scan8[0]];
             if( ref < 0 )
                 continue;
-            completed = h->fref[l][ ref >> MB_INTERLACED ]->orig->i_lines_completed;
+            completed = x264_frame_cond_wait( h->fref[l][ ref >> MB_INTERLACED ]->orig, -1 );
             if( (h->mb.cache.mv[l][x264_scan8[15]][1] >> (2 - MB_INTERLACED)) + h->mb.i_mb_y*16 > completed )
             {
                 x264_log( h, X264_LOG_WARNING, "internal error (MV out of thread range)\n");