]> git.proxmox.com Git - libgit2.git/blame - src/global.c
Merge pull request #968 from arrbee/diff-support-typechange
[libgit2.git] / src / global.c
CommitLineData
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
13git_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
43static DWORD _tls_index;
44static int _tls_init = 0;
45
46void 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
56void 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
63git_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
83static pthread_key_t _tls_key;
84static int _tls_init = 0;
85
86static void cb__free_status(void *st)
87{
2bc8fa02 88 git__free(st);
a15c550d
VM
89}
90
91void 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
100void git_threads_shutdown(void)
101{
102 pthread_key_delete(_tls_key);
103 _tls_init = 0;
104}
105
106git_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
126static git_global_st __state;
127
128void git_threads_init(void)
129{
130 /* noop */
131}
132
133void git_threads_shutdown(void)
134{
135 /* noop */
136}
137
138git_global_st *git__global_state(void)
139{
140 return &__state;
141}
142
143#endif /* GIT_THREADS */