summaryrefslogtreecommitdiff
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
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.
-rw-r--r--CMakeLists.txt7
-rw-r--r--src/global.c12
-rw-r--r--src/hash/hash_win32.c3
-rw-r--r--src/thread-utils.h4
-rw-r--r--src/win32/pthread.c89
-rw-r--r--src/win32/pthread.h14
6 files changed, 103 insertions, 26 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 019777e78..1c70ec2d6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -287,13 +287,8 @@ FILE(GLOB SRC_H include/git2.h include/git2/*.h include/git2/sys/*.h)
# On Windows use specific platform sources
IF (WIN32 AND NOT CYGWIN)
- ADD_DEFINITIONS(-DWIN32)
+ ADD_DEFINITIONS(-DWIN32 -D_WIN32_WINNT=0x0501)
FILE(GLOB SRC_OS src/win32/*.c src/win32/*.h)
- IF (THREADSAFE)
- ADD_DEFINITIONS(-D_WIN32_WINNT=0x0600)
- ELSE()
- ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501)
- ENDIF()
ELSEIF (AMIGA)
ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R)
FILE(GLOB SRC_OS src/amiga/*.c src/amiga/*.h)
diff --git a/src/global.c b/src/global.c
index a06d0c81f..b504e5e0a 100644
--- a/src/global.c
+++ b/src/global.c
@@ -71,18 +71,22 @@ int git_threads_init(void)
GIT_MEMORY_BARRIER;
+ win32_pthread_initialize();
+
return error;
}
void git_threads_shutdown(void)
{
+ /* Shut down any subsystems that have global state */
+ win32_pthread_shutdown();
+ git_futils_dirs_free();
+ git_hash_global_shutdown();
+
TlsFree(_tls_index);
_tls_init = 0;
- git_mutex_free(&git__mwindow_mutex);
- /* Shut down any subsystems that have global state */
- git_hash_global_shutdown();
- git_futils_dirs_free();
+ git_mutex_free(&git__mwindow_mutex);
}
git_global_st *git__global_state(void)
diff --git a/src/hash/hash_win32.c b/src/hash/hash_win32.c
index 43d54ca6d..6732f93d7 100644
--- a/src/hash/hash_win32.c
+++ b/src/hash/hash_win32.c
@@ -46,7 +46,8 @@ GIT_INLINE(int) hash_cng_prov_init(void)
return -1;
/* Load bcrypt.dll explicitly from the system directory */
- if ((dll_path_len = GetSystemDirectory(dll_path, MAX_PATH)) == 0 || dll_path_len > MAX_PATH ||
+ if ((dll_path_len = GetSystemDirectory(dll_path, MAX_PATH)) == 0 ||
+ dll_path_len > MAX_PATH ||
StringCchCat(dll_path, MAX_PATH, "\\") < 0 ||
StringCchCat(dll_path, MAX_PATH, GIT_HASH_CNG_DLL_NAME) < 0 ||
(hash_prov.prov.cng.dll = LoadLibrary(dll_path)) == NULL)
diff --git a/src/thread-utils.h b/src/thread-utils.h
index 371dc0b26..914c1357d 100644
--- a/src/thread-utils.h
+++ b/src/thread-utils.h
@@ -40,10 +40,6 @@ typedef git_atomic git_atomic_ssize;
#ifdef GIT_THREADS
-#if defined(GIT_WIN32) && _WIN32_WINNT < 0x0600
-# error "Unsupported Windows version for thread support"
-#endif
-
#define git_thread pthread_t
#define git_thread_create(thread, attr, start_routine, arg) \
pthread_create(thread, attr, start_routine, arg)
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