| 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(std::ptrdiff_t increment) { | 296 inline void MallocHook::InvokePreSbrkHook(std::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 std::ptrdiff_t increment) { | 312 std::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 |