1 // Copyright (c) 2005, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 // Author: Sanjay Ghemawat
33 // This has the implementation details of malloc_hook that are needed
34 // to use malloc-hook inside the tcmalloc system. It does not hold
35 // any of the client-facing calls that are used to add new hooks.
37 #ifndef _MALLOC_HOOK_INL_H_
38 #define _MALLOC_HOOK_INL_H_
41 #include <sys/types.h>
42 #include "base/atomicops.h"
43 #include "base/basictypes.h"
44 #include <gperftools/malloc_hook.h>
46 namespace base
{ namespace internal
{
48 // The following (implementation) code is DEPRECATED.
49 // A simple atomic pointer class that can be initialized by the linker
50 // when you define a namespace-scope variable as:
52 // AtomicPtr<Foo*> my_global = { &initial_value };
54 // This isn't suitable for a general atomic<> class because of the
55 // public access to data_.
56 template<typename PtrT
>
59 COMPILE_ASSERT(sizeof(PtrT
) <= sizeof(AtomicWord
),
60 PtrT_should_fit_in_AtomicWord
);
63 // Depending on the system, Acquire_Load(AtomicWord*) may have
64 // been defined to return an AtomicWord, Atomic32, or Atomic64.
65 // We hide that implementation detail here with an explicit cast.
66 // This prevents MSVC 2005, at least, from complaining (it has to
67 // do with __wp64; AtomicWord is __wp64, but Atomic32/64 aren't).
68 return reinterpret_cast<PtrT
>(static_cast<AtomicWord
>(
69 base::subtle::Acquire_Load(&data_
)));
72 // Sets the contained value to new_val and returns the old value,
73 // atomically, with acquire and release semantics.
74 // This is a full-barrier instruction.
75 PtrT
Exchange(PtrT new_val
);
77 // Atomically executes:
79 // if (data_ == old_val)
82 // This is a full-barrier instruction.
83 PtrT
CompareAndSwap(PtrT old_val
, PtrT new_val
);
85 // Not private so that the class is an aggregate and can be
86 // initialized by the linker. Don't access this directly.
90 // These are initialized in malloc_hook.cc
91 extern AtomicPtr
<MallocHook::NewHook
> new_hook_
;
92 extern AtomicPtr
<MallocHook::DeleteHook
> delete_hook_
;
93 extern AtomicPtr
<MallocHook::PreMmapHook
> premmap_hook_
;
94 extern AtomicPtr
<MallocHook::MmapHook
> mmap_hook_
;
95 extern AtomicPtr
<MallocHook::MunmapHook
> munmap_hook_
;
96 extern AtomicPtr
<MallocHook::MremapHook
> mremap_hook_
;
97 extern AtomicPtr
<MallocHook::PreSbrkHook
> presbrk_hook_
;
98 extern AtomicPtr
<MallocHook::SbrkHook
> sbrk_hook_
;
99 // End DEPRECATED code.
101 // Maximum of 7 hooks means that HookList is 8 words.
102 static const int kHookListMaxValues
= 7;
104 // HookList: a class that provides synchronized insertions and removals and
105 // lockless traversal. Most of the implementation is in malloc_hook.cc.
106 template <typename T
>
107 struct PERFTOOLS_DLL_DECL HookList
{
108 COMPILE_ASSERT(sizeof(T
) <= sizeof(AtomicWord
), T_should_fit_in_AtomicWord
);
110 // Adds value to the list. Note that duplicates are allowed. Thread-safe and
111 // blocking (acquires hooklist_spinlock). Returns true on success; false
112 // otherwise (failures include invalid value and no space left).
115 // Removes the first entry matching value from the list. Thread-safe and
116 // blocking (acquires hooklist_spinlock). Returns true on success; false
117 // otherwise (failures include invalid value and no value found).
118 bool Remove(T value
);
120 // Store up to n values of the list in output_array, and return the number of
121 // elements stored. Thread-safe and non-blocking. This is fast (one memory
122 // access) if the list is empty.
123 int Traverse(T
* output_array
, int n
) const;
125 // Fast inline implementation for fast path of Invoke*Hook.
127 return base::subtle::Acquire_Load(&priv_end
) == 0;
130 // This internal data is not private so that the class is an aggregate and can
131 // be initialized by the linker. Don't access this directly. Use the
132 // INIT_HOOK_LIST macro in malloc_hook.cc.
134 // One more than the index of the last valid element in priv_data. During
135 // 'Remove' this may be past the last valid element in priv_data, but
136 // subsequent values will be 0.
138 AtomicWord priv_data
[kHookListMaxValues
];
141 extern HookList
<MallocHook::NewHook
> new_hooks_
;
142 extern HookList
<MallocHook::DeleteHook
> delete_hooks_
;
143 extern HookList
<MallocHook::PreMmapHook
> premmap_hooks_
;
144 extern HookList
<MallocHook::MmapHook
> mmap_hooks_
;
145 extern HookList
<MallocHook::MmapReplacement
> mmap_replacement_
;
146 extern HookList
<MallocHook::MunmapHook
> munmap_hooks_
;
147 extern HookList
<MallocHook::MunmapReplacement
> munmap_replacement_
;
148 extern HookList
<MallocHook::MremapHook
> mremap_hooks_
;
149 extern HookList
<MallocHook::PreSbrkHook
> presbrk_hooks_
;
150 extern HookList
<MallocHook::SbrkHook
> sbrk_hooks_
;
152 } } // namespace base::internal
154 // The following method is DEPRECATED
155 inline MallocHook::NewHook
MallocHook::GetNewHook() {
156 return base::internal::new_hook_
.Get();
159 inline void MallocHook::InvokeNewHook(const void* p
, size_t s
) {
160 if (!base::internal::new_hooks_
.empty()) {
161 InvokeNewHookSlow(p
, s
);
163 // The following code is DEPRECATED.
164 MallocHook::NewHook hook
= MallocHook::GetNewHook();
165 if (hook
!= NULL
) (*hook
)(p
, s
);
166 // End DEPRECATED code.
169 // The following method is DEPRECATED
170 inline MallocHook::DeleteHook
MallocHook::GetDeleteHook() {
171 return base::internal::delete_hook_
.Get();
174 inline void MallocHook::InvokeDeleteHook(const void* p
) {
175 if (!base::internal::delete_hooks_
.empty()) {
176 InvokeDeleteHookSlow(p
);
178 // The following code is DEPRECATED.
179 MallocHook::DeleteHook hook
= MallocHook::GetDeleteHook();
180 if (hook
!= NULL
) (*hook
)(p
);
181 // End DEPRECATED code.
184 // The following method is DEPRECATED
185 inline MallocHook::PreMmapHook
MallocHook::GetPreMmapHook() {
186 return base::internal::premmap_hook_
.Get();
189 inline void MallocHook::InvokePreMmapHook(const void* start
,
195 if (!base::internal::premmap_hooks_
.empty()) {
196 InvokePreMmapHookSlow(start
, size
, protection
, flags
, fd
, offset
);
198 // The following code is DEPRECATED.
199 MallocHook::PreMmapHook hook
= MallocHook::GetPreMmapHook();
200 if (hook
!= NULL
) (*hook
)(start
, size
,
203 // End DEPRECATED code.
206 // The following method is DEPRECATED
207 inline MallocHook::MmapHook
MallocHook::GetMmapHook() {
208 return base::internal::mmap_hook_
.Get();
211 inline void MallocHook::InvokeMmapHook(const void* result
,
218 if (!base::internal::mmap_hooks_
.empty()) {
219 InvokeMmapHookSlow(result
, start
, size
, protection
, flags
, fd
, offset
);
221 // The following code is DEPRECATED.
222 MallocHook::MmapHook hook
= MallocHook::GetMmapHook();
223 if (hook
!= NULL
) (*hook
)(result
,
227 // End DEPRECATED code.
230 inline bool MallocHook::InvokeMmapReplacement(const void* start
,
237 if (!base::internal::mmap_replacement_
.empty()) {
238 return InvokeMmapReplacementSlow(start
, size
,
246 // The following method is DEPRECATED
247 inline MallocHook::MunmapHook
MallocHook::GetMunmapHook() {
248 return base::internal::munmap_hook_
.Get();
251 inline void MallocHook::InvokeMunmapHook(const void* p
, size_t size
) {
252 if (!base::internal::munmap_hooks_
.empty()) {
253 InvokeMunmapHookSlow(p
, size
);
255 // The following code is DEPRECATED.
256 MallocHook::MunmapHook hook
= MallocHook::GetMunmapHook();
257 if (hook
!= NULL
) (*hook
)(p
, size
);
258 // End DEPRECATED code.
261 inline bool MallocHook::InvokeMunmapReplacement(
262 const void* p
, size_t size
, int* result
) {
263 if (!base::internal::mmap_replacement_
.empty()) {
264 return InvokeMunmapReplacementSlow(p
, size
, result
);
269 // The following method is DEPRECATED
270 inline MallocHook::MremapHook
MallocHook::GetMremapHook() {
271 return base::internal::mremap_hook_
.Get();
274 inline void MallocHook::InvokeMremapHook(const void* result
,
275 const void* old_addr
,
279 const void* new_addr
) {
280 if (!base::internal::mremap_hooks_
.empty()) {
281 InvokeMremapHookSlow(result
, old_addr
, old_size
, new_size
, flags
, new_addr
);
283 // The following code is DEPRECATED.
284 MallocHook::MremapHook hook
= MallocHook::GetMremapHook();
285 if (hook
!= NULL
) (*hook
)(result
,
287 new_size
, flags
, new_addr
);
288 // End DEPRECATED code.
291 // The following method is DEPRECATED
292 inline MallocHook::PreSbrkHook
MallocHook::GetPreSbrkHook() {
293 return base::internal::presbrk_hook_
.Get();
296 inline void MallocHook::InvokePreSbrkHook(ptrdiff_t increment
) {
297 if (!base::internal::presbrk_hooks_
.empty() && increment
!= 0) {
298 InvokePreSbrkHookSlow(increment
);
300 // The following code is DEPRECATED.
301 MallocHook::PreSbrkHook hook
= MallocHook::GetPreSbrkHook();
302 if (hook
!= NULL
&& increment
!= 0) (*hook
)(increment
);
303 // End DEPRECATED code.
306 // The following method is DEPRECATED
307 inline MallocHook::SbrkHook
MallocHook::GetSbrkHook() {
308 return base::internal::sbrk_hook_
.Get();
311 inline void MallocHook::InvokeSbrkHook(const void* result
,
312 ptrdiff_t increment
) {
313 if (!base::internal::sbrk_hooks_
.empty() && increment
!= 0) {
314 InvokeSbrkHookSlow(result
, increment
);
316 // The following code is DEPRECATED.
317 MallocHook::SbrkHook hook
= MallocHook::GetSbrkHook();
318 if (hook
!= NULL
&& increment
!= 0) (*hook
)(result
, increment
);
319 // End DEPRECATED code.
322 #endif /* _MALLOC_HOOK_INL_H_ */