| line | stmt | bran | cond | sub | pod | time | code | 
| 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 |  |  |  |  |  |  |  | 
| 34 | 1 |  |  |  |  |  | static void threadstate_dispose(git_threadstate *threadstate) | 
| 35 |  |  |  |  |  |  | { | 
| 36 | 1 | 50 |  |  |  |  | if (!threadstate) | 
| 37 | 0 |  |  |  |  |  | return; | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 1 | 50 |  |  |  |  | if (threadstate->error_t.message != git_str__initstr) | 
| 40 | 1 |  |  |  |  |  | git__free(threadstate->error_t.message); | 
| 41 | 1 |  |  |  |  |  | threadstate->error_t.message = NULL; | 
| 42 |  |  |  |  |  |  | } | 
| 43 |  |  |  |  |  |  |  | 
| 44 | 1 |  |  |  |  |  | static void GIT_SYSTEM_CALL threadstate_free(void *threadstate) | 
| 45 |  |  |  |  |  |  | { | 
| 46 | 1 |  |  |  |  |  | threadstate_dispose(threadstate); | 
| 47 | 1 |  |  |  |  |  | git__free(threadstate); | 
| 48 | 1 |  |  |  |  |  | } | 
| 49 |  |  |  |  |  |  |  | 
| 50 | 0 |  |  |  |  |  | static void git_threadstate_global_shutdown(void) | 
| 51 |  |  |  |  |  |  | { | 
| 52 |  |  |  |  |  |  | git_threadstate *threadstate; | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 0 |  |  |  |  |  | threadstate = git_tlsdata_get(tls_key); | 
| 55 | 0 |  |  |  |  |  | git_tlsdata_set(tls_key, NULL); | 
| 56 |  |  |  |  |  |  |  | 
| 57 | 0 |  |  |  |  |  | threadstate_dispose(threadstate); | 
| 58 | 0 |  |  |  |  |  | git__free(threadstate); | 
| 59 |  |  |  |  |  |  |  | 
| 60 | 0 |  |  |  |  |  | git_tlsdata_dispose(tls_key); | 
| 61 | 0 |  |  |  |  |  | } | 
| 62 |  |  |  |  |  |  |  | 
| 63 | 87 |  |  |  |  |  | int git_threadstate_global_init(void) | 
| 64 |  |  |  |  |  |  | { | 
| 65 | 87 | 50 |  |  |  |  | if (git_tlsdata_init(&tls_key, &threadstate_free) != 0) | 
| 66 | 0 |  |  |  |  |  | return -1; | 
| 67 |  |  |  |  |  |  |  | 
| 68 | 87 |  |  |  |  |  | return git_runtime_shutdown_register(git_threadstate_global_shutdown); | 
| 69 |  |  |  |  |  |  | } | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 35418 |  |  |  |  |  | git_threadstate *git_threadstate_get(void) | 
| 72 |  |  |  |  |  |  | { | 
| 73 |  |  |  |  |  |  | git_threadstate *threadstate; | 
| 74 |  |  |  |  |  |  |  | 
| 75 | 35418 | 100 |  |  |  |  | if ((threadstate = git_tlsdata_get(tls_key)) != NULL) | 
| 76 | 35387 |  |  |  |  |  | return threadstate; | 
| 77 |  |  |  |  |  |  |  | 
| 78 | 62 |  |  |  |  |  | if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL || | 
| 79 | 31 |  |  |  |  |  | git_str_init(&threadstate->error_buf, 0) < 0) | 
| 80 | 0 |  |  |  |  |  | return NULL; | 
| 81 |  |  |  |  |  |  |  | 
| 82 | 31 |  |  |  |  |  | git_tlsdata_set(tls_key, threadstate); | 
| 83 | 31 |  |  |  |  |  | return threadstate; | 
| 84 |  |  |  |  |  |  | } |