forked from libgit2/libgit2
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/custom-tls-for-external-library' into libgit-ne…
…xt-1.7.2
- Loading branch information
Showing
9 changed files
with
479 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* Copyright (C) the libgit2 contributors. All rights reserved. | ||
* | ||
* This file is part of libgit2, distributed under the GNU GPL v2 with | ||
* a Linking Exception. For full terms see the included COPYING file. | ||
*/ | ||
#ifndef INCLUDE_sys_custom_tls_h__ | ||
#define INCLUDE_sys_custom_tls_h__ | ||
|
||
#include "git2/common.h" | ||
|
||
GIT_BEGIN_DECL | ||
|
||
/** | ||
* Used to retrieve a pointer from a user of the library to pass to a newly | ||
* created internal libgit2 thread. This should allow users of the library to | ||
* establish a context that spans an internally threaded operation. This can | ||
* useful for libraries that leverage callbacks used in an internally threaded | ||
* routine. | ||
*/ | ||
typedef void *GIT_CALLBACK(git_retrieve_tls_for_internal_thread_cb)(void); | ||
|
||
/** | ||
* This callback will be called when a thread is exiting so that a user | ||
* of the library can clean up their thread local storage. | ||
*/ | ||
typedef void GIT_CALLBACK(git_set_tls_on_internal_thread_cb)(void *payload); | ||
|
||
/** | ||
* This callback will be called when a thread is exiting so that a user | ||
* of the library can clean up their thread local storage. | ||
*/ | ||
typedef void GIT_CALLBACK(git_teardown_tls_on_internal_thread_cb)(void); | ||
|
||
/** | ||
* Sets the callbacks for custom thread local storage used by internally | ||
* created libgit2 threads. This allows users of the library an opportunity | ||
* to set thread local storage for internal threads based on the creating | ||
* thread. | ||
* | ||
* @param retrieve_storage_for_internal_thread Used to retrieve a pointer on | ||
* a thread before spawning child | ||
* threads. This pointer will be | ||
* passed to set_storage_on_thread | ||
* in the newly spawned threads. | ||
* @param set_storage_on_thread When a thread is spawned internally in libgit2, | ||
* whatever pointer was retrieved in the calling | ||
* thread by retrieve_storage_for_internal_thread | ||
* will be passed to this callback in the newly | ||
* spawned thread. | ||
* @param teardown_storage_on_thread Before an internally spawned thread exits, | ||
* this method will be called allowing a user | ||
* of the library an opportunity to clean up | ||
* any thread local storage they set up on | ||
* the internal thread. | ||
* @return 0 on success, or an error code. (use git_error_last for information | ||
* about the error) | ||
*/ | ||
GIT_EXTERN(int) git_custom_tls_set_callbacks( | ||
git_retrieve_tls_for_internal_thread_cb retrieve_storage_for_internal_thread, | ||
git_set_tls_on_internal_thread_cb set_storage_on_thread, | ||
git_teardown_tls_on_internal_thread_cb teardown_storage_on_thread); | ||
|
||
GIT_END_DECL | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* | ||
* Copyright (C) the libgit2 contributors. All rights reserved. | ||
* | ||
* This file is part of libgit2, distributed under the GNU GPL v2 with | ||
* a Linking Exception. For full terms see the included COPYING file. | ||
*/ | ||
|
||
#include "runtime.h" | ||
|
||
#ifdef GIT_THREADS | ||
|
||
#ifdef GIT_WIN32 | ||
# include "win32/thread.h" | ||
#else | ||
# include "unix/pthread.h" | ||
#endif | ||
|
||
struct git_custom_tls_callbacks { | ||
git_retrieve_tls_for_internal_thread_cb retrieve_storage_for_internal_thread; | ||
|
||
git_set_tls_on_internal_thread_cb set_storage_on_thread; | ||
|
||
git_teardown_tls_on_internal_thread_cb teardown_storage_on_thread; | ||
|
||
git_rwlock lock; | ||
}; | ||
|
||
struct git_custom_tls_callbacks git__custom_tls = { 0, 0, 0 }; | ||
|
||
static void git_custom_tls_global_shutdown(void) | ||
{ | ||
if (git_rwlock_wrlock(&git__custom_tls.lock) < 0) | ||
return; | ||
|
||
git__custom_tls.retrieve_storage_for_internal_thread = 0; | ||
git__custom_tls.set_storage_on_thread = 0; | ||
git__custom_tls.teardown_storage_on_thread = 0; | ||
|
||
git_rwlock_wrunlock(&git__custom_tls.lock); | ||
git_rwlock_free(&git__custom_tls.lock); | ||
} | ||
|
||
int git_custom_tls__global_init(void) | ||
{ | ||
if (git_rwlock_init(&git__custom_tls.lock) < 0) | ||
return -1; | ||
|
||
return git_runtime_shutdown_register(git_custom_tls_global_shutdown); | ||
} | ||
|
||
int git_custom_tls_set_callbacks( | ||
git_retrieve_tls_for_internal_thread_cb retrieve_storage_for_internal_thread, | ||
git_set_tls_on_internal_thread_cb set_storage_on_thread, | ||
git_teardown_tls_on_internal_thread_cb teardown_storage_on_thread) | ||
{ | ||
/* We want to ensure that all callbacks are set or not set in totality. | ||
* It does not make sense to have a subset of callbacks set. | ||
*/ | ||
assert((retrieve_storage_for_internal_thread && set_storage_on_thread && | ||
teardown_storage_on_thread) || !(retrieve_storage_for_internal_thread && | ||
set_storage_on_thread && teardown_storage_on_thread)); | ||
|
||
if (git_rwlock_wrlock(&git__custom_tls.lock) < 0) { | ||
git_error_set(GIT_ERROR_OS, "failed to lock custom thread local storage"); | ||
return -1; | ||
} | ||
|
||
git__custom_tls.retrieve_storage_for_internal_thread = | ||
retrieve_storage_for_internal_thread; | ||
git__custom_tls.set_storage_on_thread = | ||
set_storage_on_thread; | ||
git__custom_tls.teardown_storage_on_thread = | ||
teardown_storage_on_thread; | ||
|
||
git_rwlock_wrunlock(&git__custom_tls.lock); | ||
return 0; | ||
} | ||
|
||
int git_custom_tls__init(git_custom_tls *tls) | ||
{ | ||
if (git_rwlock_rdlock(&git__custom_tls.lock) < 0) { | ||
git_error_set(GIT_ERROR_OS, "failed to lock custom thread local storage"); | ||
return -1; | ||
} | ||
|
||
/* We try to ensure that all 3 callbacks must be set or not set. | ||
* It would not make sense to have a subset of the callbacks set. | ||
*/ | ||
if (!git__custom_tls.retrieve_storage_for_internal_thread) { | ||
tls->set_storage_on_thread = NULL; | ||
tls->teardown_storage_on_thread = NULL; | ||
tls->payload = NULL; | ||
} else { | ||
/* We set these on a struct so that if for whatever reason the opts are changed | ||
* at least the opts will remain consistent for any given thread already in | ||
* motion. | ||
*/ | ||
tls->set_storage_on_thread = git__custom_tls.set_storage_on_thread; | ||
tls->teardown_storage_on_thread = git__custom_tls.teardown_storage_on_thread; | ||
tls->payload = git__custom_tls.retrieve_storage_for_internal_thread(); | ||
} | ||
|
||
git_rwlock_rdunlock(&git__custom_tls.lock); | ||
return 0; | ||
} | ||
|
||
#else | ||
|
||
int git_custom_tls__global_init(void) | ||
{ | ||
return 0; | ||
} | ||
|
||
int git_custom_tls_set_callbacks( | ||
git_retrieve_tls_for_internal_thread_cb retrieve_storage_for_internal_thread, | ||
git_set_tls_on_internal_thread_cb set_storage_on_thread, | ||
git_teardown_tls_on_internal_thread_cb teardown_storage_on_thread) | ||
{ | ||
return 0; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Copyright (C) the libgit2 contributors. All rights reserved. | ||
* | ||
* This file is part of libgit2, distributed under the GNU GPL v2 with | ||
* a Linking Exception. For full terms see the included COPYING file. | ||
*/ | ||
#ifndef INCLUDE_custom_tls_h__ | ||
#define INCLUDE_custom_tls_h__ | ||
|
||
#include "git2/sys/custom_tls.h" | ||
|
||
int git_custom_tls__global_init(void); | ||
|
||
#ifdef GIT_THREADS | ||
|
||
typedef struct { | ||
git_set_tls_on_internal_thread_cb set_storage_on_thread; | ||
|
||
git_teardown_tls_on_internal_thread_cb teardown_storage_on_thread; | ||
|
||
/** | ||
* payload should be set on the thread that is spawning the child thread. | ||
* This payload will be passed to set_storage_on_thread | ||
*/ | ||
void *payload; | ||
} git_custom_tls; | ||
|
||
int git_custom_tls__init(git_custom_tls *tls); | ||
|
||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
* Copyright (C) the libgit2 contributors. All rights reserved. | ||
* | ||
* This file is part of libgit2, distributed under the GNU GPL v2 with | ||
* a Linking Exception. For full terms see the included COPYING file. | ||
*/ | ||
|
||
#include "pthread.h" | ||
#include "thread.h" | ||
#include "runtime.h" | ||
|
||
git_tlsdata_key thread_handle; | ||
|
||
static void git_threads_global_shutdown(void) { | ||
git_tlsdata_dispose(thread_handle); | ||
} | ||
|
||
int git_threads_global_init(void) { | ||
int error = git_tlsdata_init(&thread_handle, NULL); | ||
if (error != 0) { | ||
return error; | ||
} | ||
|
||
return git_runtime_shutdown_register(git_threads_global_shutdown); | ||
} | ||
|
||
static void *git_unix__threadproc(void *arg) | ||
{ | ||
void *result; | ||
int error; | ||
git_thread *thread = arg; | ||
|
||
error = git_tlsdata_set(thread_handle, thread); | ||
if (error != 0) { | ||
return NULL; | ||
} | ||
|
||
if (thread->tls.set_storage_on_thread) { | ||
thread->tls.set_storage_on_thread(thread->tls.payload); | ||
} | ||
|
||
result = thread->proc(thread->param); | ||
|
||
if (thread->tls.teardown_storage_on_thread) { | ||
thread->tls.teardown_storage_on_thread(); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
int git_thread_create( | ||
git_thread *thread, | ||
void *(*start_routine)(void*), | ||
void *arg) | ||
{ | ||
|
||
thread->proc = start_routine; | ||
thread->param = arg; | ||
if (git_custom_tls__init(&thread->tls) < 0) | ||
return -1; | ||
|
||
return pthread_create(&thread->thread, NULL, git_unix__threadproc, thread); | ||
} | ||
|
||
void git_thread_exit(void *value) | ||
{ | ||
git_thread *thread = git_tlsdata_get(thread_handle); | ||
|
||
if (thread && thread->tls.teardown_storage_on_thread) | ||
thread->tls.teardown_storage_on_thread(); | ||
|
||
return pthread_exit(value); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.