2 * Copyright (C) 2009-2012 the libgit2 contributors
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.
10 #include "git2/threads.h"
11 #include "thread-utils.h"
14 git_mutex git__mwindow_mutex
;
17 * Handle the global state with TLS
19 * If libgit2 is built with GIT_THREADS enabled,
20 * the `git_threads_init()` function must be called
21 * before calling any other function of the library.
23 * This function allocates a TLS index (using pthreads
24 * or the native Win32 API) to store the global state
25 * on a per-thread basis.
27 * Any internal method that requires global state will
28 * then call `git__global_state()` which returns a pointer
29 * to the global state structure; this pointer is lazily
30 * allocated on each thread.
32 * Before shutting down the library, the
33 * `git_threads_shutdown` method must be called to free
34 * the previously reserved TLS index.
36 * If libgit2 is built without threading support, the
37 * `git__global_statestate()` call returns a pointer to a single,
38 * statically allocated global state. The `git_thread_`
39 * functions are not available in that case.
43 * `git_threads_init()` allows subsystems to perform global setup,
44 * which may take place in the global scope. An explicit memory
45 * fence exists at the exit of `git_threads_init()`. Without this,
46 * CPU cores are free to reorder cache invalidation of `_tls_init`
47 * before cache invalidation of the subsystems' newly written global
50 #if defined(GIT_THREADS) && defined(GIT_WIN32)
52 static DWORD _tls_index
;
53 static int _tls_init
= 0;
55 int git_threads_init(void)
62 _tls_index
= TlsAlloc();
63 git_mutex_init(&git__mwindow_mutex
);
65 /* Initialize any other subsystems that have global state */
66 if ((error
= git_hash_global_init()) >= 0)
77 void git_threads_shutdown(void)
81 git_mutex_free(&git__mwindow_mutex
);
83 /* Shut down any subsystems that have global state */
84 git_hash_global_shutdown();
87 git_global_st
*git__global_state(void)
93 if ((ptr
= TlsGetValue(_tls_index
)) != NULL
)
96 ptr
= git__malloc(sizeof(git_global_st
));
100 memset(ptr
, 0x0, sizeof(git_global_st
));
101 TlsSetValue(_tls_index
, ptr
);
105 #elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
107 static pthread_key_t _tls_key
;
108 static int _tls_init
= 0;
110 static void cb__free_status(void *st
)
115 int git_threads_init(void)
122 git_mutex_init(&git__mwindow_mutex
);
123 pthread_key_create(&_tls_key
, &cb__free_status
);
125 /* Initialize any other subsystems that have global state */
126 if ((error
= git_hash_global_init()) >= 0)
134 void git_threads_shutdown(void)
136 pthread_key_delete(_tls_key
);
138 git_mutex_free(&git__mwindow_mutex
);
140 /* Shut down any subsystems that have global state */
141 git_hash_global_shutdown();
144 git_global_st
*git__global_state(void)
150 if ((ptr
= pthread_getspecific(_tls_key
)) != NULL
)
153 ptr
= git__malloc(sizeof(git_global_st
));
157 memset(ptr
, 0x0, sizeof(git_global_st
));
158 pthread_setspecific(_tls_key
, ptr
);
164 static git_global_st __state
;
166 int git_threads_init(void)
172 void git_threads_shutdown(void)
177 git_global_st
*git__global_state(void)
182 #endif /* GIT_THREADS */