diff options
| author | Patrick Steinhardt <ps@pks.im> | 2016-06-20 18:21:42 +0200 |
|---|---|---|
| committer | Patrick Steinhardt <ps@pks.im> | 2016-06-20 19:50:18 +0200 |
| commit | 8aaa9fb6238336b313766d7bd9c20cff07cb840b (patch) | |
| tree | f6c0f9cb5bbb3316bfbe63aa85000d6e885c765f /src/win32/thread.c | |
| parent | a342e870fcce7f524b54e5671cab4b0702e7540f (diff) | |
| download | libgit2-8aaa9fb6238336b313766d7bd9c20cff07cb840b.tar.gz | |
win32: rename pthread.{c,h} to thread.{c,h}
The old pthread-file did re-implement the pthreads API with exact symbol
matching. As the thread-abstraction has now been split up between Unix- and
Windows-specific files within the `git_` namespace to avoid symbol-clashes
between libgit2 and pthreads, the rewritten wrappers have nothing to do with
pthreads anymore.
Rename the Windows-specific pthread-files to honor this change.
Diffstat (limited to 'src/win32/thread.c')
| -rw-r--r-- | src/win32/thread.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/src/win32/thread.c b/src/win32/thread.c new file mode 100644 index 000000000..8222c65fe --- /dev/null +++ b/src/win32/thread.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "thread.h" +#include "../global.h" + +#define CLEAN_THREAD_EXIT 0x6F012842 + +/* The thread procedure stub used to invoke the caller's procedure + * and capture the return value for later collection. Windows will + * only hold a DWORD, but we need to be able to store an entire + * void pointer. This requires the indirection. */ +static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter) +{ + git_thread *thread = lpParameter; + + thread->result = thread->proc(thread->param); + + git__free_tls_data(); + + return CLEAN_THREAD_EXIT; +} + +int git_thread_create( + git_thread *GIT_RESTRICT thread, + void *(*start_routine)(void*), + void *GIT_RESTRICT arg) +{ + thread->result = NULL; + thread->param = arg; + thread->proc = start_routine; + thread->thread = CreateThread( + NULL, 0, git_win32__threadproc, thread, 0, NULL); + + return thread->thread ? 0 : -1; +} + +int git_thread_join( + git_thread *thread, + void **value_ptr) +{ + DWORD exit; + + if (WaitForSingleObject(thread->thread, INFINITE) != WAIT_OBJECT_0) + return -1; + + if (!GetExitCodeThread(thread->thread, &exit)) { + CloseHandle(thread->thread); + return -1; + } + + /* Check for the thread having exited uncleanly. If exit was unclean, + * then we don't have a return value to give back to the caller. */ + if (exit != CLEAN_THREAD_EXIT) { + assert(false); + thread->result = NULL; + } + + if (value_ptr) + *value_ptr = thread->result; + + CloseHandle(thread->thread); + return 0; +} + +int git_mutex_init(git_mutex *GIT_RESTRICT mutex) +{ + InitializeCriticalSection(mutex); + return 0; +} + +int git_mutex_free(git_mutex *mutex) +{ + DeleteCriticalSection(mutex); + return 0; +} + +int git_mutex_lock(git_mutex *mutex) +{ + EnterCriticalSection(mutex); + return 0; +} + +int git_mutex_unlock(git_mutex *mutex) +{ + LeaveCriticalSection(mutex); + return 0; +} + +int git_cond_init(git_cond *cond) +{ + /* This is an auto-reset event. */ + *cond = CreateEventW(NULL, FALSE, FALSE, NULL); + assert(*cond); + + /* If we can't create the event, claim that the reason was out-of-memory. + * The actual reason can be fetched with GetLastError(). */ + return *cond ? 0 : ENOMEM; +} + +int git_cond_free(git_cond *cond) +{ + BOOL closed; + + if (!cond) + return EINVAL; + + closed = CloseHandle(*cond); + assert(closed); + GIT_UNUSED(closed); + + *cond = NULL; + return 0; +} + +int git_cond_wait(git_cond *cond, git_mutex *mutex) +{ + int error; + DWORD wait_result; + + if (!cond || !mutex) + return EINVAL; + + /* The caller must be holding the mutex. */ + error = git_mutex_unlock(mutex); + + if (error) + return error; + + wait_result = WaitForSingleObject(*cond, INFINITE); + assert(WAIT_OBJECT_0 == wait_result); + GIT_UNUSED(wait_result); + + return git_mutex_lock(mutex); +} + +int git_cond_signal(git_cond *cond) +{ + BOOL signaled; + + if (!cond) + return EINVAL; + + signaled = SetEvent(*cond); + assert(signaled); + GIT_UNUSED(signaled); + + return 0; +} + + +typedef void (WINAPI *win32_srwlock_fn)(GIT_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 git_rwlock_init(git_rwlock *GIT_RESTRICT lock) +{ + if (win32_srwlock_initialize) + win32_srwlock_initialize(&lock->native.srwl); + else + InitializeCriticalSection(&lock->native.csec); + + return 0; +} + +int git_rwlock_rdlock(git_rwlock *lock) +{ + if (win32_srwlock_acquire_shared) + win32_srwlock_acquire_shared(&lock->native.srwl); + else + EnterCriticalSection(&lock->native.csec); + + return 0; +} + +int git_rwlock_rdunlock(git_rwlock *lock) +{ + if (win32_srwlock_release_shared) + win32_srwlock_release_shared(&lock->native.srwl); + else + LeaveCriticalSection(&lock->native.csec); + + return 0; +} + +int git_rwlock_wrlock(git_rwlock *lock) +{ + if (win32_srwlock_acquire_exclusive) + win32_srwlock_acquire_exclusive(&lock->native.srwl); + else + EnterCriticalSection(&lock->native.csec); + + return 0; +} + +int git_rwlock_wrunlock(git_rwlock *lock) +{ + if (win32_srwlock_release_exclusive) + win32_srwlock_release_exclusive(&lock->native.srwl); + else + LeaveCriticalSection(&lock->native.csec); + + return 0; +} + +int git_rwlock_free(git_rwlock *lock) +{ + if (!win32_srwlock_initialize) + DeleteCriticalSection(&lock->native.csec); + git__memzero(lock, sizeof(*lock)); + return 0; +} + +int win32_pthread_initialize(void) +{ + HMODULE hModule = GetModuleHandleW(L"kernel32"); + + if (hModule) { + win32_srwlock_initialize = (win32_srwlock_fn) + GetProcAddress(hModule, "InitializeSRWLock"); + win32_srwlock_acquire_shared = (win32_srwlock_fn) + GetProcAddress(hModule, "AcquireSRWLockShared"); + win32_srwlock_release_shared = (win32_srwlock_fn) + GetProcAddress(hModule, "ReleaseSRWLockShared"); + win32_srwlock_acquire_exclusive = (win32_srwlock_fn) + GetProcAddress(hModule, "AcquireSRWLockExclusive"); + win32_srwlock_release_exclusive = (win32_srwlock_fn) + GetProcAddress(hModule, "ReleaseSRWLockExclusive"); + } + + return 0; +} |
