Commit 43095341 by Russell Belfer

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.
parent 44d65531
...@@ -287,13 +287,8 @@ FILE(GLOB SRC_H include/git2.h include/git2/*.h include/git2/sys/*.h) ...@@ -287,13 +287,8 @@ FILE(GLOB SRC_H include/git2.h include/git2/*.h include/git2/sys/*.h)
# On Windows use specific platform sources # On Windows use specific platform sources
IF (WIN32 AND NOT CYGWIN) 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) 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) ELSEIF (AMIGA)
ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R) ADD_DEFINITIONS(-DNO_ADDRINFO -DNO_READDIR_R)
FILE(GLOB SRC_OS src/amiga/*.c src/amiga/*.h) FILE(GLOB SRC_OS src/amiga/*.c src/amiga/*.h)
......
...@@ -71,18 +71,22 @@ int git_threads_init(void) ...@@ -71,18 +71,22 @@ int git_threads_init(void)
GIT_MEMORY_BARRIER; GIT_MEMORY_BARRIER;
win32_pthread_initialize();
return error; return error;
} }
void git_threads_shutdown(void) 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); TlsFree(_tls_index);
_tls_init = 0; _tls_init = 0;
git_mutex_free(&git__mwindow_mutex);
/* Shut down any subsystems that have global state */ git_mutex_free(&git__mwindow_mutex);
git_hash_global_shutdown();
git_futils_dirs_free();
} }
git_global_st *git__global_state(void) git_global_st *git__global_state(void)
......
...@@ -46,7 +46,8 @@ GIT_INLINE(int) hash_cng_prov_init(void) ...@@ -46,7 +46,8 @@ GIT_INLINE(int) hash_cng_prov_init(void)
return -1; return -1;
/* Load bcrypt.dll explicitly from the system directory */ /* 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, "\\") < 0 ||
StringCchCat(dll_path, MAX_PATH, GIT_HASH_CNG_DLL_NAME) < 0 || StringCchCat(dll_path, MAX_PATH, GIT_HASH_CNG_DLL_NAME) < 0 ||
(hash_prov.prov.cng.dll = LoadLibrary(dll_path)) == NULL) (hash_prov.prov.cng.dll = LoadLibrary(dll_path)) == NULL)
......
...@@ -40,10 +40,6 @@ typedef git_atomic git_atomic_ssize; ...@@ -40,10 +40,6 @@ typedef git_atomic git_atomic_ssize;
#ifdef GIT_THREADS #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 pthread_t
#define git_thread_create(thread, attr, start_routine, arg) \ #define git_thread_create(thread, attr, start_routine, arg) \
pthread_create(thread, attr, start_routine, arg) pthread_create(thread, attr, start_routine, arg)
......
...@@ -127,9 +127,10 @@ int pthread_cond_signal(pthread_cond_t *cond) ...@@ -127,9 +127,10 @@ int pthread_cond_signal(pthread_cond_t *cond)
return 0; return 0;
} }
/* pthread_cond_broadcast is not implemented because doing so with just Win32 events /* pthread_cond_broadcast is not implemented because doing so with just
* is quite complicated, and no caller in libgit2 uses it yet. */ * Win32 events is quite complicated, and no caller in libgit2 uses it
* yet.
*/
int pthread_num_processors_np(void) int pthread_num_processors_np(void)
{ {
DWORD_PTR p, s; DWORD_PTR p, s;
...@@ -142,41 +143,111 @@ int pthread_num_processors_np(void) ...@@ -142,41 +143,111 @@ int pthread_num_processors_np(void)
return n ? n : 1; 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( int pthread_rwlock_init(
pthread_rwlock_t *GIT_RESTRICT lock, pthread_rwlock_t *GIT_RESTRICT lock,
const pthread_rwlockattr_t *GIT_RESTRICT attr) const pthread_rwlockattr_t *GIT_RESTRICT attr)
{ {
(void)attr; (void)attr;
InitializeSRWLock(lock);
if (win32_srwlock_initialize)
win32_srwlock_initialize(&lock->native.srwl);
else
InitializeCriticalSection(&lock->native.csec);
return 0; return 0;
} }
int pthread_rwlock_rdlock(pthread_rwlock_t *lock) 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; return 0;
} }
int pthread_rwlock_rdunlock(pthread_rwlock_t *lock) 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; return 0;
} }
int pthread_rwlock_wrlock(pthread_rwlock_t *lock) 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; return 0;
} }
int pthread_rwlock_wrunlock(pthread_rwlock_t *lock) 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; return 0;
} }
int pthread_rwlock_destroy(pthread_rwlock_t *lock) 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; return 0;
} }
...@@ -24,10 +24,17 @@ typedef int pthread_rwlockattr_t; ...@@ -24,10 +24,17 @@ typedef int pthread_rwlockattr_t;
typedef CRITICAL_SECTION pthread_mutex_t; typedef CRITICAL_SECTION pthread_mutex_t;
typedef HANDLE pthread_t; typedef HANDLE pthread_t;
typedef HANDLE pthread_cond_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_MUTEX_INITIALIZER {(void*)-1}
#define PTHREAD_RWLOCK_INITIALIZER SRWLOCK_INIT
int pthread_create( int pthread_create(
pthread_t *GIT_RESTRICT thread, pthread_t *GIT_RESTRICT thread,
...@@ -61,4 +68,7 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *); ...@@ -61,4 +68,7 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *);
int pthread_rwlock_wrunlock(pthread_rwlock_t *); int pthread_rwlock_wrunlock(pthread_rwlock_t *);
int pthread_rwlock_destroy(pthread_rwlock_t *); int pthread_rwlock_destroy(pthread_rwlock_t *);
extern int win32_pthread_initialize(void);
extern int win32_pthread_shutdown(void);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment