1 /* 2 * Copyright (C) the libgit2 contributors. All rights reserved. 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 8 #include "threadstate.h" 9 #include "runtime.h" 10 11 /** 12 * Handle the thread-local state 13 * 14 * `git_threadstate_global_init` will be called as part 15 * of `git_libgit2_init` (which itself must be called 16 * before calling any other function in the library). 17 * 18 * This function allocates a TLS index to store the per- 19 * thread state. 20 * 21 * Any internal method that requires thread-local state 22 * will then call `git_threadstate_get()` which returns a 23 * pointer to the thread-local state structure; this 24 * structure is lazily allocated on each thread. 25 * 26 * This mechanism will register a shutdown handler 27 * (`git_threadstate_global_shutdown`) which will free the 28 * TLS index. This shutdown handler will be called by 29 * `git_libgit2_shutdown`. 30 */ 31 32 static git_tlsdata_key tls_key; 33 threadstate_dispose(git_threadstate * threadstate)34static void threadstate_dispose(git_threadstate *threadstate) 35 { 36 if (!threadstate) 37 return; 38 39 git__free(threadstate->error_t.message); 40 threadstate->error_t.message = NULL; 41 } 42 threadstate_free(void * threadstate)43static void GIT_SYSTEM_CALL threadstate_free(void *threadstate) 44 { 45 threadstate_dispose(threadstate); 46 git__free(threadstate); 47 } 48 git_threadstate_global_shutdown(void)49static void git_threadstate_global_shutdown(void) 50 { 51 git_threadstate *threadstate; 52 53 threadstate = git_tlsdata_get(tls_key); 54 git_tlsdata_set(tls_key, NULL); 55 56 threadstate_dispose(threadstate); 57 git__free(threadstate); 58 59 git_tlsdata_dispose(tls_key); 60 } 61 git_threadstate_global_init(void)62int git_threadstate_global_init(void) 63 { 64 if (git_tlsdata_init(&tls_key, &threadstate_free) != 0) 65 return -1; 66 67 return git_runtime_shutdown_register(git_threadstate_global_shutdown); 68 } 69 git_threadstate_get(void)70git_threadstate *git_threadstate_get(void) 71 { 72 git_threadstate *threadstate; 73 74 if ((threadstate = git_tlsdata_get(tls_key)) != NULL) 75 return threadstate; 76 77 if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL || 78 git_buf_init(&threadstate->error_buf, 0) < 0) 79 return NULL; 80 81 git_tlsdata_set(tls_key, threadstate); 82 return threadstate; 83 } 84