15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2005, 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) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using STL_NAMESPACE::string; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using STL_NAMESPACE::vector; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DumpAddressMap(string* result) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result += "\nMAPPED_LIBRARIES:\n"; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We keep doubling until we get a fit 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t old_resultlen = result->size(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int amap_size = 10240; amap_size < 10000000; amap_size *= 2) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->resize(old_resultlen + amap_size); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool wrote_all = false; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int bytes_written = 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tcmalloc::FillProcSelfMaps(&((*result)[old_resultlen]), amap_size, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &wrote_all); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (wrote_all) { // we fit! 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*result)[old_resultlen + bytes_written] = '\0'; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->resize(old_resultlen + bytes_written); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->reserve(old_resultlen); // just don't print anything 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: this routine is meant to be called before threads are spawned. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::Initialize() { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialize_called = false; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialize_called) return; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialize_called = true; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GLIBC__ 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GNU libc++ versions 3.3 and 3.4 obey the environment variables 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GLIBCPP_FORCE_NEW and GLIBCXX_FORCE_NEW respectively. Setting 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one of these variables forces the STL default allocator to call 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new() or delete() for each allocation or deletion. Otherwise 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the STL allocator tries to avoid the high cost of doing 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allocations by pooling memory internally. However, tcmalloc 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // does allocations really fast, especially for the types of small 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // items one sees in STL, so it's better off just using us. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO: control whether we do this via an environment variable? 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setenv("GLIBCPP_FORCE_NEW", "1", false /* no overwrite*/); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setenv("GLIBCXX_FORCE_NEW", "1", false /* no overwrite*/); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now we need to make the setenv 'stick', which it may not do since 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the env is flakey before main() is called. But luckily stl only 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // looks at this env var the first time it tries to do an alloc, and 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // caches what it finds. So we just cause an stl alloc here. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string dummy("I need to be allocated"); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dummy += "!"; // so the definition of dummy isn't optimized out 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* __GLIBC__ */ 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SysAllocator implementation 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SysAllocator::~SysAllocator() {} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default implementation -- does nothing 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MallocExtension::~MallocExtension() { } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::VerifyAllMemory() { return true; } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::VerifyNewMemory(const void* p) { return true; } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::VerifyArrayNewMemory(const void* p) { return true; } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::VerifyMallocMemory(const void* p) { return true; } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::GetNumericProperty(const char* property, size_t* value) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::SetNumericProperty(const char* property, size_t value) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::GetStats(char* buffer, int length) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(length > 0); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = '\0'; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MallocExtension::MallocMemoryStats(int* blocks, size_t* total, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int histogram[kMallocHistogramSize]) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *blocks = 0; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *total = 0; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(histogram, 0, sizeof(*histogram) * kMallocHistogramSize); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void** MallocExtension::ReadStackTraces(int* sample_period) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void** MallocExtension::ReadHeapGrowthStackTraces() { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::MarkThreadIdle() { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default implementation does nothing 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::MarkThreadBusy() { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default implementation does nothing 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SysAllocator* MallocExtension::GetSystemAllocator() { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::SetSystemAllocator(SysAllocator *a) { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default implementation does nothing 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::ReleaseToSystem(size_t num_bytes) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default implementation does nothing 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::ReleaseFreeMemory() { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReleaseToSystem(static_cast<size_t>(-1)); // SIZE_T_MAX 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::SetMemoryReleaseRate(double rate) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default implementation does nothing 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double MallocExtension::GetMemoryReleaseRate() { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1.0; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t MallocExtension::GetEstimatedAllocatedSize(size_t size) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t MallocExtension::GetAllocatedSize(const void* p) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(GetOwnership(p) != kNotOwned); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MallocExtension::Ownership MallocExtension::GetOwnership(const void* p) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kUnknownOwnership; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::GetFreeListSizes( 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<MallocExtension::FreeListInfo>* v) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v->clear(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The current malloc extension object. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static pthread_once_t module_init = PTHREAD_ONCE_INIT; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static MallocExtension* current_instance = NULL; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void InitModule() { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_instance = new MallocExtension; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NO_HEAP_CHECK 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::IgnoreObject(current_instance); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MallocExtension* MallocExtension::instance() { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perftools_pthread_once(&module_init, InitModule); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current_instance; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::Register(MallocExtension* implementation) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perftools_pthread_once(&module_init, InitModule); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When running under valgrind, our custom malloc is replaced with 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // valgrind's one and malloc extensions will not work. (Note: 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // callers should be responsible for checking that they are the 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // malloc that is really being run, before calling Register. This 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is just here as an extra sanity check.) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RunningOnValgrind()) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_instance = implementation; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------- 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Heap sampling support 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------- 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Accessors 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uintptr_t Count(void** entry) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<uintptr_t>(entry[0]); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uintptr_t Size(void** entry) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<uintptr_t>(entry[1]); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uintptr_t Depth(void** entry) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<uintptr_t>(entry[2]); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* PC(void** entry, int i) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return entry[3+i]; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintCountAndSize(MallocExtensionWriter* writer, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t count, uintptr_t size) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[100]; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buf, sizeof(buf), 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%6"PRIu64": %8"PRIu64" [%6"PRIu64": %8"PRIu64"] @", 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(count), 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(size), 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(count), 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(size)); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(buf, strlen(buf)); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHeader(MallocExtensionWriter* writer, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* label, void** entries) { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute the total count and total size 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t total_count = 0; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t total_size = 0; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_count += Count(entry); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_size += Size(entry); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const kTitle = "heap profile: "; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(kTitle, strlen(kTitle)); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintCountAndSize(writer, total_count, total_size); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(" ", 1); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(label, strlen(label)); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append("\n", 1); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintStackEntry(MallocExtensionWriter* writer, void** entry) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintCountAndSize(writer, Count(entry), Size(entry)); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < Depth(entry); i++) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[32]; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buf, sizeof(buf), " %p", PC(entry, i)); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(buf, strlen(buf)); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append("\n", 1); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::GetHeapSample(MallocExtensionWriter* writer) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sample_period = 0; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** entries = ReadStackTraces(&sample_period); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entries == NULL) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const kErrorMsg = 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "This malloc implementation does not support sampling.\n" 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "As of 2005/01/26, only tcmalloc supports sampling, and\n" 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "you are probably running a binary that does not use\n" 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "tcmalloc.\n"; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(kErrorMsg, strlen(kErrorMsg)); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char label[32]; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sprintf(label, "heap_v2/%d", sample_period); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintHeader(writer, label, entries); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintStackEntry(writer, entry); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] entries; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpAddressMap(writer); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::GetHeapGrowthStacks(MallocExtensionWriter* writer) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** entries = ReadHeapGrowthStackTraces(); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entries == NULL) { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const kErrorMsg = 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "This malloc implementation does not support " 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ReadHeapGrowthStackTraces().\n" 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "As of 2005/09/27, only tcmalloc supports this, and you\n" 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "are probably running a binary that does not use tcmalloc.\n"; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writer->append(kErrorMsg, strlen(kErrorMsg)); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do not canonicalize the stack entries, so that we get a 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time-ordered list of stack traces, which may be useful if the 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // client wants to focus on the latest stack traces. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintHeader(writer, "growth", entries); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (void** entry = entries; Count(entry) != 0; entry += 3 + Depth(entry)) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintStackEntry(writer, entry); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] entries; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DumpAddressMap(writer); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MallocExtension::Ranges(void* arg, RangeFunction func) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No callbacks by default 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These are C shims that work on the current instance. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define C_SHIM(fn, retval, paramlist, arglist) \ 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extern "C" PERFTOOLS_DLL_DECL retval MallocExtension_##fn paramlist { \ 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MallocExtension::instance()->fn arglist; \ 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(VerifyAllMemory, int, (void), ()); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(VerifyNewMemory, int, (const void* p), (p)); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(VerifyArrayNewMemory, int, (const void* p), (p)); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(VerifyMallocMemory, int, (const void* p), (p)); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(MallocMemoryStats, int, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (int* blocks, size_t* total, int histogram[kMallocHistogramSize]), 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (blocks, total, histogram)); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(GetStats, void, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (char* buffer, int buffer_length), (buffer, buffer_length)); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(GetNumericProperty, int, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (const char* property, size_t* value), (property, value)); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(SetNumericProperty, int, 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (const char* property, size_t value), (property, value)); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(MarkThreadIdle, void, (void), ()); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(MarkThreadBusy, void, (void), ()); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(ReleaseFreeMemory, void, (void), ()); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(ReleaseToSystem, void, (size_t num_bytes), (num_bytes)); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(GetEstimatedAllocatedSize, size_t, (size_t size), (size)); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)C_SHIM(GetAllocatedSize, size_t, (const void* p), (p)); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Can't use the shim here because of the need to translate the enums. 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MallocExtension_Ownership MallocExtension_GetOwnership(const void* p) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<MallocExtension_Ownership>( 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MallocExtension::instance()->GetOwnership(p)); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 373