This source file includes following definitions.
- uv__once_inner
- uv_once
- uv_thread_join
- uv_mutex_init
- uv_mutex_destroy
- uv_mutex_lock
- uv_mutex_trylock
- uv_mutex_unlock
- uv_rwlock_init
- uv_rwlock_destroy
- uv_rwlock_rdlock
- uv_rwlock_tryrdlock
- uv_rwlock_rdunlock
- uv_rwlock_wrlock
- uv_rwlock_trywrlock
- uv_rwlock_wrunlock
- uv_sem_init
- uv_sem_destroy
- uv_sem_post
- uv_sem_wait
- uv_sem_trywait
- uv__rwlock_srwlock_init
- uv__rwlock_srwlock_destroy
- uv__rwlock_srwlock_rdlock
- uv__rwlock_srwlock_tryrdlock
- uv__rwlock_srwlock_rdunlock
- uv__rwlock_srwlock_wrlock
- uv__rwlock_srwlock_trywrlock
- uv__rwlock_srwlock_wrunlock
- uv__rwlock_fallback_init
- uv__rwlock_fallback_destroy
- uv__rwlock_fallback_rdlock
- uv__rwlock_fallback_tryrdlock
- uv__rwlock_fallback_rdunlock
- uv__rwlock_fallback_wrlock
- uv__rwlock_fallback_trywrlock
- uv__rwlock_fallback_wrunlock
- uv_cond_fallback_init
- uv_cond_condvar_init
- uv_cond_init
- uv_cond_fallback_destroy
- uv_cond_condvar_destroy
- uv_cond_destroy
- uv_cond_fallback_signal
- uv_cond_condvar_signal
- uv_cond_signal
- uv_cond_fallback_broadcast
- uv_cond_condvar_broadcast
- uv_cond_broadcast
- uv_cond_wait_helper
- uv_cond_fallback_wait
- uv_cond_condvar_wait
- uv_cond_wait
- uv_cond_fallback_timedwait
- uv_cond_condvar_timedwait
- uv_cond_timedwait
- uv_barrier_init
- uv_barrier_destroy
- uv_barrier_wait
#include <assert.h>
#include <limits.h>
#include "uv.h"
#include "internal.h"
#define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL)
#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL)
#ifdef _MSC_VER
# define inline __inline
# define NOINLINE __declspec (noinline)
#else
# define inline inline
# define NOINLINE __attribute__ ((noinline))
#endif
inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock);
inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock);
inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock);
inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock);
inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock);
inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock);
inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock);
inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock);
inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock);
inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock);
inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock);
inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock);
inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock);
inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock);
inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock);
inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock);
inline static int uv_cond_fallback_init(uv_cond_t* cond);
inline static void uv_cond_fallback_destroy(uv_cond_t* cond);
inline static void uv_cond_fallback_signal(uv_cond_t* cond);
inline static void uv_cond_fallback_broadcast(uv_cond_t* cond);
inline static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex);
inline static int uv_cond_fallback_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout);
inline static int uv_cond_condvar_init(uv_cond_t* cond);
inline static void uv_cond_condvar_destroy(uv_cond_t* cond);
inline static void uv_cond_condvar_signal(uv_cond_t* cond);
inline static void uv_cond_condvar_broadcast(uv_cond_t* cond);
inline static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex);
inline static int uv_cond_condvar_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout);
static NOINLINE void uv__once_inner(uv_once_t* guard,
void (*callback)(void)) {
DWORD result;
HANDLE existing_event, created_event;
created_event = CreateEvent(NULL, 1, 0, NULL);
if (created_event == 0) {
uv_fatal_error(GetLastError(), "CreateEvent");
}
existing_event = InterlockedCompareExchangePointer(&guard->event,
created_event,
NULL);
if (existing_event == NULL) {
callback();
result = SetEvent(created_event);
assert(result);
guard->ran = 1;
} else {
CloseHandle(created_event);
result = WaitForSingleObject(existing_event, INFINITE);
assert(result == WAIT_OBJECT_0);
}
}
void uv_once(uv_once_t* guard, void (*callback)(void)) {
if (guard->ran) {
return;
}
uv__once_inner(guard, callback);
}
int uv_thread_join(uv_thread_t *tid) {
if (WaitForSingleObject(*tid, INFINITE))
return uv_translate_sys_error(GetLastError());
else {
CloseHandle(*tid);
*tid = 0;
return 0;
}
}
int uv_mutex_init(uv_mutex_t* mutex) {
InitializeCriticalSection(mutex);
return 0;
}
void uv_mutex_destroy(uv_mutex_t* mutex) {
DeleteCriticalSection(mutex);
}
void uv_mutex_lock(uv_mutex_t* mutex) {
EnterCriticalSection(mutex);
}
int uv_mutex_trylock(uv_mutex_t* mutex) {
if (TryEnterCriticalSection(mutex))
return 0;
else
return UV_EAGAIN;
}
void uv_mutex_unlock(uv_mutex_t* mutex) {
LeaveCriticalSection(mutex);
}
int uv_rwlock_init(uv_rwlock_t* rwlock) {
uv__once_init();
if (HAVE_SRWLOCK_API())
return uv__rwlock_srwlock_init(rwlock);
else
return uv__rwlock_fallback_init(rwlock);
}
void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
if (HAVE_SRWLOCK_API())
uv__rwlock_srwlock_destroy(rwlock);
else
uv__rwlock_fallback_destroy(rwlock);
}
void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
if (HAVE_SRWLOCK_API())
uv__rwlock_srwlock_rdlock(rwlock);
else
uv__rwlock_fallback_rdlock(rwlock);
}
int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
if (HAVE_SRWLOCK_API())
return uv__rwlock_srwlock_tryrdlock(rwlock);
else
return uv__rwlock_fallback_tryrdlock(rwlock);
}
void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
if (HAVE_SRWLOCK_API())
uv__rwlock_srwlock_rdunlock(rwlock);
else
uv__rwlock_fallback_rdunlock(rwlock);
}
void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
if (HAVE_SRWLOCK_API())
uv__rwlock_srwlock_wrlock(rwlock);
else
uv__rwlock_fallback_wrlock(rwlock);
}
int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
if (HAVE_SRWLOCK_API())
return uv__rwlock_srwlock_trywrlock(rwlock);
else
return uv__rwlock_fallback_trywrlock(rwlock);
}
void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
if (HAVE_SRWLOCK_API())
uv__rwlock_srwlock_wrunlock(rwlock);
else
uv__rwlock_fallback_wrunlock(rwlock);
}
int uv_sem_init(uv_sem_t* sem, unsigned int value) {
*sem = CreateSemaphore(NULL, value, INT_MAX, NULL);
if (*sem == NULL)
return uv_translate_sys_error(GetLastError());
else
return 0;
}
void uv_sem_destroy(uv_sem_t* sem) {
if (!CloseHandle(*sem))
abort();
}
void uv_sem_post(uv_sem_t* sem) {
if (!ReleaseSemaphore(*sem, 1, NULL))
abort();
}
void uv_sem_wait(uv_sem_t* sem) {
if (WaitForSingleObject(*sem, INFINITE) != WAIT_OBJECT_0)
abort();
}
int uv_sem_trywait(uv_sem_t* sem) {
DWORD r = WaitForSingleObject(*sem, 0);
if (r == WAIT_OBJECT_0)
return 0;
if (r == WAIT_TIMEOUT)
return UV_EAGAIN;
abort();
return -1;
}
inline static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock) {
pInitializeSRWLock(&rwlock->srwlock_);
return 0;
}
inline static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock) {
(void) rwlock;
}
inline static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) {
pAcquireSRWLockShared(&rwlock->srwlock_);
}
inline static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) {
if (pTryAcquireSRWLockShared(&rwlock->srwlock_))
return 0;
else
return UV_EBUSY;
}
inline static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) {
pReleaseSRWLockShared(&rwlock->srwlock_);
}
inline static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) {
pAcquireSRWLockExclusive(&rwlock->srwlock_);
}
inline static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) {
if (pTryAcquireSRWLockExclusive(&rwlock->srwlock_))
return 0;
else
return UV_EBUSY;
}
inline static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) {
pReleaseSRWLockExclusive(&rwlock->srwlock_);
}
inline static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) {
int err;
err = uv_mutex_init(&rwlock->fallback_.read_mutex_);
if (err)
return err;
err = uv_mutex_init(&rwlock->fallback_.write_mutex_);
if (err) {
uv_mutex_destroy(&rwlock->fallback_.read_mutex_);
return err;
}
rwlock->fallback_.num_readers_ = 0;
return 0;
}
inline static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock) {
uv_mutex_destroy(&rwlock->fallback_.read_mutex_);
uv_mutex_destroy(&rwlock->fallback_.write_mutex_);
}
inline static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) {
uv_mutex_lock(&rwlock->fallback_.read_mutex_);
if (++rwlock->fallback_.num_readers_ == 1)
uv_mutex_lock(&rwlock->fallback_.write_mutex_);
uv_mutex_unlock(&rwlock->fallback_.read_mutex_);
}
inline static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) {
int err;
err = uv_mutex_trylock(&rwlock->fallback_.read_mutex_);
if (err)
goto out;
err = 0;
if (rwlock->fallback_.num_readers_ == 0)
err = uv_mutex_trylock(&rwlock->fallback_.write_mutex_);
if (err == 0)
rwlock->fallback_.num_readers_++;
uv_mutex_unlock(&rwlock->fallback_.read_mutex_);
out:
return err;
}
inline static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) {
uv_mutex_lock(&rwlock->fallback_.read_mutex_);
if (--rwlock->fallback_.num_readers_ == 0)
uv_mutex_unlock(&rwlock->fallback_.write_mutex_);
uv_mutex_unlock(&rwlock->fallback_.read_mutex_);
}
inline static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock) {
uv_mutex_lock(&rwlock->fallback_.write_mutex_);
}
inline static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) {
return uv_mutex_trylock(&rwlock->fallback_.write_mutex_);
}
inline static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) {
uv_mutex_unlock(&rwlock->fallback_.write_mutex_);
}
inline static int uv_cond_fallback_init(uv_cond_t* cond) {
int err;
cond->fallback.waiters_count = 0;
InitializeCriticalSection(&cond->fallback.waiters_count_lock);
cond->fallback.signal_event = CreateEvent(NULL,
FALSE,
FALSE,
NULL);
if (!cond->fallback.signal_event) {
err = GetLastError();
goto error2;
}
cond->fallback.broadcast_event = CreateEvent(NULL,
TRUE,
FALSE,
NULL);
if (!cond->fallback.broadcast_event) {
err = GetLastError();
goto error;
}
return 0;
error:
CloseHandle(cond->fallback.signal_event);
error2:
DeleteCriticalSection(&cond->fallback.waiters_count_lock);
return uv_translate_sys_error(err);
}
inline static int uv_cond_condvar_init(uv_cond_t* cond) {
pInitializeConditionVariable(&cond->cond_var);
return 0;
}
int uv_cond_init(uv_cond_t* cond) {
uv__once_init();
if (HAVE_CONDVAR_API())
return uv_cond_condvar_init(cond);
else
return uv_cond_fallback_init(cond);
}
inline static void uv_cond_fallback_destroy(uv_cond_t* cond) {
if (!CloseHandle(cond->fallback.broadcast_event))
abort();
if (!CloseHandle(cond->fallback.signal_event))
abort();
DeleteCriticalSection(&cond->fallback.waiters_count_lock);
}
inline static void uv_cond_condvar_destroy(uv_cond_t* cond) {
}
void uv_cond_destroy(uv_cond_t* cond) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_destroy(cond);
else
uv_cond_fallback_destroy(cond);
}
inline static void uv_cond_fallback_signal(uv_cond_t* cond) {
int have_waiters;
EnterCriticalSection(&cond->fallback.waiters_count_lock);
have_waiters = cond->fallback.waiters_count > 0;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
if (have_waiters)
SetEvent(cond->fallback.signal_event);
}
inline static void uv_cond_condvar_signal(uv_cond_t* cond) {
pWakeConditionVariable(&cond->cond_var);
}
void uv_cond_signal(uv_cond_t* cond) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_signal(cond);
else
uv_cond_fallback_signal(cond);
}
inline static void uv_cond_fallback_broadcast(uv_cond_t* cond) {
int have_waiters;
EnterCriticalSection(&cond->fallback.waiters_count_lock);
have_waiters = cond->fallback.waiters_count > 0;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
if (have_waiters)
SetEvent(cond->fallback.broadcast_event);
}
inline static void uv_cond_condvar_broadcast(uv_cond_t* cond) {
pWakeAllConditionVariable(&cond->cond_var);
}
void uv_cond_broadcast(uv_cond_t* cond) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_broadcast(cond);
else
uv_cond_fallback_broadcast(cond);
}
inline int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex,
DWORD dwMilliseconds) {
DWORD result;
int last_waiter;
HANDLE handles[2] = {
cond->fallback.signal_event,
cond->fallback.broadcast_event
};
EnterCriticalSection(&cond->fallback.waiters_count_lock);
cond->fallback.waiters_count++;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
uv_mutex_unlock(mutex);
result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds);
EnterCriticalSection(&cond->fallback.waiters_count_lock);
cond->fallback.waiters_count--;
last_waiter = result == WAIT_OBJECT_0 + 1
&& cond->fallback.waiters_count == 0;
LeaveCriticalSection(&cond->fallback.waiters_count_lock);
if (last_waiter) {
ResetEvent(cond->fallback.broadcast_event);
}
uv_mutex_lock(mutex);
if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1)
return 0;
if (result == WAIT_TIMEOUT)
return UV_ETIMEDOUT;
abort();
return -1;
}
inline static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
if (uv_cond_wait_helper(cond, mutex, INFINITE))
abort();
}
inline static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE))
abort();
}
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
if (HAVE_CONDVAR_API())
uv_cond_condvar_wait(cond, mutex);
else
uv_cond_fallback_wait(cond, mutex);
}
inline static int uv_cond_fallback_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout) {
return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6));
}
inline static int uv_cond_condvar_timedwait(uv_cond_t* cond,
uv_mutex_t* mutex, uint64_t timeout) {
if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6)))
return 0;
if (GetLastError() != ERROR_TIMEOUT)
abort();
return UV_ETIMEDOUT;
}
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex,
uint64_t timeout) {
if (HAVE_CONDVAR_API())
return uv_cond_condvar_timedwait(cond, mutex, timeout);
else
return uv_cond_fallback_timedwait(cond, mutex, timeout);
}
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
int err;
barrier->n = count;
barrier->count = 0;
err = uv_mutex_init(&barrier->mutex);
if (err)
return err;
err = uv_sem_init(&barrier->turnstile1, 0);
if (err)
goto error2;
err = uv_sem_init(&barrier->turnstile2, 1);
if (err)
goto error;
return 0;
error:
uv_sem_destroy(&barrier->turnstile1);
error2:
uv_mutex_destroy(&barrier->mutex);
return err;
}
void uv_barrier_destroy(uv_barrier_t* barrier) {
uv_sem_destroy(&barrier->turnstile2);
uv_sem_destroy(&barrier->turnstile1);
uv_mutex_destroy(&barrier->mutex);
}
void uv_barrier_wait(uv_barrier_t* barrier) {
uv_mutex_lock(&barrier->mutex);
if (++barrier->count == barrier->n) {
uv_sem_wait(&barrier->turnstile2);
uv_sem_post(&barrier->turnstile1);
}
uv_mutex_unlock(&barrier->mutex);
uv_sem_wait(&barrier->turnstile1);
uv_sem_post(&barrier->turnstile1);
uv_mutex_lock(&barrier->mutex);
if (--barrier->count == 0) {
uv_sem_wait(&barrier->turnstile1);
uv_sem_post(&barrier->turnstile2);
}
uv_mutex_unlock(&barrier->mutex);
uv_sem_wait(&barrier->turnstile2);
uv_sem_post(&barrier->turnstile2);
}