diff options
Diffstat (limited to 'src/global.c')
-rw-r--r-- | src/global.c | 112 |
1 files changed, 91 insertions, 21 deletions
diff --git a/src/global.c b/src/global.c index 7d39c6fa8..03a4bcedf 100644 --- a/src/global.c +++ b/src/global.c @@ -7,7 +7,7 @@ #include "common.h" #include "global.h" #include "hash.h" -#include "fileops.h" +#include "sysdir.h" #include "git2/threads.h" #include "thread-utils.h" @@ -16,13 +16,20 @@ git_mutex git__mwindow_mutex; #define MAX_SHUTDOWN_CB 8 -git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB]; -git_atomic git__n_shutdown_callbacks; +#ifdef GIT_SSL +# include <openssl/ssl.h> +SSL_CTX *git__ssl_ctx; +static git_mutex *openssl_locks; +#endif + +static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB]; +static git_atomic git__n_shutdown_callbacks; +static git_atomic git__n_inits; void git__on_shutdown(git_global_shutdown_fn callback) { int count = git_atomic_inc(&git__n_shutdown_callbacks); - assert(count <= MAX_SHUTDOWN_CB); + assert(count <= MAX_SHUTDOWN_CB && count > 0); git__shutdown_callbacks[count - 1] = callback; } @@ -30,10 +37,68 @@ static void git__shutdown(void) { int pos; - while ((pos = git_atomic_dec(&git__n_shutdown_callbacks)) >= 0) { - if (git__shutdown_callbacks[pos]) - git__shutdown_callbacks[pos](); + for (pos = git_atomic_get(&git__n_shutdown_callbacks); pos > 0; pos = git_atomic_dec(&git__n_shutdown_callbacks)) { + git_global_shutdown_fn cb = git__swap(git__shutdown_callbacks[pos - 1], NULL); + if (cb != NULL) + cb(); + } + +} + +#if defined(GIT_THREADS) && defined(GIT_SSL) +void openssl_locking_function(int mode, int n, const char *file, int line) +{ + int lock; + + GIT_UNUSED(file); + GIT_UNUSED(line); + + lock = mode & CRYPTO_LOCK; + + if (lock) { + git_mutex_lock(&openssl_locks[n]); + } else { + git_mutex_unlock(&openssl_locks[n]); + } +} +#endif + + +static void init_ssl(void) +{ +#ifdef GIT_SSL + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); + git__ssl_ctx = SSL_CTX_new(SSLv23_method()); + SSL_CTX_set_mode(git__ssl_ctx, SSL_MODE_AUTO_RETRY); + SSL_CTX_set_verify(git__ssl_ctx, SSL_VERIFY_NONE, NULL); + if (!SSL_CTX_set_default_verify_paths(git__ssl_ctx)) { + SSL_CTX_free(git__ssl_ctx); + git__ssl_ctx = NULL; + } + +# ifdef GIT_THREADS + { + int num_locks, i; + + num_locks = CRYPTO_num_locks(); + openssl_locks = git__calloc(num_locks, sizeof(git_mutex)); + if (openssl_locks == NULL) { + SSL_CTX_free(git__ssl_ctx); + git__ssl_ctx = NULL; + } + + for (i = 0; i < num_locks; i++) { + if (git_mutex_init(&openssl_locks[i]) != 0) { + SSL_CTX_free(git__ssl_ctx); + git__ssl_ctx = NULL; + } + } + + CRYPTO_set_locking_callback(openssl_locking_function); } +# endif +#endif } /** @@ -73,10 +138,9 @@ static void git__shutdown(void) #if defined(GIT_THREADS) && defined(GIT_WIN32) static DWORD _tls_index; -static DWORD _mutex = 0; -static DWORD _n_inits = 0; +static volatile LONG _mutex = 0; -static int synchronized_threads_init() +static int synchronized_threads_init(void) { int error; @@ -86,7 +150,7 @@ static int synchronized_threads_init() /* Initialize any other subsystems that have global state */ if ((error = git_hash_global_init()) >= 0) - error = git_futils_dirs_global_init(); + error = git_sysdir_global_init(); win32_pthread_initialize(); @@ -101,7 +165,7 @@ int git_threads_init(void) while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); } /* Only do work on a 0 -> 1 transition of the refcount */ - if (1 == ++_n_inits) + if (1 == git_atomic_inc(&git__n_inits)) error = synchronized_threads_init(); /* Exit the lock */ @@ -110,7 +174,7 @@ int git_threads_init(void) return error; } -static void synchronized_threads_shutdown() +static void synchronized_threads_shutdown(void) { /* Shut down any subsystems that have global state */ git__shutdown(); @@ -124,7 +188,7 @@ void git_threads_shutdown(void) while (InterlockedCompareExchange(&_mutex, 1, 0)) { Sleep(0); } /* Only do work on a 1 -> 0 transition of the refcount */ - if (0 == --_n_inits) + if (0 == git_atomic_dec(&git__n_inits)) synchronized_threads_shutdown(); /* Exit the lock */ @@ -135,7 +199,7 @@ git_global_st *git__global_state(void) { void *ptr; - assert(_n_inits); + assert(git_atomic_get(&git__n_inits) > 0); if ((ptr = TlsGetValue(_tls_index)) != NULL) return ptr; @@ -153,7 +217,6 @@ git_global_st *git__global_state(void) static pthread_key_t _tls_key; static pthread_once_t _once_init = PTHREAD_ONCE_INIT; -static git_atomic git__n_inits; int init_error = 0; static void cb__free_status(void *st) @@ -167,9 +230,13 @@ static void init_once(void) return; pthread_key_create(&_tls_key, &cb__free_status); + /* Initialize any other subsystems that have global state */ if ((init_error = git_hash_global_init()) >= 0) - init_error = git_futils_dirs_global_init(); + init_error = git_sysdir_global_init(); + + /* OpenSSL needs to be initialized from the main thread */ + init_ssl(); GIT_MEMORY_BARRIER; } @@ -183,6 +250,7 @@ int git_threads_init(void) void git_threads_shutdown(void) { + void *ptr = NULL; pthread_once_t new_once = PTHREAD_ONCE_INIT; if (git_atomic_dec(&git__n_inits) > 0) return; @@ -190,7 +258,7 @@ void git_threads_shutdown(void) /* Shut down any subsystems that have global state */ git__shutdown(); - void *ptr = pthread_getspecific(_tls_key); + ptr = pthread_getspecific(_tls_key); pthread_setspecific(_tls_key, NULL); git__free(ptr); @@ -203,7 +271,7 @@ git_global_st *git__global_state(void) { void *ptr; - assert(git__n_inits.val); + assert(git_atomic_get(&git__n_inits) > 0); if ((ptr = pthread_getspecific(_tls_key)) != NULL) return ptr; @@ -223,14 +291,16 @@ static git_global_st __state; int git_threads_init(void) { - /* noop */ + init_ssl(); + git_atomic_inc(&git__n_inits); return 0; } void git_threads_shutdown(void) { /* Shut down any subsystems that have global state */ - git__shutdown(); + if (0 == git_atomic_dec(&git__n_inits)) + git__shutdown(); } git_global_st *git__global_state(void) |