OLD | NEW |
1 // Copyright (c) 2005, Google Inc. | 1 // Copyright (c) 2005, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 27 matching lines...) Expand all Loading... |
38 #define _MALLOC_HOOK_INL_H_ | 38 #define _MALLOC_HOOK_INL_H_ |
39 | 39 |
40 #include <stddef.h> | 40 #include <stddef.h> |
41 #include <sys/types.h> | 41 #include <sys/types.h> |
42 #include "base/atomicops.h" | 42 #include "base/atomicops.h" |
43 #include "base/basictypes.h" | 43 #include "base/basictypes.h" |
44 #include <google/malloc_hook.h> | 44 #include <google/malloc_hook.h> |
45 | 45 |
46 namespace base { namespace internal { | 46 namespace base { namespace internal { |
47 | 47 |
| 48 // The following (implementation) code is DEPRECATED. |
48 // A simple atomic pointer class that can be initialized by the linker | 49 // A simple atomic pointer class that can be initialized by the linker |
49 // when you define a namespace-scope variable as: | 50 // when you define a namespace-scope variable as: |
50 // | 51 // |
51 // AtomicPtr<Foo*> my_global = { &initial_value }; | 52 // AtomicPtr<Foo*> my_global = { &initial_value }; |
52 // | 53 // |
53 // This isn't suitable for a general atomic<> class because of the | 54 // This isn't suitable for a general atomic<> class because of the |
54 // public access to data_. | 55 // public access to data_. |
55 template<typename PtrT> | 56 template<typename PtrT> |
56 class AtomicPtr { | 57 class AtomicPtr { |
57 public: | 58 public: |
58 COMPILE_ASSERT(sizeof(PtrT) <= sizeof(AtomicWord), | 59 COMPILE_ASSERT(sizeof(PtrT) <= sizeof(AtomicWord), |
59 PtrT_should_fit_in_AtomicWord); | 60 PtrT_should_fit_in_AtomicWord); |
60 | 61 |
61 PtrT Get() const { | 62 PtrT Get() const { |
62 // Depending on the system, Acquire_Load(AtomicWord*) may have | 63 // Depending on the system, Acquire_Load(AtomicWord*) may have |
63 // been defined to return an AtomicWord, Atomic32, or Atomic64. | 64 // been defined to return an AtomicWord, Atomic32, or Atomic64. |
64 // We hide that implementation detail here with an explicit cast. | 65 // We hide that implementation detail here with an explicit cast. |
65 // This prevents MSVC 2005, at least, from complaining (it has to | 66 // This prevents MSVC 2005, at least, from complaining (it has to |
66 // do with __wp64; AtomicWord is __wp64, but Atomic32/64 aren't). | 67 // do with __wp64; AtomicWord is __wp64, but Atomic32/64 aren't). |
67 return reinterpret_cast<PtrT>(static_cast<AtomicWord>( | 68 return reinterpret_cast<PtrT>(static_cast<AtomicWord>( |
68 base::subtle::Acquire_Load(&data_))); | 69 base::subtle::Acquire_Load(&data_))); |
69 } | 70 } |
70 | 71 |
71 // Sets the contained value to new_val and returns the old value, | 72 // Sets the contained value to new_val and returns the old value, |
72 // atomically, with acquire and release semantics. | 73 // atomically, with acquire and release semantics. |
| 74 // This is a full-barrier instruction. |
73 PtrT Exchange(PtrT new_val); | 75 PtrT Exchange(PtrT new_val); |
74 | 76 |
| 77 // Atomically executes: |
| 78 // result = data_ |
| 79 // if (data_ == old_val) |
| 80 // data_ = new_val; |
| 81 // return result; |
| 82 // This is a full-barrier instruction. |
| 83 PtrT CompareAndSwap(PtrT old_val, PtrT new_val); |
| 84 |
75 // Not private so that the class is an aggregate and can be | 85 // Not private so that the class is an aggregate and can be |
76 // initialized by the linker. Don't access this directly. | 86 // initialized by the linker. Don't access this directly. |
77 AtomicWord data_; | 87 AtomicWord data_; |
78 }; | 88 }; |
79 | 89 |
80 // These are initialized in malloc_hook.cc | 90 // These are initialized in malloc_hook.cc |
81 extern AtomicPtr<MallocHook::NewHook> new_hook_; | 91 extern AtomicPtr<MallocHook::NewHook> new_hook_; |
82 extern AtomicPtr<MallocHook::DeleteHook> delete_hook_; | 92 extern AtomicPtr<MallocHook::DeleteHook> delete_hook_; |
83 extern AtomicPtr<MallocHook::PreMmapHook> premmap_hook_; | 93 extern AtomicPtr<MallocHook::PreMmapHook> premmap_hook_; |
84 extern AtomicPtr<MallocHook::MmapHook> mmap_hook_; | 94 extern AtomicPtr<MallocHook::MmapHook> mmap_hook_; |
85 extern AtomicPtr<MallocHook::MunmapHook> munmap_hook_; | 95 extern AtomicPtr<MallocHook::MunmapHook> munmap_hook_; |
86 extern AtomicPtr<MallocHook::MremapHook> mremap_hook_; | 96 extern AtomicPtr<MallocHook::MremapHook> mremap_hook_; |
87 extern AtomicPtr<MallocHook::PreSbrkHook> presbrk_hook_; | 97 extern AtomicPtr<MallocHook::PreSbrkHook> presbrk_hook_; |
88 extern AtomicPtr<MallocHook::SbrkHook> sbrk_hook_; | 98 extern AtomicPtr<MallocHook::SbrkHook> sbrk_hook_; |
| 99 // End DEPRECATED code. |
| 100 |
| 101 // Maximum of 7 hooks means that HookList is 8 words. |
| 102 static const int kHookListMaxValues = 7; |
| 103 |
| 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 HookList { |
| 108 COMPILE_ASSERT(sizeof(T) <= sizeof(AtomicWord), T_should_fit_in_AtomicWord); |
| 109 |
| 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). |
| 113 bool Add(T value); |
| 114 |
| 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); |
| 119 |
| 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; |
| 124 |
| 125 // Fast inline implementation for fast path of Invoke*Hook. |
| 126 bool empty() const { |
| 127 return base::subtle::Acquire_Load(&priv_end) == 0; |
| 128 } |
| 129 |
| 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. |
| 133 |
| 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. |
| 137 AtomicWord priv_end; |
| 138 AtomicWord priv_data[kHookListMaxValues]; |
| 139 }; |
| 140 |
| 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_; |
89 | 151 |
90 } } // namespace base::internal | 152 } } // namespace base::internal |
91 | 153 |
| 154 // The following method is DEPRECATED |
92 inline MallocHook::NewHook MallocHook::GetNewHook() { | 155 inline MallocHook::NewHook MallocHook::GetNewHook() { |
93 return base::internal::new_hook_.Get(); | 156 return base::internal::new_hook_.Get(); |
94 } | 157 } |
95 | 158 |
96 inline void MallocHook::InvokeNewHook(const void* p, size_t s) { | 159 inline void MallocHook::InvokeNewHook(const void* p, size_t s) { |
| 160 if (!base::internal::new_hooks_.empty()) { |
| 161 InvokeNewHookSlow(p, s); |
| 162 } |
| 163 // The following code is DEPRECATED. |
97 MallocHook::NewHook hook = MallocHook::GetNewHook(); | 164 MallocHook::NewHook hook = MallocHook::GetNewHook(); |
98 if (hook != NULL) (*hook)(p, s); | 165 if (hook != NULL) (*hook)(p, s); |
| 166 // End DEPRECATED code. |
99 } | 167 } |
100 | 168 |
| 169 // The following method is DEPRECATED |
101 inline MallocHook::DeleteHook MallocHook::GetDeleteHook() { | 170 inline MallocHook::DeleteHook MallocHook::GetDeleteHook() { |
102 return base::internal::delete_hook_.Get(); | 171 return base::internal::delete_hook_.Get(); |
103 } | 172 } |
104 | 173 |
105 inline void MallocHook::InvokeDeleteHook(const void* p) { | 174 inline void MallocHook::InvokeDeleteHook(const void* p) { |
| 175 if (!base::internal::delete_hooks_.empty()) { |
| 176 InvokeDeleteHookSlow(p); |
| 177 } |
| 178 // The following code is DEPRECATED. |
106 MallocHook::DeleteHook hook = MallocHook::GetDeleteHook(); | 179 MallocHook::DeleteHook hook = MallocHook::GetDeleteHook(); |
107 if (hook != NULL) (*hook)(p); | 180 if (hook != NULL) (*hook)(p); |
| 181 // End DEPRECATED code. |
108 } | 182 } |
109 | 183 |
| 184 // The following method is DEPRECATED |
110 inline MallocHook::PreMmapHook MallocHook::GetPreMmapHook() { | 185 inline MallocHook::PreMmapHook MallocHook::GetPreMmapHook() { |
111 return base::internal::premmap_hook_.Get(); | 186 return base::internal::premmap_hook_.Get(); |
112 } | 187 } |
113 | 188 |
114 inline void MallocHook::InvokePreMmapHook(const void* start, | 189 inline void MallocHook::InvokePreMmapHook(const void* start, |
115 size_t size, | 190 size_t size, |
116 int protection, | 191 int protection, |
117 int flags, | 192 int flags, |
118 int fd, | 193 int fd, |
119 off_t offset) { | 194 off_t offset) { |
| 195 if (!base::internal::premmap_hooks_.empty()) { |
| 196 InvokePreMmapHookSlow(start, size, protection, flags, fd, offset); |
| 197 } |
| 198 // The following code is DEPRECATED. |
120 MallocHook::PreMmapHook hook = MallocHook::GetPreMmapHook(); | 199 MallocHook::PreMmapHook hook = MallocHook::GetPreMmapHook(); |
121 if (hook != NULL) (*hook)(start, size, | 200 if (hook != NULL) (*hook)(start, size, |
122 protection, flags, | 201 protection, flags, |
123 fd, offset); | 202 fd, offset); |
| 203 // End DEPRECATED code. |
124 } | 204 } |
125 | 205 |
| 206 // The following method is DEPRECATED |
126 inline MallocHook::MmapHook MallocHook::GetMmapHook() { | 207 inline MallocHook::MmapHook MallocHook::GetMmapHook() { |
127 return base::internal::mmap_hook_.Get(); | 208 return base::internal::mmap_hook_.Get(); |
128 } | 209 } |
129 | 210 |
130 inline void MallocHook::InvokeMmapHook(const void* result, | 211 inline void MallocHook::InvokeMmapHook(const void* result, |
131 const void* start, | 212 const void* start, |
132 size_t size, | 213 size_t size, |
133 int protection, | 214 int protection, |
134 int flags, | 215 int flags, |
135 int fd, | 216 int fd, |
136 off_t offset) { | 217 off_t offset) { |
| 218 if (!base::internal::mmap_hooks_.empty()) { |
| 219 InvokeMmapHookSlow(result, start, size, protection, flags, fd, offset); |
| 220 } |
| 221 // The following code is DEPRECATED. |
137 MallocHook::MmapHook hook = MallocHook::GetMmapHook(); | 222 MallocHook::MmapHook hook = MallocHook::GetMmapHook(); |
138 if (hook != NULL) (*hook)(result, | 223 if (hook != NULL) (*hook)(result, |
139 start, size, | 224 start, size, |
140 protection, flags, | 225 protection, flags, |
141 fd, offset); | 226 fd, offset); |
| 227 // End DEPRECATED code. |
142 } | 228 } |
143 | 229 |
| 230 inline bool MallocHook::InvokeMmapReplacement(const void* start, |
| 231 size_t size, |
| 232 int protection, |
| 233 int flags, |
| 234 int fd, |
| 235 off_t offset, |
| 236 void** result) { |
| 237 if (!base::internal::mmap_replacement_.empty()) { |
| 238 return InvokeMmapReplacementSlow(start, size, |
| 239 protection, flags, |
| 240 fd, offset, |
| 241 result); |
| 242 } |
| 243 return false; |
| 244 } |
| 245 |
| 246 // The following method is DEPRECATED |
144 inline MallocHook::MunmapHook MallocHook::GetMunmapHook() { | 247 inline MallocHook::MunmapHook MallocHook::GetMunmapHook() { |
145 return base::internal::munmap_hook_.Get(); | 248 return base::internal::munmap_hook_.Get(); |
146 } | 249 } |
147 | 250 |
148 inline void MallocHook::InvokeMunmapHook(const void* p, size_t size) { | 251 inline void MallocHook::InvokeMunmapHook(const void* p, size_t size) { |
| 252 if (!base::internal::munmap_hooks_.empty()) { |
| 253 InvokeMunmapHookSlow(p, size); |
| 254 } |
| 255 // The following code is DEPRECATED. |
149 MallocHook::MunmapHook hook = MallocHook::GetMunmapHook(); | 256 MallocHook::MunmapHook hook = MallocHook::GetMunmapHook(); |
150 if (hook != NULL) (*hook)(p, size); | 257 if (hook != NULL) (*hook)(p, size); |
| 258 // End DEPRECATED code. |
151 } | 259 } |
152 | 260 |
| 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); |
| 265 } |
| 266 return false; |
| 267 } |
| 268 |
| 269 // The following method is DEPRECATED |
153 inline MallocHook::MremapHook MallocHook::GetMremapHook() { | 270 inline MallocHook::MremapHook MallocHook::GetMremapHook() { |
154 return base::internal::mremap_hook_.Get(); | 271 return base::internal::mremap_hook_.Get(); |
155 } | 272 } |
156 | 273 |
157 inline void MallocHook::InvokeMremapHook(const void* result, | 274 inline void MallocHook::InvokeMremapHook(const void* result, |
158 const void* old_addr, | 275 const void* old_addr, |
159 size_t old_size, | 276 size_t old_size, |
160 size_t new_size, | 277 size_t new_size, |
161 int flags, | 278 int flags, |
162 const void* new_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); |
| 282 } |
| 283 // The following code is DEPRECATED. |
163 MallocHook::MremapHook hook = MallocHook::GetMremapHook(); | 284 MallocHook::MremapHook hook = MallocHook::GetMremapHook(); |
164 if (hook != NULL) (*hook)(result, | 285 if (hook != NULL) (*hook)(result, |
165 old_addr, old_size, | 286 old_addr, old_size, |
166 new_size, flags, new_addr); | 287 new_size, flags, new_addr); |
| 288 // End DEPRECATED code. |
167 } | 289 } |
168 | 290 |
| 291 // The following method is DEPRECATED |
169 inline MallocHook::PreSbrkHook MallocHook::GetPreSbrkHook() { | 292 inline MallocHook::PreSbrkHook MallocHook::GetPreSbrkHook() { |
170 return base::internal::presbrk_hook_.Get(); | 293 return base::internal::presbrk_hook_.Get(); |
171 } | 294 } |
172 | 295 |
173 inline void MallocHook::InvokePreSbrkHook(ptrdiff_t increment) { | 296 inline void MallocHook::InvokePreSbrkHook(ptrdiff_t increment) { |
| 297 if (!base::internal::presbrk_hooks_.empty() && increment != 0) { |
| 298 InvokePreSbrkHookSlow(increment); |
| 299 } |
| 300 // The following code is DEPRECATED. |
174 MallocHook::PreSbrkHook hook = MallocHook::GetPreSbrkHook(); | 301 MallocHook::PreSbrkHook hook = MallocHook::GetPreSbrkHook(); |
175 if (hook != NULL && increment != 0) (*hook)(increment); | 302 if (hook != NULL && increment != 0) (*hook)(increment); |
| 303 // End DEPRECATED code. |
176 } | 304 } |
177 | 305 |
| 306 // The following method is DEPRECATED |
178 inline MallocHook::SbrkHook MallocHook::GetSbrkHook() { | 307 inline MallocHook::SbrkHook MallocHook::GetSbrkHook() { |
179 return base::internal::sbrk_hook_.Get(); | 308 return base::internal::sbrk_hook_.Get(); |
180 } | 309 } |
181 | 310 |
182 inline void MallocHook::InvokeSbrkHook(const void* result, | 311 inline void MallocHook::InvokeSbrkHook(const void* result, |
183 ptrdiff_t increment) { | 312 ptrdiff_t increment) { |
| 313 if (!base::internal::sbrk_hooks_.empty() && increment != 0) { |
| 314 InvokeSbrkHookSlow(result, increment); |
| 315 } |
| 316 // The following code is DEPRECATED. |
184 MallocHook::SbrkHook hook = MallocHook::GetSbrkHook(); | 317 MallocHook::SbrkHook hook = MallocHook::GetSbrkHook(); |
185 if (hook != NULL && increment != 0) (*hook)(result, increment); | 318 if (hook != NULL && increment != 0) (*hook)(result, increment); |
| 319 // End DEPRECATED code. |
186 } | 320 } |
187 | 321 |
188 #endif /* _MALLOC_HOOK_INL_H_ */ | 322 #endif /* _MALLOC_HOOK_INL_H_ */ |
OLD | NEW |