summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Radionov <RSATom@gmail.com>2011-12-21 09:08:56 +0700
committerRonald S. Bultje <rsbultje@gmail.com>2011-12-20 20:21:10 -0800
commit2003a29284660255016b1ec4bd5dfb8d53e6a852 (patch)
treedfdc3b0258edb32f8d83d048b463f1f549904ea7
parent021914e27fe943649e26ea82b2bbd67c89c7c324 (diff)
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@gmail.com>
-rw-r--r--libavcodec/w32pthreads.h16
1 files changed, 11 insertions, 5 deletions
diff --git a/libavcodec/w32pthreads.h b/libavcodec/w32pthreads.h
index 2d1470c5ee..3cdbc2c343 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)