diff --git a/libs/apr/include/arch/win32/apr_arch_thread_cond.h b/libs/apr/include/arch/win32/apr_arch_thread_cond.h index 840949c26a..c7f69f8064 100644 --- a/libs/apr/include/arch/win32/apr_arch_thread_cond.h +++ b/libs/apr/include/arch/win32/apr_arch_thread_cond.h @@ -21,10 +21,11 @@ struct apr_thread_cond_t { apr_pool_t *pool; - HANDLE event; - int signal_all; - int num_waiting; - int signalled; + HANDLE semaphore; + CRITICAL_SECTION csection; + unsigned long num_waiting; + unsigned long num_wake; + unsigned long generation; }; #endif /* THREAD_COND_H */ diff --git a/libs/apr/locks/win32/thread_cond.c b/libs/apr/locks/win32/thread_cond.c index 30d2c4a2bc..60286e542d 100644 --- a/libs/apr/locks/win32/thread_cond.c +++ b/libs/apr/locks/win32/thread_cond.c @@ -18,67 +18,98 @@ #include "apr_private.h" #include "apr_general.h" #include "apr_strings.h" -#include "win32/apr_arch_thread_mutex.h" -#include "win32/apr_arch_thread_cond.h" +#include "apr_arch_thread_mutex.h" +#include "apr_arch_thread_cond.h" #include "apr_portable.h" +#include + static apr_status_t thread_cond_cleanup(void *data) { apr_thread_cond_t *cond = data; - CloseHandle(cond->event); + CloseHandle(cond->semaphore); + DeleteCriticalSection(&cond->csection); return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond, apr_pool_t *pool) { - *cond = apr_palloc(pool, sizeof(**cond)); - (*cond)->pool = pool; - (*cond)->event = CreateEvent(NULL, TRUE, FALSE, NULL); - (*cond)->signal_all = 0; - (*cond)->num_waiting = 0; + apr_thread_cond_t *cv; - apr_pool_cleanup_register(pool, *cond, thread_cond_cleanup, - apr_pool_cleanup_null); + cv = apr_pcalloc(pool, sizeof(**cond)); + if (cv == NULL) { + return APR_ENOMEM; + } + + cv->semaphore = CreateSemaphore(NULL, 0, LONG_MAX, NULL); + if (cv->semaphore == NULL) { + return apr_get_os_error(); + } + + *cond = cv; + cv->pool = pool; + InitializeCriticalSection(&cv->csection); + apr_pool_cleanup_register(cv->pool, cv, thread_cond_cleanup, + apr_pool_cleanup_null); return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond) +{ + return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup); +} + static APR_INLINE apr_status_t _thread_cond_timedwait(apr_thread_cond_t *cond, apr_thread_mutex_t *mutex, DWORD timeout_ms ) { DWORD res; + apr_status_t rv; + unsigned int wake = 0; + unsigned long generation; - while (1) { - cond->num_waiting++; + EnterCriticalSection(&cond->csection); + cond->num_waiting++; + generation = cond->generation; + LeaveCriticalSection(&cond->csection); - apr_thread_mutex_unlock(mutex); - res = WaitForSingleObject(cond->event, timeout_ms); - apr_thread_mutex_lock(mutex); - cond->num_waiting--; - if (res != WAIT_OBJECT_0) { - apr_status_t rv = apr_get_os_error(); - if (res == WAIT_TIMEOUT) { - return APR_TIMEUP; + apr_thread_mutex_unlock(mutex); + + do { + res = WaitForSingleObject(cond->semaphore, timeout_ms); + + EnterCriticalSection(&cond->csection); + + if (cond->num_wake) { + if (cond->generation != generation) { + cond->num_wake--; + cond->num_waiting--; + rv = APR_SUCCESS; + break; + } else { + wake = 1; } - return apr_get_os_error(); } - if (cond->signal_all) { - if (cond->num_waiting == 0) { - cond->signal_all = 0; - cond->signalled = 0; - ResetEvent(cond->event); - } + else if (res != WAIT_OBJECT_0) { + cond->num_waiting--; + rv = APR_TIMEUP; break; } - else if (cond->signalled) { - cond->signalled = 0; - ResetEvent(cond->event); - break; + + LeaveCriticalSection(&cond->csection); + + if (wake) { + wake = 0; + ReleaseSemaphore(cond->semaphore, 1, NULL); } - } - return APR_SUCCESS; + } while (1); + + LeaveCriticalSection(&cond->csection); + apr_thread_mutex_lock(mutex); + + return rv; } APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond, @@ -98,35 +129,40 @@ APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond, APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond) { - apr_status_t rv = APR_SUCCESS; - DWORD res; + unsigned int wake = 0; - cond->signalled = 1; - res = SetEvent(cond->event); - if (res == 0) { - rv = apr_get_os_error(); + EnterCriticalSection(&cond->csection); + if (cond->num_waiting > cond->num_wake) { + wake = 1; + cond->num_wake++; + cond->generation++; } - return rv; + LeaveCriticalSection(&cond->csection); + + if (wake) { + ReleaseSemaphore(cond->semaphore, 1, NULL); + } + + return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond) { - apr_status_t rv = APR_SUCCESS; - DWORD res; + unsigned long num_wake = 0; - cond->signalled = 1; - cond->signal_all = 1; - res = SetEvent(cond->event); - if (res == 0) { - rv = apr_get_os_error(); + EnterCriticalSection(&cond->csection); + if (cond->num_waiting > cond->num_wake) { + num_wake = cond->num_waiting - cond->num_wake; + cond->num_wake = cond->num_waiting; + cond->generation++; } - return rv; -} + LeaveCriticalSection(&cond->csection); -APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond) -{ - return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup); + if (num_wake) { + ReleaseSemaphore(cond->semaphore, num_wake, NULL); + } + + return APR_SUCCESS; } APR_POOL_IMPLEMENT_ACCESSOR(thread_cond) - diff --git a/src/switch_time.c b/src/switch_time.c index 3f8eec5c0f..9e4e0df0b8 100644 --- a/src/switch_time.c +++ b/src/switch_time.c @@ -408,9 +408,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(softtimer_runtime) switch_mutex_init(&TIMER_MATRIX[1].mutex, SWITCH_MUTEX_NESTED, module_pool); switch_thread_cond_create(&TIMER_MATRIX[1].cond, module_pool); -#ifndef WIN32 globals.use_cond_yield = globals.RUNNING == 1; -#endif while (globals.RUNNING == 1) { runtime.reference += STEP_MIC;