[FFmpeg-cvslog] w32threads: wait for the waked thread in pthread_cond_signal.

Sergey Radionov git at videolan.org
Thu Dec 22 02:05:03 CET 2011


ffmpeg | branch: master | Sergey Radionov <RSATom at gmail.com> | Wed Dec 21 09:08:56 2011 +0700| [2003a29284660255016b1ec4bd5dfb8d53e6a852] | committer: Ronald S. Bultje

w32threads: wait for the waked thread in pthread_cond_signal.

This fixes a deadlock VLC triggered with multithreaded decoding. The
wait forces one of the current waiters to wake and not the thread
which calls pthread_cond_signal() itself.

Signed-off-by: Ronald S. Bultje <rsbultje at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=2003a29284660255016b1ec4bd5dfb8d53e6a852
---

 libavcodec/w32pthreads.h |   16 +++++++++++-----
 1 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/libavcodec/w32pthreads.h b/libavcodec/w32pthreads.h
index 2d1470c..3cdbc2c 100644
--- a/libavcodec/w32pthreads.h
+++ b/libavcodec/w32pthreads.h
@@ -139,7 +139,7 @@ static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr)
     win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
     if (!win32_cond->semaphore)
         return;
-    win32_cond->waiters_done = CreateEvent(NULL, FALSE, FALSE, NULL);
+    win32_cond->waiters_done = CreateEvent(NULL, TRUE, FALSE, NULL);
     if (!win32_cond->waiters_done)
         return;
 
@@ -204,11 +204,10 @@ static void pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
 
     /* non native condition variables */
     pthread_mutex_lock(&win32_cond->mtx_broadcast);
-    pthread_mutex_unlock(&win32_cond->mtx_broadcast);
-
     pthread_mutex_lock(&win32_cond->mtx_waiter_count);
     win32_cond->waiter_count++;
     pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+    pthread_mutex_unlock(&win32_cond->mtx_broadcast);
 
     // unlock the external mutex
     pthread_mutex_unlock(mutex);
@@ -216,7 +215,7 @@ static void pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
 
     pthread_mutex_lock(&win32_cond->mtx_waiter_count);
     win32_cond->waiter_count--;
-    last_waiter = !win32_cond->waiter_count && win32_cond->is_broadcast;
+    last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast;
     pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
 
     if (last_waiter)
@@ -235,13 +234,20 @@ static void pthread_cond_signal(pthread_cond_t *cond)
         return;
     }
 
+    pthread_mutex_lock(&win32_cond->mtx_broadcast);
+
     /* non-native condition variables */
     pthread_mutex_lock(&win32_cond->mtx_waiter_count);
     have_waiter = win32_cond->waiter_count;
     pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
 
-    if (have_waiter)
+    if (have_waiter) {
         ReleaseSemaphore(win32_cond->semaphore, 1, NULL);
+        WaitForSingleObject(win32_cond->waiters_done, INFINITE);
+        ResetEvent(win32_cond->waiters_done);
+    }
+
+    pthread_mutex_unlock(&win32_cond->mtx_broadcast);
 }
 
 static void w32thread_init(void)



More information about the ffmpeg-cvslog mailing list