Commit 8970acb750ecf4b86883d9ea1a8cb280517e6c86

Edward Thomson 2020-05-15T10:29:41

thread: don't use the global tlsdata for thread exit We want to store a pointer to emulate `pthread_exit` on Windows. Do this within the threading infrastructure so that it could potentially be re-used outside of the context of libgit2 itself.

diff --git a/src/threadstate.h b/src/threadstate.h
index 9a4ef4d..51810a9 100644
--- a/src/threadstate.h
+++ b/src/threadstate.h
@@ -14,12 +14,6 @@ typedef struct {
 	git_error error_t;
 	git_buf error_buf;
 	char oid_fmt[GIT_OID_HEXSZ+1];
-
-	/* On Windows, this is the current child thread that was started by
-	 * `git_thread_create`.  This is used to set the thread's exit code
-	 * when terminated by `git_thread_exit`.  It is unused on POSIX.
-	 */
-	git_thread *current_thread;
 } git_threadstate;
 
 extern int git_threadstate_global_init(void);
diff --git a/src/win32/thread.c b/src/win32/thread.c
index b9f8bc9..dad32ef 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -7,8 +7,6 @@
 
 #include "thread.h"
 
-#include "../tlsdata.h"
-
 #define CLEAN_THREAD_EXIT 0x6F012842
 
 typedef void (WINAPI *win32_srwlock_fn)(GIT_SRWLOCK *);
@@ -19,6 +17,8 @@ static win32_srwlock_fn win32_srwlock_release_shared;
 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
@@ -28,13 +28,18 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter)
 	git_thread *thread = lpParameter;
 
 	/* Set the current thread for `git_thread_exit` */
-	GIT_TLSDATA->current_thread = thread;
+	FlsSetValue(fls_index, thread);
 
 	thread->result = thread->proc(thread->param);
 
 	return CLEAN_THREAD_EXIT;
 }
 
+static void git_threads_global_shutdown(void)
+{
+	FlsFree(fls_index);
+}
+
 int git_threads_global_init(void)
 {
 	HMODULE hModule = GetModuleHandleW(L"kernel32");
@@ -52,6 +57,11 @@ int git_threads_global_init(void)
 			GetProcAddress(hModule, "ReleaseSRWLockExclusive");
 	}
 
+	if ((fls_index = FlsAlloc(NULL)) == FLS_OUT_OF_INDEXES)
+		return -1;
+
+	git__on_shutdown(git_threads_global_shutdown);
+
 	return 0;
 }
 
@@ -99,8 +109,11 @@ int git_thread_join(
 
 void git_thread_exit(void *value)
 {
-	assert(GIT_TLSDATA->current_thread);
-	GIT_TLSDATA->current_thread->result = value;
+	git_thread *thread = FlsGetValue(fls_index);
+
+	if (thread)
+		thread->result = value;
+
 	ExitThread(CLEAN_THREAD_EXIT);
 }