]>
Commit | Line | Data |
---|---|---|
a15c550d | 1 | /* |
5e0de328 | 2 | * Copyright (C) 2009-2012 the libgit2 contributors |
a15c550d VM |
3 | * |
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. | |
6 | */ | |
7 | #include "common.h" | |
8 | #include "global.h" | |
9 | #include "git2/threads.h" | |
10 | #include "thread-utils.h" | |
11 | ||
8cef828d CMN |
12 | |
13 | git_mutex git__mwindow_mutex; | |
14 | ||
a15c550d VM |
15 | /** |
16 | * Handle the global state with TLS | |
17 | * | |
18 | * If libgit2 is built with GIT_THREADS enabled, | |
19 | * the `git_threads_init()` function must be called | |
20 | * before calling any other function of the library. | |
21 | * | |
22 | * This function allocates a TLS index (using pthreads | |
23 | * or the native Win32 API) to store the global state | |
24 | * on a per-thread basis. | |
25 | * | |
26 | * Any internal method that requires global state will | |
27 | * then call `git__global_state()` which returns a pointer | |
28 | * to the global state structure; this pointer is lazily | |
29 | * allocated on each thread. | |
30 | * | |
31 | * Before shutting down the library, the | |
32 | * `git_threads_shutdown` method must be called to free | |
33 | * the previously reserved TLS index. | |
34 | * | |
35 | * If libgit2 is built without threading support, the | |
36 | * `git__global_statestate()` call returns a pointer to a single, | |
37 | * statically allocated global state. The `git_thread_` | |
38 | * functions are not available in that case. | |
39 | */ | |
40 | ||
41 | #if defined(GIT_THREADS) && defined(GIT_WIN32) | |
42 | ||
43 | static DWORD _tls_index; | |
44 | static int _tls_init = 0; | |
45 | ||
46 | void git_threads_init(void) | |
47 | { | |
48 | if (_tls_init) | |
49 | return; | |
50 | ||
51 | _tls_index = TlsAlloc(); | |
52 | _tls_init = 1; | |
8cef828d | 53 | git_mutex_init(&git__mwindow_mutex); |
a15c550d VM |
54 | } |
55 | ||
56 | void git_threads_shutdown(void) | |
57 | { | |
58 | TlsFree(_tls_index); | |
59 | _tls_init = 0; | |
8cef828d | 60 | git_mutex_free(&git__mwindow_mutex); |
a15c550d VM |
61 | } |
62 | ||
63 | git_global_st *git__global_state(void) | |
64 | { | |
65 | void *ptr; | |
66 | ||
93b5fabc VM |
67 | assert(_tls_init); |
68 | ||
a15c550d VM |
69 | if ((ptr = TlsGetValue(_tls_index)) != NULL) |
70 | return ptr; | |
71 | ||
2bc8fa02 | 72 | ptr = git__malloc(sizeof(git_global_st)); |
a15c550d VM |
73 | if (!ptr) |
74 | return NULL; | |
75 | ||
76 | memset(ptr, 0x0, sizeof(git_global_st)); | |
77 | TlsSetValue(_tls_index, ptr); | |
78 | return ptr; | |
79 | } | |
80 | ||
81 | #elif defined(GIT_THREADS) && defined(_POSIX_THREADS) | |
82 | ||
83 | static pthread_key_t _tls_key; | |
84 | static int _tls_init = 0; | |
85 | ||
86 | static void cb__free_status(void *st) | |
87 | { | |
2bc8fa02 | 88 | git__free(st); |
a15c550d VM |
89 | } |
90 | ||
91 | void git_threads_init(void) | |
92 | { | |
93 | if (_tls_init) | |
94 | return; | |
95 | ||
96 | pthread_key_create(&_tls_key, &cb__free_status); | |
97 | _tls_init = 1; | |
98 | } | |
99 | ||
100 | void git_threads_shutdown(void) | |
101 | { | |
102 | pthread_key_delete(_tls_key); | |
103 | _tls_init = 0; | |
104 | } | |
105 | ||
106 | git_global_st *git__global_state(void) | |
107 | { | |
108 | void *ptr; | |
109 | ||
93b5fabc VM |
110 | assert(_tls_init); |
111 | ||
a15c550d VM |
112 | if ((ptr = pthread_getspecific(_tls_key)) != NULL) |
113 | return ptr; | |
114 | ||
2bc8fa02 | 115 | ptr = git__malloc(sizeof(git_global_st)); |
a15c550d VM |
116 | if (!ptr) |
117 | return NULL; | |
118 | ||
119 | memset(ptr, 0x0, sizeof(git_global_st)); | |
120 | pthread_setspecific(_tls_key, ptr); | |
121 | return ptr; | |
122 | } | |
123 | ||
124 | #else | |
125 | ||
126 | static git_global_st __state; | |
127 | ||
128 | void git_threads_init(void) | |
129 | { | |
130 | /* noop */ | |
131 | } | |
132 | ||
133 | void git_threads_shutdown(void) | |
134 | { | |
135 | /* noop */ | |
136 | } | |
137 | ||
138 | git_global_st *git__global_state(void) | |
139 | { | |
140 | return &__state; | |
141 | } | |
142 | ||
143 | #endif /* GIT_THREADS */ |