summaryrefslogtreecommitdiff
path: root/deps/uv/src/win/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'deps/uv/src/win/thread.c')
-rw-r--r--deps/uv/src/win/thread.c280
1 files changed, 76 insertions, 204 deletions
diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c
index bacceab95f..91684e9387 100644
--- a/deps/uv/src/win/thread.c
+++ b/deps/uv/src/win/thread.c
@@ -27,28 +27,8 @@
#include "internal.h"
-#define HAVE_SRWLOCK_API() (pTryAcquireSRWLockShared != NULL)
#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL)
-static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock);
-static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock);
-static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock);
-static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock);
-static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock);
-static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock);
-static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock);
-static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock);
-
-static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock);
-static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock);
-static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock);
-static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock);
-static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock);
-static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock);
-static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock);
-static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock);
-
-
static int uv_cond_fallback_init(uv_cond_t* cond);
static void uv_cond_fallback_destroy(uv_cond_t* cond);
static void uv_cond_fallback_signal(uv_cond_t* cond);
@@ -232,7 +212,7 @@ int uv_mutex_trylock(uv_mutex_t* mutex) {
if (TryEnterCriticalSection(mutex))
return 0;
else
- return UV_EAGAIN;
+ return UV_EBUSY;
}
@@ -242,68 +222,111 @@ void uv_mutex_unlock(uv_mutex_t* mutex) {
int uv_rwlock_init(uv_rwlock_t* rwlock) {
- uv__once_init();
+ /* Initialize the semaphore that acts as the write lock. */
+ HANDLE handle = CreateSemaphoreW(NULL, 1, 1, NULL);
+ if (handle == NULL)
+ return uv_translate_sys_error(GetLastError());
+ rwlock->state_.write_semaphore_ = handle;
- if (HAVE_SRWLOCK_API())
- return uv__rwlock_srwlock_init(rwlock);
- else
- return uv__rwlock_fallback_init(rwlock);
+ /* Initialize the critical section protecting the reader count. */
+ InitializeCriticalSection(&rwlock->state_.num_readers_lock_);
+
+ /* Initialize the reader count. */
+ rwlock->state_.num_readers_ = 0;
+
+ return 0;
}
void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
- if (HAVE_SRWLOCK_API())
- uv__rwlock_srwlock_destroy(rwlock);
- else
- uv__rwlock_fallback_destroy(rwlock);
+ DeleteCriticalSection(&rwlock->state_.num_readers_lock_);
+ CloseHandle(rwlock->state_.write_semaphore_);
}
void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
- if (HAVE_SRWLOCK_API())
- uv__rwlock_srwlock_rdlock(rwlock);
- else
- uv__rwlock_fallback_rdlock(rwlock);
+ /* Acquire the lock that protects the reader count. */
+ EnterCriticalSection(&rwlock->state_.num_readers_lock_);
+
+ /* Increase the reader count, and lock for write if this is the first
+ * reader.
+ */
+ if (++rwlock->state_.num_readers_ == 1) {
+ DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE);
+ if (r != WAIT_OBJECT_0)
+ uv_fatal_error(GetLastError(), "WaitForSingleObject");
+ }
+
+ /* Release the lock that protects the reader count. */
+ LeaveCriticalSection(&rwlock->state_.num_readers_lock_);
}
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);
+ int err;
+
+ if (!TryEnterCriticalSection(&rwlock->state_.num_readers_lock_))
+ return UV_EBUSY;
+
+ err = 0;
+
+ if (rwlock->state_.num_readers_ == 0) {
+ /* Currently there are no other readers, which means that the write lock
+ * needs to be acquired.
+ */
+ DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0);
+ if (r == WAIT_OBJECT_0)
+ rwlock->state_.num_readers_++;
+ else if (r == WAIT_TIMEOUT)
+ err = UV_EBUSY;
+ else if (r == WAIT_FAILED)
+ uv_fatal_error(GetLastError(), "WaitForSingleObject");
+
+ } else {
+ /* The write lock has already been acquired because there are other
+ * active readers.
+ */
+ rwlock->state_.num_readers_++;
+ }
+
+ LeaveCriticalSection(&rwlock->state_.num_readers_lock_);
+ return err;
}
void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
- if (HAVE_SRWLOCK_API())
- uv__rwlock_srwlock_rdunlock(rwlock);
- else
- uv__rwlock_fallback_rdunlock(rwlock);
+ EnterCriticalSection(&rwlock->state_.num_readers_lock_);
+
+ if (--rwlock->state_.num_readers_ == 0) {
+ if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL))
+ uv_fatal_error(GetLastError(), "ReleaseSemaphore");
+ }
+
+ LeaveCriticalSection(&rwlock->state_.num_readers_lock_);
}
void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
- if (HAVE_SRWLOCK_API())
- uv__rwlock_srwlock_wrlock(rwlock);
- else
- uv__rwlock_fallback_wrlock(rwlock);
+ DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, INFINITE);
+ if (r != WAIT_OBJECT_0)
+ uv_fatal_error(GetLastError(), "WaitForSingleObject");
}
int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
- if (HAVE_SRWLOCK_API())
- return uv__rwlock_srwlock_trywrlock(rwlock);
+ DWORD r = WaitForSingleObject(rwlock->state_.write_semaphore_, 0);
+ if (r == WAIT_OBJECT_0)
+ return 0;
+ else if (r == WAIT_TIMEOUT)
+ return UV_EBUSY;
else
- return uv__rwlock_fallback_trywrlock(rwlock);
+ uv_fatal_error(GetLastError(), "WaitForSingleObject");
}
void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
- if (HAVE_SRWLOCK_API())
- uv__rwlock_srwlock_wrunlock(rwlock);
- else
- uv__rwlock_fallback_wrunlock(rwlock);
+ if (!ReleaseSemaphore(rwlock->state_.write_semaphore_, 1, NULL))
+ uv_fatal_error(GetLastError(), "ReleaseSemaphore");
}
@@ -348,157 +371,6 @@ int uv_sem_trywait(uv_sem_t* sem) {
}
-static int uv__rwlock_srwlock_init(uv_rwlock_t* rwlock) {
- pInitializeSRWLock(&rwlock->srwlock_);
- return 0;
-}
-
-
-static void uv__rwlock_srwlock_destroy(uv_rwlock_t* rwlock) {
- (void) rwlock;
-}
-
-
-static void uv__rwlock_srwlock_rdlock(uv_rwlock_t* rwlock) {
- pAcquireSRWLockShared(&rwlock->srwlock_);
-}
-
-
-static int uv__rwlock_srwlock_tryrdlock(uv_rwlock_t* rwlock) {
- if (pTryAcquireSRWLockShared(&rwlock->srwlock_))
- return 0;
- else
- return UV_EBUSY; /* TODO(bnoordhuis) EAGAIN when owned by this thread. */
-}
-
-
-static void uv__rwlock_srwlock_rdunlock(uv_rwlock_t* rwlock) {
- pReleaseSRWLockShared(&rwlock->srwlock_);
-}
-
-
-static void uv__rwlock_srwlock_wrlock(uv_rwlock_t* rwlock) {
- pAcquireSRWLockExclusive(&rwlock->srwlock_);
-}
-
-
-static int uv__rwlock_srwlock_trywrlock(uv_rwlock_t* rwlock) {
- if (pTryAcquireSRWLockExclusive(&rwlock->srwlock_))
- return 0;
- else
- return UV_EBUSY; /* TODO(bnoordhuis) EAGAIN when owned by this thread. */
-}
-
-
-static void uv__rwlock_srwlock_wrunlock(uv_rwlock_t* rwlock) {
- pReleaseSRWLockExclusive(&rwlock->srwlock_);
-}
-
-
-static int uv__rwlock_fallback_init(uv_rwlock_t* rwlock) {
- /* Initialize the semaphore that acts as the write lock. */
- HANDLE handle = CreateSemaphoreW(NULL, 1, 1, NULL);
- if (handle == NULL)
- return uv_translate_sys_error(GetLastError());
- rwlock->fallback_.write_lock_.sem = handle;
-
- /* Initialize the critical section protecting the reader count. */
- InitializeCriticalSection(&rwlock->fallback_.read_lock_.cs);
-
- /* Initialize the reader count. */
- rwlock->fallback_.num_readers_ = 0;
-
- return 0;
-}
-
-
-static void uv__rwlock_fallback_destroy(uv_rwlock_t* rwlock) {
- DeleteCriticalSection(&rwlock->fallback_.read_lock_.cs);
- CloseHandle(rwlock->fallback_.write_lock_.sem);
-}
-
-
-static void uv__rwlock_fallback_rdlock(uv_rwlock_t* rwlock) {
- /* Acquire the lock that protects the reader count. */
- EnterCriticalSection(&rwlock->fallback_.read_lock_.cs);
-
- /* Increase the reader count, and lock for write if this is the first
- * reader.
- */
- if (++rwlock->fallback_.num_readers_ == 1) {
- DWORD r = WaitForSingleObject(rwlock->fallback_.write_lock_.sem, INFINITE);
- if (r != WAIT_OBJECT_0)
- uv_fatal_error(GetLastError(), "WaitForSingleObject");
- }
-
- /* Release the lock that protects the reader count. */
- LeaveCriticalSection(&rwlock->fallback_.read_lock_.cs);
-}
-
-
-static int uv__rwlock_fallback_tryrdlock(uv_rwlock_t* rwlock) {
- int err;
-
- if (!TryEnterCriticalSection(&rwlock->fallback_.read_lock_.cs))
- return UV_EAGAIN;
-
- err = 0;
- if (rwlock->fallback_.num_readers_ == 0) {
- DWORD r = WaitForSingleObject(rwlock->fallback_.write_lock_.sem, 0);
- if (r == WAIT_OBJECT_0)
- rwlock->fallback_.num_readers_++;
- else if (r == WAIT_TIMEOUT)
- err = UV_EAGAIN;
- else if (r == WAIT_FAILED)
- err = uv_translate_sys_error(GetLastError());
- else
- err = UV_EIO;
- }
-
- LeaveCriticalSection(&rwlock->fallback_.read_lock_.cs);
- return err;
-}
-
-
-static void uv__rwlock_fallback_rdunlock(uv_rwlock_t* rwlock) {
- EnterCriticalSection(&rwlock->fallback_.read_lock_.cs);
-
- if (--rwlock->fallback_.num_readers_ == 0) {
- if (!ReleaseSemaphore(rwlock->fallback_.write_lock_.sem, 1, NULL))
- uv_fatal_error(GetLastError(), "ReleaseSemaphore");
- }
-
- LeaveCriticalSection(&rwlock->fallback_.read_lock_.cs);
-}
-
-
-static void uv__rwlock_fallback_wrlock(uv_rwlock_t* rwlock) {
- DWORD r = WaitForSingleObject(rwlock->fallback_.write_lock_.sem, INFINITE);
- if (r != WAIT_OBJECT_0)
- uv_fatal_error(GetLastError(), "WaitForSingleObject");
-}
-
-
-static int uv__rwlock_fallback_trywrlock(uv_rwlock_t* rwlock) {
- DWORD r = WaitForSingleObject(rwlock->fallback_.write_lock_.sem, 0);
- if (r == WAIT_OBJECT_0)
- return 0;
- else if (r == WAIT_TIMEOUT)
- return UV_EAGAIN;
- else if (r == WAIT_FAILED)
- return uv_translate_sys_error(GetLastError());
- else
- return UV_EIO;
-}
-
-
-static void uv__rwlock_fallback_wrunlock(uv_rwlock_t* rwlock) {
- if (!ReleaseSemaphore(rwlock->fallback_.write_lock_.sem, 1, NULL))
- uv_fatal_error(GetLastError(), "ReleaseSemaphore");
-}
-
-
-
/* This condition variable implementation is based on the SetEvent solution
* (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
* We could not use the SignalObjectAndWait solution (section 3.4) because