Commit 8b03d7fe authored by Ronald S. Bultje's avatar Ronald S. Bultje

w32thread: port fixes to pthread_cond_broadcast() from x264.

parent d8538f06
...@@ -115,9 +115,12 @@ static inline int pthread_mutex_unlock(pthread_mutex_t *m) ...@@ -115,9 +115,12 @@ static inline int pthread_mutex_unlock(pthread_mutex_t *m)
/* for pre-Windows 6.0 platforms we need to define and use our own condition /* for pre-Windows 6.0 platforms we need to define and use our own condition
* variable and api */ * variable and api */
typedef struct { typedef struct {
pthread_mutex_t mtx_broadcast;
pthread_mutex_t mtx_waiter_count; pthread_mutex_t mtx_waiter_count;
volatile int waiter_count; volatile int waiter_count;
HANDLE semaphore; HANDLE semaphore;
HANDLE waiters_done;
int is_broadcast;
} win32_cond_t; } win32_cond_t;
static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr)
...@@ -136,8 +139,12 @@ static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) ...@@ -136,8 +139,12 @@ static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr)
win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
if (!win32_cond->semaphore) if (!win32_cond->semaphore)
return; return;
win32_cond->waiters_done = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!win32_cond->waiters_done)
return;
pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL); pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL);
pthread_mutex_init(&win32_cond->mtx_broadcast, NULL);
} }
static void pthread_cond_destroy(pthread_cond_t *cond) static void pthread_cond_destroy(pthread_cond_t *cond)
...@@ -149,7 +156,9 @@ static void pthread_cond_destroy(pthread_cond_t *cond) ...@@ -149,7 +156,9 @@ static void pthread_cond_destroy(pthread_cond_t *cond)
/* non native condition variables */ /* non native condition variables */
CloseHandle(win32_cond->semaphore); CloseHandle(win32_cond->semaphore);
CloseHandle(win32_cond->waiters_done);
pthread_mutex_destroy(&win32_cond->mtx_waiter_count); pthread_mutex_destroy(&win32_cond->mtx_waiter_count);
pthread_mutex_destroy(&win32_cond->mtx_broadcast);
av_freep(&win32_cond); av_freep(&win32_cond);
cond->ptr = NULL; cond->ptr = NULL;
} }
...@@ -157,41 +166,70 @@ static void pthread_cond_destroy(pthread_cond_t *cond) ...@@ -157,41 +166,70 @@ static void pthread_cond_destroy(pthread_cond_t *cond)
static void pthread_cond_broadcast(pthread_cond_t *cond) static void pthread_cond_broadcast(pthread_cond_t *cond)
{ {
win32_cond_t *win32_cond = cond->ptr; win32_cond_t *win32_cond = cond->ptr;
int have_waiter;
if (cond_broadcast) { if (cond_broadcast) {
cond_broadcast(cond); cond_broadcast(cond);
return; return;
} }
/* non native condition variables */ /* non native condition variables */
pthread_mutex_lock(&win32_cond->mtx_broadcast);
pthread_mutex_lock(&win32_cond->mtx_waiter_count); pthread_mutex_lock(&win32_cond->mtx_waiter_count);
have_waiter = 0;
if (win32_cond->waiter_count) { if (win32_cond->waiter_count) {
ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL); win32_cond->is_broadcast = 1;
win32_cond->waiter_count = 0; have_waiter = 1;
} }
pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
if (have_waiter) {
ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL);
pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
WaitForSingleObject(win32_cond->waiters_done, INFINITE);
win32_cond->is_broadcast = 0;
} else
pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
pthread_mutex_unlock(&win32_cond->mtx_broadcast);
} }
static void pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) static void pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{ {
win32_cond_t *win32_cond = cond->ptr; win32_cond_t *win32_cond = cond->ptr;
int last_waiter;
if (cond_wait) { if (cond_wait) {
cond_wait(cond, mutex, INFINITE); cond_wait(cond, mutex, INFINITE);
return; return;
} }
/* non native condition variables */ /* 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); pthread_mutex_lock(&win32_cond->mtx_waiter_count);
win32_cond->waiter_count++; win32_cond->waiter_count++;
pthread_mutex_unlock(&win32_cond->mtx_waiter_count); pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
// unlock the external mutex
pthread_mutex_unlock(mutex); pthread_mutex_unlock(mutex);
WaitForSingleObject(win32_cond->semaphore, INFINITE); WaitForSingleObject(win32_cond->semaphore, INFINITE);
pthread_mutex_lock(mutex);
pthread_mutex_lock(&win32_cond->mtx_waiter_count);
win32_cond->waiter_count--;
last_waiter = !win32_cond->waiter_count && win32_cond->is_broadcast;
pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
if (last_waiter)
SetEvent(win32_cond->waiters_done);
// lock the external mutex
return pthread_mutex_lock(mutex);
} }
static void pthread_cond_signal(pthread_cond_t *cond) static void pthread_cond_signal(pthread_cond_t *cond)
{ {
win32_cond_t *win32_cond = cond->ptr; win32_cond_t *win32_cond = cond->ptr;
int have_waiter;
if (cond_signal) { if (cond_signal) {
cond_signal(cond); cond_signal(cond);
return; return;
...@@ -199,11 +237,11 @@ static void pthread_cond_signal(pthread_cond_t *cond) ...@@ -199,11 +237,11 @@ static void pthread_cond_signal(pthread_cond_t *cond)
/* non-native condition variables */ /* non-native condition variables */
pthread_mutex_lock(&win32_cond->mtx_waiter_count); pthread_mutex_lock(&win32_cond->mtx_waiter_count);
if (win32_cond->waiter_count) { have_waiter = win32_cond->waiter_count;
ReleaseSemaphore(win32_cond->semaphore, 1, NULL);
win32_cond->waiter_count--;
}
pthread_mutex_unlock(&win32_cond->mtx_waiter_count); pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
if (have_waiter)
ReleaseSemaphore(win32_cond->semaphore, 1, NULL);
} }
static void w32thread_init(void) static void w32thread_init(void)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment