summaryrefslogtreecommitdiff
path: root/src/errors.c
diff options
context:
space:
mode:
authorShawn O. Pearce <spearce@spearce.org>2008-12-30 21:49:38 -0800
committerShawn O. Pearce <spearce@spearce.org>2008-12-30 21:56:11 -0800
commita1d34bc000cee6d72c3b5e329faa58424641611f (patch)
tree89d3150640c0ed5b386bc8113ac8999b20371ece /src/errors.c
parentd74679498086d0fc2293dceb59155c696b11b86c (diff)
downloadlibgit2-a1d34bc000cee6d72c3b5e329faa58424641611f.tar.gz
Support building on Mac OS X by using pthread_getspecific for TLS
The Mach-O format does not permit gcc to implement the __thread TLS specification, so we must instead emulate it using a single int cell allocated from memory and stored inside of the thread specific data associated with the current pthread. What makes this tricky is git_errno must be a valid lvalue, so we really need to return a pointer to the caller and deference it as part of the git_errno macro. The GCC-specific __attribute__((constructor)) extension is used to ensure the pthread_key_t is allocated before any Git functions are executed in the library, as this is necessary to access our thread specific storage. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'src/errors.c')
-rw-r--r--src/errors.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/errors.c b/src/errors.c
index b3e014dd4..75636f477 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -1,9 +1,32 @@
#include "common.h"
#include "thread-utils.h" /* for GIT_TLS */
+#if defined(GIT_TLS)
/* compile-time constant initialization required */
GIT_TLS int git_errno = 0;
+#elif defined(GIT_HAS_PTHREAD)
+
+static pthread_key_t errno_key;
+
+static void init_errno(void) __attribute__((constructor));
+static void init_errno(void)
+{
+ pthread_key_create(&errno_key, free);
+}
+
+int *git__errno_storage(void)
+{
+ int *e = pthread_getspecific(errno_key);
+ if (!e) {
+ e = calloc(1, sizeof(*e));
+ pthread_setspecific(errno_key, e);
+ }
+ return e;
+}
+
+#endif
+
static struct {
int num;
const char *str;