2 * Copyright (C) the libgit2 contributors. All rights reserved.
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
11 #include "git2/global.h"
12 #include "git2/sys/openssl.h"
13 #include "thread-utils.h"
16 git_mutex git__mwindow_mutex
;
18 #define MAX_SHUTDOWN_CB 8
21 # include <openssl/ssl.h>
22 SSL_CTX
*git__ssl_ctx
;
24 static git_mutex
*openssl_locks
;
28 static git_global_shutdown_fn git__shutdown_callbacks
[MAX_SHUTDOWN_CB
];
29 static git_atomic git__n_shutdown_callbacks
;
30 static git_atomic git__n_inits
;
32 void git__on_shutdown(git_global_shutdown_fn callback
)
34 int count
= git_atomic_inc(&git__n_shutdown_callbacks
);
35 assert(count
<= MAX_SHUTDOWN_CB
&& count
> 0);
36 git__shutdown_callbacks
[count
- 1] = callback
;
39 static void git__shutdown(void)
43 for (pos
= git_atomic_get(&git__n_shutdown_callbacks
); pos
> 0; pos
= git_atomic_dec(&git__n_shutdown_callbacks
)) {
44 git_global_shutdown_fn cb
= git__swap(git__shutdown_callbacks
[pos
- 1], NULL
);
51 #if defined(GIT_THREADS) && defined(GIT_SSL)
52 void openssl_locking_function(int mode
, int n
, const char *file
, int line
)
59 lock
= mode
& CRYPTO_LOCK
;
62 git_mutex_lock(&openssl_locks
[n
]);
64 git_mutex_unlock(&openssl_locks
[n
]);
68 static void shutdown_ssl_locking(void)
72 num_locks
= CRYPTO_num_locks();
73 CRYPTO_set_locking_callback(NULL
);
75 for (i
= 0; i
< num_locks
; ++i
)
76 git_mutex_free(openssl_locks
);
77 git__free(openssl_locks
);
81 static void init_ssl(void)
84 long ssl_opts
= SSL_OP_NO_SSLv2
| SSL_OP_NO_SSLv3
;
86 /* Older OpenSSL and MacOS OpenSSL doesn't have this */
87 #ifdef SSL_OP_NO_COMPRESSION
88 ssl_opts
|= SSL_OP_NO_COMPRESSION
;
91 SSL_load_error_strings();
92 OpenSSL_add_ssl_algorithms();
94 * Load SSLv{2,3} and TLSv1 so that we can talk with servers
95 * which use the SSL hellos, which are often used for
96 * compatibility. We then disable SSL so we only allow OpenSSL
97 * to speak TLSv1 to perform the encryption itself.
99 git__ssl_ctx
= SSL_CTX_new(SSLv23_method());
100 SSL_CTX_set_options(git__ssl_ctx
, ssl_opts
);
101 SSL_CTX_set_mode(git__ssl_ctx
, SSL_MODE_AUTO_RETRY
);
102 SSL_CTX_set_verify(git__ssl_ctx
, SSL_VERIFY_NONE
, NULL
);
103 if (!SSL_CTX_set_default_verify_paths(git__ssl_ctx
)) {
104 SSL_CTX_free(git__ssl_ctx
);
110 int git_openssl_set_locking(void)
116 num_locks
= CRYPTO_num_locks();
117 openssl_locks
= git__calloc(num_locks
, sizeof(git_mutex
));
118 GITERR_CHECK_ALLOC(openssl_locks
);
120 for (i
= 0; i
< num_locks
; i
++) {
121 if (git_mutex_init(&openssl_locks
[i
]) != 0) {
122 giterr_set(GITERR_SSL
, "failed to initialize openssl locks");
127 CRYPTO_set_locking_callback(openssl_locking_function
);
128 git__on_shutdown(shutdown_ssl_locking
);
131 giterr_set(GITERR_THREAD
, "libgit2 as not built with threads");
135 giterr_set(GITERR_SSL
, "libgit2 was not built with OpenSSL support");
141 * Handle the global state with TLS
143 * If libgit2 is built with GIT_THREADS enabled,
144 * the `git_libgit2_init()` function must be called
145 * before calling any other function of the library.
147 * This function allocates a TLS index (using pthreads
148 * or the native Win32 API) to store the global state
149 * on a per-thread basis.
151 * Any internal method that requires global state will
152 * then call `git__global_state()` which returns a pointer
153 * to the global state structure; this pointer is lazily
154 * allocated on each thread.
156 * Before shutting down the library, the
157 * `git_libgit2_shutdown` method must be called to free
158 * the previously reserved TLS index.
160 * If libgit2 is built without threading support, the
161 * `git__global_statestate()` call returns a pointer to a single,
162 * statically allocated global state. The `git_thread_`
163 * functions are not available in that case.
167 * `git_libgit2_init()` allows subsystems to perform global setup,
168 * which may take place in the global scope. An explicit memory
169 * fence exists at the exit of `git_libgit2_init()`. Without this,
170 * CPU cores are free to reorder cache invalidation of `_tls_init`
171 * before cache invalidation of the subsystems' newly written global
174 #if defined(GIT_THREADS) && defined(GIT_WIN32)
176 static DWORD _tls_index
;
177 static volatile LONG _mutex
= 0;
179 static int synchronized_threads_init(void)
183 _tls_index
= TlsAlloc();
184 if (git_mutex_init(&git__mwindow_mutex
))
187 /* Initialize any other subsystems that have global state */
188 if ((error
= git_hash_global_init()) >= 0)
189 error
= git_sysdir_global_init();
191 win32_pthread_initialize();
196 int git_libgit2_init(void)
201 while (InterlockedCompareExchange(&_mutex
, 1, 0)) { Sleep(0); }
203 /* Only do work on a 0 -> 1 transition of the refcount */
204 if ((ret
= git_atomic_inc(&git__n_inits
)) == 1) {
205 if (synchronized_threads_init() < 0)
210 InterlockedExchange(&_mutex
, 0);
215 static void synchronized_threads_shutdown(void)
217 /* Shut down any subsystems that have global state */
220 git_mutex_free(&git__mwindow_mutex
);
223 int git_libgit2_shutdown(void)
228 while (InterlockedCompareExchange(&_mutex
, 1, 0)) { Sleep(0); }
230 /* Only do work on a 1 -> 0 transition of the refcount */
231 if ((ret
= git_atomic_dec(&git__n_inits
)) == 0)
232 synchronized_threads_shutdown();
235 InterlockedExchange(&_mutex
, 0);
240 git_global_st
*git__global_state(void)
244 assert(git_atomic_get(&git__n_inits
) > 0);
246 if ((ptr
= TlsGetValue(_tls_index
)) != NULL
)
249 ptr
= git__malloc(sizeof(git_global_st
));
253 memset(ptr
, 0x0, sizeof(git_global_st
));
254 TlsSetValue(_tls_index
, ptr
);
258 #elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
260 static pthread_key_t _tls_key
;
261 static pthread_once_t _once_init
= PTHREAD_ONCE_INIT
;
264 static void cb__free_status(void *st
)
266 git_global_st
*state
= (git_global_st
*) st
;
267 git__free(state
->error_t
.message
);
272 static void init_once(void)
274 if ((init_error
= git_mutex_init(&git__mwindow_mutex
)) != 0)
276 pthread_key_create(&_tls_key
, &cb__free_status
);
279 /* Initialize any other subsystems that have global state */
280 if ((init_error
= git_hash_global_init()) >= 0)
281 init_error
= git_sysdir_global_init();
283 /* OpenSSL needs to be initialized from the main thread */
289 int git_libgit2_init(void)
293 pthread_once(&_once_init
, init_once
);
294 ret
= git_atomic_inc(&git__n_inits
);
296 return init_error
? init_error
: ret
;
299 int git_libgit2_shutdown(void)
302 pthread_once_t new_once
= PTHREAD_ONCE_INIT
;
305 if ((ret
= git_atomic_dec(&git__n_inits
)) > 0)
308 /* Shut down any subsystems that have global state */
311 ptr
= pthread_getspecific(_tls_key
);
312 pthread_setspecific(_tls_key
, NULL
);
315 pthread_key_delete(_tls_key
);
316 git_mutex_free(&git__mwindow_mutex
);
317 _once_init
= new_once
;
322 git_global_st
*git__global_state(void)
326 assert(git_atomic_get(&git__n_inits
) > 0);
328 if ((ptr
= pthread_getspecific(_tls_key
)) != NULL
)
331 ptr
= git__malloc(sizeof(git_global_st
));
335 memset(ptr
, 0x0, sizeof(git_global_st
));
336 pthread_setspecific(_tls_key
, ptr
);
342 static git_global_st __state
;
344 int git_libgit2_init(void)
346 static int ssl_inited
= 0;
353 return git_atomic_inc(&git__n_inits
);
356 int git_libgit2_shutdown(void)
360 /* Shut down any subsystems that have global state */
361 if (ret
= git_atomic_dec(&git__n_inits
))
367 git_global_st
*git__global_state(void)
372 #endif /* GIT_THREADS */