Index: third_party/tcmalloc/chromium/src/thread_cache.cc |
=================================================================== |
--- third_party/tcmalloc/chromium/src/thread_cache.cc (revision 124832) |
+++ third_party/tcmalloc/chromium/src/thread_cache.cc (working copy) |
@@ -32,7 +32,6 @@ |
#include <config.h> |
#include "thread_cache.h" |
-#include <errno.h> |
#include <string.h> // for memcpy |
#include <algorithm> // for max, min |
#include "base/commandlineflags.h" // for SpinLockHolder |
@@ -47,9 +46,8 @@ |
EnvToInt64("TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES", |
kDefaultOverallThreadCacheSize), |
"Bound on the total amount of bytes allocated to " |
- "thread caches. This bound is not strict, so it is possible " |
- "for the cache to go over this bound in certain circumstances. " |
- "Maximum value of this flag is capped to 1 GB."); |
+ "thread caches. This bound is not strict, so it is possible " |
+ "for the cache to go over this bound in certain circumstances. "); |
namespace tcmalloc { |
@@ -74,21 +72,16 @@ |
#if defined(HAVE_TLS) |
bool kernel_supports_tls = false; // be conservative |
-# if defined(_WIN32) // windows has supported TLS since winnt, I think. |
+# if !HAVE_DECL_UNAME // if too old for uname, probably too old for TLS |
void CheckIfKernelSupportsTLS() { |
- kernel_supports_tls = true; |
- } |
-# elif !HAVE_DECL_UNAME // if too old for uname, probably too old for TLS |
- void CheckIfKernelSupportsTLS() { |
kernel_supports_tls = false; |
} |
# else |
# include <sys/utsname.h> // DECL_UNAME checked for <sys/utsname.h> too |
void CheckIfKernelSupportsTLS() { |
struct utsname buf; |
- if (uname(&buf) < 0) { // should be impossible |
- Log(kLog, __FILE__, __LINE__, |
- "uname failed assuming no TLS support (errno)", errno); |
+ if (uname(&buf) != 0) { // should be impossible |
+ MESSAGE("uname failed assuming no TLS support (errno=%d)\n", errno); |
kernel_supports_tls = false; |
} else if (strcasecmp(buf.sysname, "linux") == 0) { |
// The linux case: the first kernel to support TLS was 2.6.0 |
@@ -100,10 +93,6 @@ |
kernel_supports_tls = false; |
else |
kernel_supports_tls = true; |
- } else if (strcasecmp(buf.sysname, "CYGWIN_NT-6.1-WOW64") == 0) { |
- // In my testing, this version of cygwin, at least, would hang |
- // when using TLS. |
- kernel_supports_tls = false; |
} else { // some other kernel, we'll be optimisitic |
kernel_supports_tls = true; |
} |
@@ -270,6 +259,10 @@ |
} |
IncreaseCacheLimit(); |
+ |
+// int64 finish = CycleClock::Now(); |
+// CycleTimer ct; |
+// MESSAGE("GC: %.0f ns\n", ct.CyclesToUsec(finish-start)*1000.0); |
} |
void ThreadCache::IncreaseCacheLimit() { |
@@ -329,18 +322,6 @@ |
ASSERT(!tsd_inited_); |
perftools_pthread_key_create(&heap_key_, DestroyThreadCache); |
tsd_inited_ = true; |
- |
-#ifdef PTHREADS_CRASHES_IF_RUN_TOO_EARLY |
- // We may have used a fake pthread_t for the main thread. Fix it. |
- pthread_t zero; |
- memset(&zero, 0, sizeof(zero)); |
- SpinLockHolder h(Static::pageheap_lock()); |
- for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) { |
- if (h->tid_ == zero) { |
- h->tid_ = pthread_self(); |
- } |
- } |
-#endif |
} |
ThreadCache* ThreadCache::CreateCacheIfNecessary() { |
@@ -348,23 +329,17 @@ |
ThreadCache* heap = NULL; |
{ |
SpinLockHolder h(Static::pageheap_lock()); |
- // On some old glibc's, and on freebsd's libc (as of freebsd 8.1), |
- // calling pthread routines (even pthread_self) too early could |
- // cause a segfault. Since we can call pthreads quite early, we |
- // have to protect against that in such situations by making a |
- // 'fake' pthread. This is not ideal since it doesn't work well |
- // when linking tcmalloc statically with apps that create threads |
- // before main, so we only do it if we have to. |
-#ifdef PTHREADS_CRASHES_IF_RUN_TOO_EARLY |
- pthread_t me; |
- if (!tsd_inited_) { |
- memset(&me, 0, sizeof(me)); |
- } else { |
- me = pthread_self(); |
- } |
-#else |
+ // On very old libc's, this call may crash if it happens too |
+ // early. No libc using NPTL should be affected. If there |
+ // is a crash here, we could use code (on linux, at least) |
+ // to detect NPTL vs LinuxThreads: |
+ // http://www.redhat.com/archives/phil-list/2003-April/msg00038.html |
+ // If we detect not-NPTL, we could execute the old code from |
+ // http://google-perftools.googlecode.com/svn/tags/google-perftools-1.7/src/thread_cache.cc |
+ // that avoids calling pthread_self too early. The problem with |
+ // that code is it caused a race condition when tcmalloc is linked |
+ // in statically and other libraries spawn threads before main. |
const pthread_t me = pthread_self(); |
-#endif |
// This may be a recursive malloc call from pthread_setspecific() |
// In that case, the heap for this thread has already been created |
@@ -487,8 +462,32 @@ |
} |
unclaimed_cache_space_ = overall_thread_cache_size_ - claimed; |
per_thread_cache_size_ = space; |
+ // TCMalloc_MESSAGE(__FILE__, __LINE__, "Threads %d => cache size %8d\n", n, int(space)); |
} |
+void ThreadCache::Print(TCMalloc_Printer* out) const { |
+ for (int cl = 0; cl < kNumClasses; ++cl) { |
+ out->printf(" %5" PRIuS " : %4" PRIuS " len; %4d lo; %4"PRIuS |
+ " max; %4"PRIuS" overages;\n", |
+ Static::sizemap()->ByteSizeForClass(cl), |
+ list_[cl].length(), |
+ list_[cl].lowwatermark(), |
+ list_[cl].max_length(), |
+ list_[cl].length_overages()); |
+ } |
+} |
+ |
+void ThreadCache::PrintThreads(TCMalloc_Printer* out) { |
+ size_t actual_limit = 0; |
+ for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) { |
+ h->Print(out); |
+ actual_limit += h->max_size_; |
+ } |
+ out->printf("ThreadCache overall: %"PRIuS ", unclaimed: %"PRIuS |
+ ", actual: %"PRIuS"\n", |
+ overall_thread_cache_size_, unclaimed_cache_space_, actual_limit); |
+} |
+ |
void ThreadCache::GetThreadStats(uint64_t* total_bytes, uint64_t* class_count) { |
for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) { |
*total_bytes += h->Size(); |