15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Sanjay Ghemawat <opensource@google.com> 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <config.h> 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h> 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined HAVE_STDINT_H 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h> 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined HAVE_INTTYPES_H 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <inttypes.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/dynamic_annotations.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sysinfo.h" // for FillProcSelfMaps 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NO_HEAP_CHECK 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gperftools/heap-checker.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gperftools/malloc_extension.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "gperftools/malloc_extension_c.h" 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "maybe_threads.h" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "thread_cache.h" 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using STL_NAMESPACE::string; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using STL_NAMESPACE::vector; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DumpAddressMap(string* result) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result += "\nMAPPED_LIBRARIES:\n"; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We keep doubling until we get a fit 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t old_resultlen = result->size(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int amap_size = 10240; amap_size < 10000000; amap_size *= 2) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->resize(old_resultlen + amap_size); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool wrote_all = false; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int bytes_written = 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tcmalloc::FillProcSelfMaps(&((*result)[old_resultlen]), amap_size, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &wrote_all); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (wrote_all) { // we fit! 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*result)[old_resultlen + bytes_written] = '\0'; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->resize(old_resultlen + bytes_written); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->reserve(old_resultlen); // just don't print anything 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: this routine is meant to be called before threads are spawned. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::Initialize() { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialize_called = false; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialize_called) return; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialize_called = true; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GLIBC__ 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GNU libc++ versions 3.3 and 3.4 obey the environment variables 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GLIBCPP_FORCE_NEW and GLIBCXX_FORCE_NEW respectively. Setting 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one of these variables forces the STL default allocator to call 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new() or delete() for each allocation or deletion. Otherwise 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the STL allocator tries to avoid the high cost of doing 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allocations by pooling memory internally. However, tcmalloc 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // does allocations really fast, especially for the types of small 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // items one sees in STL, so it's better off just using us. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO: control whether we do this via an environment variable? 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setenv("GLIBCPP_FORCE_NEW", "1", false /* no overwrite*/); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setenv("GLIBCXX_FORCE_NEW", "1", false /* no overwrite*/); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now we need to make the setenv 'stick', which it may not do since 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the env is flakey before main() is called. But luckily stl only 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // looks at this env var the first time it tries to do an alloc, and 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caches what it finds. So we just cause an stl alloc here. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string dummy("I need to be allocated"); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dummy += "!"; // so the definition of dummy isn't optimized out 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* __GLIBC__ */ 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SysAllocator implementation 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SysAllocator::~SysAllocator() {} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default implementation -- does nothing 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MallocExtension::~MallocExtension() { } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::VerifyAllMemory() { return true; } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::VerifyNewMemory(const void* p) { return true; } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::VerifyArrayNewMemory(const void* p) { return true; } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::VerifyMallocMemory(const void* p) { return true; } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::GetNumericProperty(const char* property, size_t* value) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::SetNumericProperty(const char* property, size_t value) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::GetStats(char* buffer, int length) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(length > 0); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = '\0'; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::MallocMemoryStats(int* blocks, size_t* total, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int histogram[kMallocHistogramSize]) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *blocks = 0; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *total = 0; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(histogram, 0, sizeof(*histogram) * kMallocHistogramSize); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void** MallocExtension::ReadStackTraces(int* sample_period) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void** MallocExtension::ReadHeapGrowthStackTraces() { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::MarkThreadIdle() { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default implementation does nothing 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::MarkThreadBusy() { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default implementation does nothing 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SysAllocator* MallocExtension::GetSystemAllocator() { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::SetSystemAllocator(SysAllocator *a) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default implementation does nothing 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::ReleaseToSystem(size_t num_bytes) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default implementation does nothing 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::ReleaseFreeMemory() { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseToSystem(static_cast<size_t>(-1)); // SIZE_T_MAX 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::SetMemoryReleaseRate(double rate) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default implementation does nothing 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double MallocExtension::GetMemoryReleaseRate() { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1.0; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t MallocExtension::GetEstimatedAllocatedSize(size_t size) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t MallocExtension::GetAllocatedSize(const void* p) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(GetOwnership(p) != kNotOwned); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MallocExtension::Ownership MallocExtension::GetOwnership(const void* p) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kUnknownOwnership; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::GetFreeListSizes( 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<MallocExtension::FreeListInfo>* v) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v->clear(); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The current malloc extension object. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static pthread_once_t module_init = PTHREAD_ONCE_INIT; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static MallocExtension* current_instance = NULL; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void InitModule() { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_instance = new MallocExtension; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NO_HEAP_CHECK 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::IgnoreObject(current_instance); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MallocExtension* MallocExtension::instance() { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perftools_pthread_once(&module_init, InitModule); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current_instance; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::Register(MallocExtension* implementation) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perftools_pthread_once(&module_init, InitModule); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When running under valgrind, our custom malloc is replaced with 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valgrind's one and malloc extensions will not work. (Note: 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // callers should be responsible for checking that they are the 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // malloc that is really being run, before calling Register. This 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is just here as an extra sanity check.) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RunningOnValgrind()) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_instance = implementation; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int MallocExtension::GetBytesAllocatedOnCurrentThread() { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return tcmalloc::ThreadCache::GetBytesAllocatedOnCurrentThread(); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------- 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Heap sampling support 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------- 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Accessors 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uintptr_t Count(void** entry) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<uintptr_t>(entry[0]); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uintptr_t Size(void** entry) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<uintptr_t>(entry[1]); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uintptr_t Depth(void** entry) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<uintptr_t>(entry[2]); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PC(void** entry, int i) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return entry[3+i]; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintCountAndSize(MallocExtensionWriter* writer, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t count, uintptr_t size) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[100]; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buf, sizeof(buf), 252558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch "%6" PRIu64 ": %8" PRIu64 " [%6" PRIu64 ": %8" PRIu64 "] @", 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(count), 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(size), 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(count), 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(size)); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(buf, strlen(buf)); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHeader(MallocExtensionWriter* writer, 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* label, void** entries) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute the total count and total size 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t total_count = 0; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t total_size = 0; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_count += Count(entry); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_size += Size(entry); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const kTitle = "heap profile: "; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(kTitle, strlen(kTitle)); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintCountAndSize(writer, total_count, total_size); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(" ", 1); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(label, strlen(label)); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append("\n", 1); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintStackEntry(MallocExtensionWriter* writer, void** entry) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintCountAndSize(writer, Count(entry), Size(entry)); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < Depth(entry); i++) { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[32]; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buf, sizeof(buf), " %p", PC(entry, i)); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(buf, strlen(buf)); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append("\n", 1); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::GetHeapSample(MallocExtensionWriter* writer) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sample_period = 0; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** entries = ReadStackTraces(&sample_period); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entries == NULL) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const kErrorMsg = 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "This malloc implementation does not support sampling.\n" 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "As of 2005/01/26, only tcmalloc supports sampling, and\n" 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "you are probably running a binary that does not use\n" 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "tcmalloc.\n"; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(kErrorMsg, strlen(kErrorMsg)); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char label[32]; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sprintf(label, "heap_v2/%d", sample_period); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintHeader(writer, label, entries); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintStackEntry(writer, entry); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] entries; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpAddressMap(writer); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::GetHeapGrowthStacks(MallocExtensionWriter* writer) { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** entries = ReadHeapGrowthStackTraces(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entries == NULL) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const kErrorMsg = 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "This malloc implementation does not support " 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ReadHeapGrowthStackTraces().\n" 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "As of 2005/09/27, only tcmalloc supports this, and you\n" 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "are probably running a binary that does not use tcmalloc.\n"; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(kErrorMsg, strlen(kErrorMsg)); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do not canonicalize the stack entries, so that we get a 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time-ordered list of stack traces, which may be useful if the 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // client wants to focus on the latest stack traces. 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintHeader(writer, "growth", entries); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintStackEntry(writer, entry); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] entries; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpAddressMap(writer); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::Ranges(void* arg, RangeFunction func) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No callbacks by default 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These are C shims that work on the current instance. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define C_SHIM(fn, retval, paramlist, arglist) \ 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extern "C" PERFTOOLS_DLL_DECL retval MallocExtension_##fn paramlist { \ 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocExtension::instance()->fn arglist; \ 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(VerifyAllMemory, int, (void), ()); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(VerifyNewMemory, int, (const void* p), (p)); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(VerifyArrayNewMemory, int, (const void* p), (p)); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(VerifyMallocMemory, int, (const void* p), (p)); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(MallocMemoryStats, int, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int* blocks, size_t* total, int histogram[kMallocHistogramSize]), 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (blocks, total, histogram)); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(GetStats, void, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (char* buffer, int buffer_length), (buffer, buffer_length)); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(GetNumericProperty, int, 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (const char* property, size_t* value), (property, value)); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(SetNumericProperty, int, 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (const char* property, size_t value), (property, value)); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(MarkThreadIdle, void, (void), ()); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(MarkThreadBusy, void, (void), ()); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(ReleaseFreeMemory, void, (void), ()); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(ReleaseToSystem, void, (size_t num_bytes), (num_bytes)); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(GetEstimatedAllocatedSize, size_t, (size_t size), (size)); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(GetAllocatedSize, size_t, (const void* p), (p)); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Can't use the shim here because of the need to translate the enums. 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MallocExtension_Ownership MallocExtension_GetOwnership(const void* p) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<MallocExtension_Ownership>( 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MallocExtension::instance()->GetOwnership(p)); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 378