summaryrefslogtreecommitdiff
path: root/src/win32
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-08-26 14:56:31 -0700
committerRussell Belfer <rb@github.com>2013-08-26 14:56:31 -0700
commit430953417f74dfcdbe030bafc069e1c07edceeb6 (patch)
treeb8276cc0ec5e481307202ec00ef7abcade6e9d98 /src/win32
parent44d655318661affa2feb51e9d6d533bb16d7f2b5 (diff)
downloadlibgit2-430953417f74dfcdbe030bafc069e1c07edceeb6.tar.gz
Load SRWLock APIs at runtime
This loads SRWLock APIs at runtime and in their absence (i.e. on Windows before Vista) falls back on a regular CRITICAL_SECTION that will not permit concurrent readers.
Diffstat (limited to 'src/win32')
-rw-r--r--src/win32/pthread.c89
-rw-r--r--src/win32/pthread.h14
2 files changed, 92 insertions, 11 deletions
diff --git a/src/win32/pthread.c b/src/win32/pthread.c
index 41cb7a4c0..8775f632a 100644
--- a/src/win32/pthread.c
+++ b/src/win32/pthread.c
@@ -127,9 +127,10 @@ int pthread_cond_signal(pthread_cond_t *cond)
return 0;
}
-/* pthread_cond_broadcast is not implemented because doing so with just Win32 events
- * is quite complicated, and no caller in libgit2 uses it yet. */
-
+/* pthread_cond_broadcast is not implemented because doing so with just
+ * Win32 events is quite complicated, and no caller in libgit2 uses it
+ * yet.
+ */
int pthread_num_processors_np(void)
{
DWORD_PTR p, s;
@@ -142,41 +143,111 @@ int pthread_num_processors_np(void)
return n ? n : 1;
}
+
+static HINSTANCE win32_kernel32_dll;
+
+typedef void (WINAPI *win32_srwlock_fn)(SRWLOCK *);
+
+static win32_srwlock_fn win32_srwlock_initialize;
+static win32_srwlock_fn win32_srwlock_acquire_shared;
+static win32_srwlock_fn win32_srwlock_release_shared;
+static win32_srwlock_fn win32_srwlock_acquire_exclusive;
+static win32_srwlock_fn win32_srwlock_release_exclusive;
+
int pthread_rwlock_init(
pthread_rwlock_t *GIT_RESTRICT lock,
const pthread_rwlockattr_t *GIT_RESTRICT attr)
{
(void)attr;
- InitializeSRWLock(lock);
+
+ if (win32_srwlock_initialize)
+ win32_srwlock_initialize(&lock->native.srwl);
+ else
+ InitializeCriticalSection(&lock->native.csec);
+
return 0;
}
int pthread_rwlock_rdlock(pthread_rwlock_t *lock)
{
- AcquireSRWLockShared(lock);
+ if (win32_srwlock_acquire_shared)
+ win32_srwlock_acquire_shared(&lock->native.srwl);
+ else
+ EnterCriticalSection(&lock->native.csec);
+
return 0;
}
int pthread_rwlock_rdunlock(pthread_rwlock_t *lock)
{
- ReleaseSRWLockShared(lock);
+ if (win32_srwlock_release_shared)
+ win32_srwlock_release_shared(&lock->native.srwl);
+ else
+ LeaveCriticalSection(&lock->native.csec);
+
return 0;
}
int pthread_rwlock_wrlock(pthread_rwlock_t *lock)
{
- AcquireSRWLockExclusive(lock);
+ if (win32_srwlock_acquire_exclusive)
+ win32_srwlock_acquire_exclusive(&lock->native.srwl);
+ else
+ EnterCriticalSection(&lock->native.csec);
+
return 0;
}
int pthread_rwlock_wrunlock(pthread_rwlock_t *lock)
{
- ReleaseSRWLockExclusive(lock);
+ if (win32_srwlock_release_exclusive)
+ win32_srwlock_release_exclusive(&lock->native.srwl);
+ else
+ LeaveCriticalSection(&lock->native.csec);
+
return 0;
}
int pthread_rwlock_destroy(pthread_rwlock_t *lock)
{
- (void)lock;
+ if (!win32_srwlock_initialize)
+ DeleteCriticalSection(&lock->native.csec);
+ git__memzero(lock, sizeof(*lock));
+ return 0;
+}
+
+
+int win32_pthread_initialize(void)
+{
+ if (win32_kernel32_dll)
+ return 0;
+
+ win32_kernel32_dll = LoadLibrary("Kernel32.dll");
+ if (!win32_kernel32_dll) {
+ giterr_set(GITERR_OS, "Could not load Kernel32.dll!");
+ return -1;
+ }
+
+ win32_srwlock_initialize = (win32_srwlock_fn)
+ GetProcAddress(win32_kernel32_dll, "InitializeSRWLock");
+ win32_srwlock_acquire_shared = (win32_srwlock_fn)
+ GetProcAddress(win32_kernel32_dll, "AcquireSRWLockShared");
+ win32_srwlock_release_shared = (win32_srwlock_fn)
+ GetProcAddress(win32_kernel32_dll, "ReleaseSRWLockShared");
+ win32_srwlock_acquire_exclusive = (win32_srwlock_fn)
+ GetProcAddress(win32_kernel32_dll, "AcquireSRWLockExclusive");
+ win32_srwlock_release_exclusive = (win32_srwlock_fn)
+ GetProcAddress(win32_kernel32_dll, "ReleaseSRWLockExclusive");
+
+ return 0;
+}
+
+int win32_pthread_shutdown(void)
+{
+ if (win32_kernel32_dll) {
+ FreeLibrary(win32_kernel32_dll);
+ win32_kernel32_dll = NULL;
+ }
+
return 0;
}
diff --git a/src/win32/pthread.h b/src/win32/pthread.h
index 50d836247..e84de471f 100644
--- a/src/win32/pthread.h
+++ b/src/win32/pthread.h
@@ -24,10 +24,17 @@ typedef int pthread_rwlockattr_t;
typedef CRITICAL_SECTION pthread_mutex_t;
typedef HANDLE pthread_t;
typedef HANDLE pthread_cond_t;
-typedef SRWLOCK pthread_rwlock_t;
+
+/* typedef struct { void *Ptr; } SRWLOCK; */
+
+typedef struct {
+ union {
+ SRWLOCK srwl;
+ CRITICAL_SECTION csec;
+ } native;
+} pthread_rwlock_t;
#define PTHREAD_MUTEX_INITIALIZER {(void*)-1}
-#define PTHREAD_RWLOCK_INITIALIZER SRWLOCK_INIT
int pthread_create(
pthread_t *GIT_RESTRICT thread,
@@ -61,4 +68,7 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *);
int pthread_rwlock_wrunlock(pthread_rwlock_t *);
int pthread_rwlock_destroy(pthread_rwlock_t *);
+extern int win32_pthread_initialize(void);
+extern int win32_pthread_shutdown(void);
+
#endif