blob: 09d2b5902c7f6ee143966903b6652e5cbc0fa41d [file] [log] [blame]
Austin Schuh745610d2015-09-06 18:19:50 -07001// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2// Copyright (c) 2008, Google Inc.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// ---
32// Author: Ken Ashcraft <opensource@google.com>
33
34#include <config.h>
35#include "static_vars.h"
36#include <stddef.h> // for NULL
37#include <new> // for operator new
38#ifdef HAVE_PTHREAD
39#include <pthread.h> // for pthread_atfork
40#endif
41#include "internal_logging.h" // for CHECK_CONDITION
42#include "common.h"
43#include "sampler.h" // for Sampler
44#include "getenv_safe.h" // TCMallocGetenvSafe
45#include "base/googleinit.h"
46
47namespace tcmalloc {
48
49#if defined(HAVE_FORK) && defined(HAVE_PTHREAD)
50// These following two functions are registered via pthread_atfork to make
51// sure the central_cache locks remain in a consisten state in the forked
52// version of the thread.
53
54void CentralCacheLockAll()
55{
56 Static::pageheap_lock()->Lock();
57 for (int i = 0; i < kNumClasses; ++i)
58 Static::central_cache()[i].Lock();
59}
60
61void CentralCacheUnlockAll()
62{
63 for (int i = 0; i < kNumClasses; ++i)
64 Static::central_cache()[i].Unlock();
65 Static::pageheap_lock()->Unlock();
66}
67#endif
68
69SpinLock Static::pageheap_lock_(SpinLock::LINKER_INITIALIZED);
70SizeMap Static::sizemap_;
71CentralFreeListPadded Static::central_cache_[kNumClasses];
72PageHeapAllocator<Span> Static::span_allocator_;
73PageHeapAllocator<StackTrace> Static::stacktrace_allocator_;
74Span Static::sampled_objects_;
75PageHeapAllocator<StackTraceTable::Bucket> Static::bucket_allocator_;
76StackTrace* Static::growth_stacks_ = NULL;
77PageHeap* Static::pageheap_ = NULL;
78
79
80void Static::InitStaticVars() {
81 sizemap_.Init();
82 span_allocator_.Init();
83 span_allocator_.New(); // Reduce cache conflicts
84 span_allocator_.New(); // Reduce cache conflicts
85 stacktrace_allocator_.Init();
86 bucket_allocator_.Init();
87 // Do a bit of sanitizing: make sure central_cache is aligned properly
88 CHECK_CONDITION((sizeof(central_cache_[0]) % 64) == 0);
89 for (int i = 0; i < kNumClasses; ++i) {
90 central_cache_[i].Init(i);
91 }
92
93 // It's important to have PageHeap allocated, not in static storage,
94 // so that HeapLeakChecker does not consider all the byte patterns stored
95 // in is caches as pointers that are sources of heap object liveness,
96 // which leads to it missing some memory leaks.
97 pageheap_ = new (MetaDataAlloc(sizeof(PageHeap))) PageHeap;
98
99 bool aggressive_decommit =
100 tcmalloc::commandlineflags::StringToBool(
101 TCMallocGetenvSafe("TCMALLOC_AGGRESSIVE_DECOMMIT"), true);
102
103 pageheap_->SetAggressiveDecommit(aggressive_decommit);
104
105 DLL_Init(&sampled_objects_);
106 Sampler::InitStatics();
107}
108
109
110#if defined(HAVE_FORK) && defined(HAVE_PTHREAD)
111
112static inline
113void SetupAtForkLocksHandler()
114{
115#if !defined(__APPLE__)
116 pthread_atfork(CentralCacheLockAll, // parent calls before fork
117 CentralCacheUnlockAll, // parent calls after fork
118 CentralCacheUnlockAll); // child calls after fork
119#endif
120}
121REGISTER_MODULE_INITIALIZER(tcmalloc_fork_handler, SetupAtForkLocksHandler());
122
123#endif
124
125} // namespace tcmalloc