Index: lib/lsan/lsan_common.cc =================================================================== --- lib/lsan/lsan_common.cc +++ lib/lsan/lsan_common.cc @@ -32,18 +32,6 @@ // also to protect the global list of root regions. BlockingMutex global_mutex(LINKER_INITIALIZED); -__attribute__((tls_model("initial-exec"))) -THREADLOCAL int disable_counter; -bool DisabledInThisThread() { return disable_counter > 0; } -void DisableInThisThread() { disable_counter++; } -void EnableInThisThread() { - if (!disable_counter && common_flags()->detect_leaks) { - Report("Unmatched call to __lsan_enable().\n"); - Die(); - } - disable_counter--; -} - Flags lsan_flags; void Flags::SetDefaults() { Index: lib/lsan/lsan_common_linux.cc =================================================================== --- lib/lsan/lsan_common_linux.cc +++ lib/lsan/lsan_common_linux.cc @@ -34,6 +34,18 @@ return LibraryNameIs(full_name, kLinkerName); } +__attribute__((tls_model("initial-exec"))) +THREADLOCAL int disable_counter; +bool DisabledInThisThread() { return disable_counter > 0; } +void DisableInThisThread() { disable_counter++; } +void EnableInThisThread() { + if (!disable_counter && common_flags()->detect_leaks) { + Report("Unmatched call to __lsan_enable().\n"); + Die(); + } + disable_counter--; +} + void InitializePlatformSpecificModules() { ListOfModules modules; modules.init(); Index: lib/lsan/lsan_common_mac.cc =================================================================== --- lib/lsan/lsan_common_mac.cc +++ lib/lsan/lsan_common_mac.cc @@ -16,8 +16,56 @@ #include "lsan_common.h" #if CAN_SANITIZE_LEAKS && SANITIZER_MAC + +#include +#include + namespace __lsan { +static pthread_key_t key; +static pthread_once_t key_once = PTHREAD_ONCE_INIT; + +static void make_tls_key() { + pthread_key_create(&key, NULL); +} + +static int *get_tls_val(bool allocate) { + pthread_once(&key_once, make_tls_key); + + int *ptr = (int *) pthread_getspecific(key); + if (ptr == NULL && allocate) { + ptr = (int *) malloc(sizeof(0)); + *ptr = 0; + } + + return ptr; +} + +bool DisabledInThisThread() { + int *disable_counter = get_tls_val(false); + return disable_counter ? *disable_counter > 0 : false; +} + +void DisableInThisThread() { + int *disable_counter = get_tls_val(true); + + ++*disable_counter; + pthread_setspecific(key, disable_counter); +} + +void EnableInThisThread() { + int *disable_counter = get_tls_val(true); + if (!*disable_counter && common_flags()->detect_leaks) { + Report("Unmatched call to __lsan_enable().\n"); + Die(); + } + + if (common_flags()->detect_leaks) { + --*disable_counter; + pthread_setspecific(key, disable_counter); + } +} + void InitializePlatformSpecificModules() {} // Scans global variables for heap pointers.