Commit 20ce17f06d27a92ada11fa5d15108532223e9884

Tyler Ang-Wanek 2020-08-06T16:24:27

Replace global storage TLS with new interface

diff --git a/src/threadstate.c b/src/threadstate.c
index 1c5ac60..6031e82 100644
--- a/src/threadstate.c
+++ b/src/threadstate.c
@@ -8,8 +8,6 @@
 #include "threadstate.h"
 #include "runtime.h"
 
-static void threadstate_dispose(git_threadstate *threadstate);
-
 /**
  * Handle the thread-local state
  *
@@ -17,8 +15,7 @@ static void threadstate_dispose(git_threadstate *threadstate);
  * of `git_libgit2_init` (which itself must be called
  * before calling any other function in the library).
  *
- * This function allocates a TLS index (using pthreads
- * or fiber-local storage in Win32) to store the per-
+ * This function allocates a TLS index to store the per-
  * thread state.
  *
  * Any internal method that requires thread-local state
@@ -30,77 +27,41 @@ static void threadstate_dispose(git_threadstate *threadstate);
  * (`git_threadstate_global_shutdown`) which will free the
  * TLS index.  This shutdown handler will be called by
  * `git_libgit2_shutdown`.
- *
- * If libgit2 is built without threading support, the
- * `git_threadstate_get()` call returns a pointer to a single,
- * statically allocated global state. The `git_thread_`
- * functions are not available in that case.
  */
 
-#if defined(GIT_THREADS) && defined(GIT_WIN32)
+static git_tlsdata_key tls_key;
 
-static DWORD fls_index;
-
-static void git_threadstate_global_shutdown(void)
+static void threadstate_dispose(git_threadstate *threadstate)
 {
-	FlsFree(fls_index);
+	if (!threadstate)
+		return;
+
+	git__free(threadstate->error_t.message);
+	threadstate->error_t.message = NULL;
 }
 
-static void WINAPI fls_free(void *threadstate)
+static void GIT_SYSTEM_CALL threadstate_free(void *threadstate)
 {
 	threadstate_dispose(threadstate);
 	git__free(threadstate);
 }
 
-int git_threadstate_global_init(void)
-{
-	if ((fls_index = FlsAlloc(fls_free)) == FLS_OUT_OF_INDEXES)
-		return -1;
-
-	return git_runtime_shutdown_register(git_threadstate_global_shutdown);
-}
-
-git_threadstate *git_threadstate_get(void)
-{
-	git_threadstate *threadstate;
-
-	if ((threadstate = FlsGetValue(fls_index)) != NULL)
-		return threadstate;
-
-	if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL ||
-	    git_buf_init(&threadstate->error_buf, 0) < 0)
-		return NULL;
-
-	FlsSetValue(fls_index, threadstate);
-	return threadstate;
-}
-
-#elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
-
-static pthread_key_t tls_key;
-
 static void git_threadstate_global_shutdown(void)
 {
 	git_threadstate *threadstate;
 
-	threadstate = pthread_getspecific(tls_key);
-	pthread_setspecific(tls_key, NULL);
+	threadstate = git_tlsdata_get(tls_key);
+	git_tlsdata_set(tls_key, NULL);
 
 	threadstate_dispose(threadstate);
 	git__free(threadstate);
 
-	pthread_key_delete(tls_key);
-}
-
-static void tls_free(void *threadstate)
-{
-	threadstate_dispose(threadstate);
-	git__free(threadstate);
+	git_tlsdata_dispose(tls_key);
 }
 
 int git_threadstate_global_init(void)
 {
-	if (pthread_key_create(&tls_key, &tls_free) != 0)
+	if (git_tlsdata_init(&tls_key, &threadstate_free) != 0)
 		return -1;
 
 	return git_runtime_shutdown_register(git_threadstate_global_shutdown);
@@ -110,46 +71,13 @@ git_threadstate *git_threadstate_get(void)
 {
 	git_threadstate *threadstate;
 
-	if ((threadstate = pthread_getspecific(tls_key)) != NULL)
+	if ((threadstate = git_tlsdata_get(tls_key)) != NULL)
 		return threadstate;
 
 	if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL ||
 	    git_buf_init(&threadstate->error_buf, 0) < 0)
 		return NULL;
 
-	pthread_setspecific(tls_key, threadstate);
+	git_tlsdata_set(tls_key, threadstate);
 	return threadstate;
 }
-
-#elif defined(GIT_THREADS)
-# error unknown threading model
-#else
-
-static git_threadstate threadstate;
-
-static void git_threadstate_global_shutdown(void)
-{
-	threadstate_dispose(&threadstate);
-	memset(&threadstate, 0, sizeof(git_threadstate));
-}
-
-int git_threadstate_global_init(void)
-{
-	return git_runtime_shutdown_register(git_threadstate_global_shutdown);
-}
-
-git_threadstate *git_threadstate_get(void)
-{
-	return &threadstate;
-}
-
-#endif
-
-static void threadstate_dispose(git_threadstate *threadstate)
-{
-	if (!threadstate)
-		return;
-
-	git__free(threadstate->error_t.message);
-	threadstate->error_t.message = NULL;
-}