Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/global.c')
-rw-r--r--src/global.c112
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)