summaryrefslogtreecommitdiff
path: root/src/global.c
diff options
context:
space:
mode:
authorVicent Martí <vicent@github.com>2012-11-13 13:28:08 -0800
committerVicent Martí <vicent@github.com>2012-11-13 13:28:08 -0800
commit3741a37f5ee80d7475cdfedcd4de7d8ea64cf1e8 (patch)
tree8861ec34c51061c59ed2daf945d2b7cf77456fed /src/global.c
parent70572ff80b071aae5d6b398572e1aa0be45f6844 (diff)
parent2a612fe3c31f2c386236ccb1483741835a5db318 (diff)
downloadlibgit2-3741a37f5ee80d7475cdfedcd4de7d8ea64cf1e8.tar.gz
Merge pull request #1055 from ethomson/sha1_win32
Win32 CryptoAPI and CNG support for SHA1
Diffstat (limited to 'src/global.c')
-rw-r--r--src/global.c51
1 files changed, 44 insertions, 7 deletions
diff --git a/src/global.c b/src/global.c
index 22127faf7..d085089c3 100644
--- a/src/global.c
+++ b/src/global.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
#include "global.h"
+#include "hash.h"
#include "git2/threads.h"
#include "thread-utils.h"
@@ -38,19 +39,39 @@ git_mutex git__mwindow_mutex;
* functions are not available in that case.
*/
+/*
+ * `git_threads_init()` allows subsystems to perform global setup,
+ * which may take place in the global scope. An explicit memory
+ * fence exists at the exit of `git_threads_init()`. Without this,
+ * CPU cores are free to reorder cache invalidation of `_tls_init`
+ * before cache invalidation of the subsystems' newly written global
+ * state.
+ */
#if defined(GIT_THREADS) && defined(GIT_WIN32)
static DWORD _tls_index;
static int _tls_init = 0;
-void git_threads_init(void)
+int git_threads_init(void)
{
+ int error;
+
if (_tls_init)
- return;
+ return 0;
_tls_index = TlsAlloc();
- _tls_init = 1;
git_mutex_init(&git__mwindow_mutex);
+
+ /* Initialize any other subsystems that have global state */
+ if ((error = git_hash_global_init()) >= 0)
+ _tls_init = 1;
+
+ if (error == 0)
+ _tls_init = 1;
+
+ GIT_MEMORY_BARRIER;
+
+ return error;
}
void git_threads_shutdown(void)
@@ -58,6 +79,9 @@ void git_threads_shutdown(void)
TlsFree(_tls_index);
_tls_init = 0;
git_mutex_free(&git__mwindow_mutex);
+
+ /* Shut down any subsystems that have global state */
+ git_hash_global_shutdown();
}
git_global_st *git__global_state(void)
@@ -88,19 +112,31 @@ static void cb__free_status(void *st)
git__free(st);
}
-void git_threads_init(void)
+int git_threads_init(void)
{
+ int error = 0;
+
if (_tls_init)
- return;
+ return 0;
pthread_key_create(&_tls_key, &cb__free_status);
- _tls_init = 1;
+
+ /* Initialize any other subsystems that have global state */
+ if ((error = git_hash_global_init()) >= 0)
+ _tls_init = 1;
+
+ GIT_MEMORY_BARRIER;
+
+ return error;
}
void git_threads_shutdown(void)
{
pthread_key_delete(_tls_key);
_tls_init = 0;
+
+ /* Shut down any subsystems that have global state */
+ git_hash_global_shutdown();
}
git_global_st *git__global_state(void)
@@ -125,9 +161,10 @@ git_global_st *git__global_state(void)
static git_global_st __state;
-void git_threads_init(void)
+int git_threads_init(void)
{
/* noop */
+ return 0;
}
void git_threads_shutdown(void)