diff options
Diffstat (limited to 'src/global.c')
-rw-r--r-- | src/global.c | 170 |
1 files changed, 20 insertions, 150 deletions
diff --git a/src/global.c b/src/global.c index c4e925b73..e6b7f46f0 100644 --- a/src/global.c +++ b/src/global.c @@ -5,7 +5,7 @@ * a Linking Exception. For full terms see the included COPYING file. */ -#include "global.h" +#include "runtime.h" #include "alloc.h" #include "threadstate.h" @@ -24,159 +24,29 @@ #include "transports/ssh.h" #include "win32/w32_stack.h" -typedef int (*git_global_init_fn)(void); - -static git_global_init_fn git__init_callbacks[] = { - git_allocator_global_init, - git_threadstate_global_init, - git_threads_global_init, - git_hash_global_init, - git_sysdir_global_init, - git_filter_global_init, - git_merge_driver_global_init, - git_transport_ssh_global_init, - git_stream_registry_global_init, - git_openssl_stream_global_init, - git_mbedtls_stream_global_init, - git_mwindow_global_init, - git_pool_global_init, - git_settings_global_init -}; - -static git_global_shutdown_fn git__shutdown_callbacks[ARRAY_SIZE(git__init_callbacks)]; - -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 <= (int) ARRAY_SIZE(git__shutdown_callbacks) && count > 0); - git__shutdown_callbacks[count - 1] = callback; -} - -static int init_common(void) -{ - size_t i; - int ret; - - /* Initialize subsystems that have global state */ - for (i = 0; i < ARRAY_SIZE(git__init_callbacks); i++) - if ((ret = git__init_callbacks[i]()) != 0) - break; - - GIT_MEMORY_BARRIER; - - return ret; -} - -static void shutdown_common(void) -{ - int pos; - - /* Shutdown subsystems that have registered */ - 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(); - } -} - -/* - * `git_libgit2_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_libgit2_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) - -/* - * On Win32, we use a spinlock to provide locking semantics. This is - * lighter-weight than a proper critical section. - */ -static volatile LONG init_spinlock = 0; - -GIT_INLINE(int) init_lock(void) -{ - while (InterlockedCompareExchange(&init_spinlock, 1, 0)) { Sleep(0); } - return 0; -} - -GIT_INLINE(int) init_unlock(void) -{ - InterlockedExchange(&init_spinlock, 0); - return 0; -} - -#elif defined(GIT_THREADS) && defined(_POSIX_THREADS) - -/* - * On POSIX, we need to use a proper mutex for locking. We might prefer - * a spinlock here, too, but there's no static initializer for a - * pthread_spinlock_t. - */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - -GIT_INLINE(int) init_lock(void) -{ - return pthread_mutex_lock(&mutex) == 0 ? 0 : -1; -} - -GIT_INLINE(int) init_unlock(void) -{ - return pthread_mutex_unlock(&mutex) == 0 ? 0 : -1; -} - -#elif defined(GIT_THREADS) -# error unknown threading model -#else - -# define init_lock() 0 -# define init_unlock() 0 - -#endif - int git_libgit2_init(void) { - int ret; - - if (init_lock() < 0) - return -1; - - /* Only do work on a 0 -> 1 transition of the refcount */ - if ((ret = git_atomic_inc(&git__n_inits)) == 1) { - if (init_common() < 0) - ret = -1; - } - - if (init_unlock() < 0) - return -1; - - return ret; + static git_runtime_init_fn init_fns[] = { + git_allocator_global_init, + git_threadstate_global_init, + git_threads_global_init, + git_hash_global_init, + git_sysdir_global_init, + git_filter_global_init, + git_merge_driver_global_init, + git_transport_ssh_global_init, + git_stream_registry_global_init, + git_openssl_stream_global_init, + git_mbedtls_stream_global_init, + git_mwindow_global_init, + git_pool_global_init, + git_settings_global_init + }; + + return git_runtime_init(init_fns, ARRAY_SIZE(init_fns)); } int git_libgit2_shutdown(void) { - int ret; - - /* Enter the lock */ - if (init_lock() < 0) - return -1; - - /* Only do work on a 1 -> 0 transition of the refcount */ - if ((ret = git_atomic_dec(&git__n_inits)) == 0) - shutdown_common(); - - /* Exit the lock */ - if (init_unlock() < 0) - return -1; - - return ret; + return git_runtime_shutdown(); } |