Index: third_party/tcmalloc/chromium/src/maybe_threads.cc |
diff --git a/third_party/tcmalloc/chromium/src/maybe_threads.cc b/third_party/tcmalloc/chromium/src/maybe_threads.cc |
index cda1d630328c73e92cccb6cda4bd520da3733eba..15c8a23dcb3509549ef6b45531f2418e988a3cf5 100644 |
--- a/third_party/tcmalloc/chromium/src/maybe_threads.cc |
+++ b/third_party/tcmalloc/chromium/src/maybe_threads.cc |
@@ -39,6 +39,7 @@ |
#include "config.h" |
#include <assert.h> |
#include <string.h> // for memcmp |
+#include <stdio.h> // for __isthreaded on FreeBSD |
// We don't actually need strings. But including this header seems to |
// stop the compiler trying to short-circuit our pthreads existence |
// tests and claiming that the address of a function is always |
@@ -98,9 +99,28 @@ int perftools_pthread_setspecific(pthread_key_t key, void *val) { |
} |
} |
+ |
static pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT; |
int perftools_pthread_once(pthread_once_t *ctl, |
void (*init_routine) (void)) { |
+#ifdef __FreeBSD__ |
+ // On __FreeBSD__, calling pthread_once on a system that is not |
+ // linked with -pthread is silently a noop. :-( Luckily, we have a |
+ // workaround: FreeBSD exposes __isthreaded in <stdio.h>, which is |
+ // set to 1 when the first thread is spawned. So on those systems, |
+ // we can use our own separate pthreads-once mechanism, which is |
+ // used until __isthreaded is 1 (which will never be true if the app |
+ // is not linked with -pthread). |
+ static bool pthread_once_ran_before_threads = false; |
+ if (pthread_once_ran_before_threads) { |
+ return 0; |
+ } |
+ if (!__isthreaded) { |
+ init_routine(); |
+ pthread_once_ran_before_threads = true; |
+ return 0; |
+ } |
+#endif |
if (pthread_once) { |
return pthread_once(ctl, init_routine); |
} else { |