*/
#include "thread.h"
-#include "../global.h"
+#include "runtime.h"
#define CLEAN_THREAD_EXIT 0x6F012842
static win32_srwlock_fn win32_srwlock_acquire_exclusive;
static win32_srwlock_fn win32_srwlock_release_exclusive;
+static DWORD fls_index;
+
/* 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
git_thread *thread = lpParameter;
/* Set the current thread for `git_thread_exit` */
- GIT_GLOBAL->current_thread = thread;
+ FlsSetValue(fls_index, thread);
thread->result = thread->proc(thread->param);
- git__free_tls_data();
-
return CLEAN_THREAD_EXIT;
}
-int git_threads_init(void)
+static void git_threads_global_shutdown(void)
+{
+ FlsFree(fls_index);
+}
+
+int git_threads_global_init(void)
{
HMODULE hModule = GetModuleHandleW(L"kernel32");
if (hModule) {
- win32_srwlock_initialize = (win32_srwlock_fn)
+ win32_srwlock_initialize = (win32_srwlock_fn)(void *)
GetProcAddress(hModule, "InitializeSRWLock");
- win32_srwlock_acquire_shared = (win32_srwlock_fn)
+ win32_srwlock_acquire_shared = (win32_srwlock_fn)(void *)
GetProcAddress(hModule, "AcquireSRWLockShared");
- win32_srwlock_release_shared = (win32_srwlock_fn)
+ win32_srwlock_release_shared = (win32_srwlock_fn)(void *)
GetProcAddress(hModule, "ReleaseSRWLockShared");
- win32_srwlock_acquire_exclusive = (win32_srwlock_fn)
+ win32_srwlock_acquire_exclusive = (win32_srwlock_fn)(void *)
GetProcAddress(hModule, "AcquireSRWLockExclusive");
- win32_srwlock_release_exclusive = (win32_srwlock_fn)
+ win32_srwlock_release_exclusive = (win32_srwlock_fn)(void *)
GetProcAddress(hModule, "ReleaseSRWLockExclusive");
}
- return 0;
+ if ((fls_index = FlsAlloc(NULL)) == FLS_OUT_OF_INDEXES)
+ return -1;
+
+ return git_runtime_shutdown_register(git_threads_global_shutdown);
}
int git_thread_create(
/* 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;
- }
+ GIT_ASSERT(exit == CLEAN_THREAD_EXIT);
if (value_ptr)
*value_ptr = thread->result;
void git_thread_exit(void *value)
{
- assert(GIT_GLOBAL->current_thread);
- GIT_GLOBAL->current_thread->result = value;
+ git_thread *thread = FlsGetValue(fls_index);
- git__free_tls_data();
+ if (thread)
+ thread->result = value;
ExitThread(CLEAN_THREAD_EXIT);
}
{
/* This is an auto-reset event. */
*cond = CreateEventW(NULL, FALSE, FALSE, NULL);
- assert(*cond);
+ GIT_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 EINVAL;
closed = CloseHandle(*cond);
- assert(closed);
+ GIT_ASSERT(closed);
GIT_UNUSED(closed);
*cond = NULL;
return error;
wait_result = WaitForSingleObject(*cond, INFINITE);
- assert(WAIT_OBJECT_0 == wait_result);
+ GIT_ASSERT(WAIT_OBJECT_0 == wait_result);
GIT_UNUSED(wait_result);
return git_mutex_lock(mutex);
return EINVAL;
signaled = SetEvent(*cond);
- assert(signaled);
+ GIT_ASSERT(signaled);
GIT_UNUSED(signaled);
return 0;