malloc_hook-inl.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
  2. // Copyright (c) 2005, 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. // Author: Sanjay Ghemawat
  32. //
  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.
  36. #ifndef _MALLOC_HOOK_INL_H_
  37. #define _MALLOC_HOOK_INL_H_
  38. #include <stddef.h>
  39. #include <sys/types.h>
  40. #include "base/atomicops.h"
  41. #include "base/basictypes.h"
  42. #include <gperftools/malloc_hook.h>
  43. #include "common.h" // for UNLIKELY
  44. namespace base { namespace internal {
  45. // Capacity of 8 means that HookList is 9 words.
  46. static const int kHookListCapacity = 8;
  47. // last entry is reserved for deprecated "singular" hooks. So we have
  48. // 7 "normal" hooks per list
  49. static const int kHookListMaxValues = 7;
  50. static const int kHookListSingularIdx = 7;
  51. // HookList: a class that provides synchronized insertions and removals and
  52. // lockless traversal. Most of the implementation is in malloc_hook.cc.
  53. template <typename T>
  54. struct PERFTOOLS_DLL_DECL HookList {
  55. COMPILE_ASSERT(sizeof(T) <= sizeof(AtomicWord), T_should_fit_in_AtomicWord);
  56. // Adds value to the list. Note that duplicates are allowed. Thread-safe and
  57. // blocking (acquires hooklist_spinlock). Returns true on success; false
  58. // otherwise (failures include invalid value and no space left).
  59. bool Add(T value);
  60. void FixupPrivEndLocked();
  61. // Removes the first entry matching value from the list. Thread-safe and
  62. // blocking (acquires hooklist_spinlock). Returns true on success; false
  63. // otherwise (failures include invalid value and no value found).
  64. bool Remove(T value);
  65. // Store up to n values of the list in output_array, and return the number of
  66. // elements stored. Thread-safe and non-blocking. This is fast (one memory
  67. // access) if the list is empty.
  68. int Traverse(T* output_array, int n) const;
  69. // Fast inline implementation for fast path of Invoke*Hook.
  70. bool empty() const {
  71. return base::subtle::NoBarrier_Load(&priv_end) == 0;
  72. }
  73. // Used purely to handle deprecated singular hooks
  74. T GetSingular() const {
  75. const AtomicWord *place = &priv_data[kHookListSingularIdx];
  76. return bit_cast<T>(base::subtle::NoBarrier_Load(place));
  77. }
  78. T ExchangeSingular(T new_val);
  79. // This internal data is not private so that the class is an aggregate and can
  80. // be initialized by the linker. Don't access this directly. Use the
  81. // INIT_HOOK_LIST macro in malloc_hook.cc.
  82. // One more than the index of the last valid element in priv_data. During
  83. // 'Remove' this may be past the last valid element in priv_data, but
  84. // subsequent values will be 0.
  85. //
  86. // Index kHookListCapacity-1 is reserved as 'deprecated' single hook pointer
  87. AtomicWord priv_end;
  88. AtomicWord priv_data[kHookListCapacity];
  89. };
  90. ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::NewHook> new_hooks_;
  91. ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::DeleteHook> delete_hooks_;
  92. ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::PreMmapHook> premmap_hooks_;
  93. ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::MmapHook> mmap_hooks_;
  94. ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::MmapReplacement> mmap_replacement_;
  95. ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::MunmapHook> munmap_hooks_;
  96. ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::MunmapReplacement> munmap_replacement_;
  97. ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::MremapHook> mremap_hooks_;
  98. ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::PreSbrkHook> presbrk_hooks_;
  99. ATTRIBUTE_VISIBILITY_HIDDEN extern HookList<MallocHook::SbrkHook> sbrk_hooks_;
  100. } } // namespace base::internal
  101. // The following method is DEPRECATED
  102. inline MallocHook::NewHook MallocHook::GetNewHook() {
  103. return base::internal::new_hooks_.GetSingular();
  104. }
  105. inline void MallocHook::InvokeNewHook(const void* p, size_t s) {
  106. if (UNLIKELY(!base::internal::new_hooks_.empty())) {
  107. InvokeNewHookSlow(p, s);
  108. }
  109. }
  110. // The following method is DEPRECATED
  111. inline MallocHook::DeleteHook MallocHook::GetDeleteHook() {
  112. return base::internal::delete_hooks_.GetSingular();
  113. }
  114. inline void MallocHook::InvokeDeleteHook(const void* p) {
  115. if (UNLIKELY(!base::internal::delete_hooks_.empty())) {
  116. InvokeDeleteHookSlow(p);
  117. }
  118. }
  119. // The following method is DEPRECATED
  120. inline MallocHook::PreMmapHook MallocHook::GetPreMmapHook() {
  121. return base::internal::premmap_hooks_.GetSingular();
  122. }
  123. inline void MallocHook::InvokePreMmapHook(const void* start,
  124. size_t size,
  125. int protection,
  126. int flags,
  127. int fd,
  128. off_t offset) {
  129. if (!base::internal::premmap_hooks_.empty()) {
  130. InvokePreMmapHookSlow(start, size, protection, flags, fd, offset);
  131. }
  132. }
  133. // The following method is DEPRECATED
  134. inline MallocHook::MmapHook MallocHook::GetMmapHook() {
  135. return base::internal::mmap_hooks_.GetSingular();
  136. }
  137. inline void MallocHook::InvokeMmapHook(const void* result,
  138. const void* start,
  139. size_t size,
  140. int protection,
  141. int flags,
  142. int fd,
  143. off_t offset) {
  144. if (!base::internal::mmap_hooks_.empty()) {
  145. InvokeMmapHookSlow(result, start, size, protection, flags, fd, offset);
  146. }
  147. }
  148. inline bool MallocHook::InvokeMmapReplacement(const void* start,
  149. size_t size,
  150. int protection,
  151. int flags,
  152. int fd,
  153. off_t offset,
  154. void** result) {
  155. if (!base::internal::mmap_replacement_.empty()) {
  156. return InvokeMmapReplacementSlow(start, size,
  157. protection, flags,
  158. fd, offset,
  159. result);
  160. }
  161. return false;
  162. }
  163. // The following method is DEPRECATED
  164. inline MallocHook::MunmapHook MallocHook::GetMunmapHook() {
  165. return base::internal::munmap_hooks_.GetSingular();
  166. }
  167. inline void MallocHook::InvokeMunmapHook(const void* p, size_t size) {
  168. if (!base::internal::munmap_hooks_.empty()) {
  169. InvokeMunmapHookSlow(p, size);
  170. }
  171. }
  172. inline bool MallocHook::InvokeMunmapReplacement(
  173. const void* p, size_t size, int* result) {
  174. if (!base::internal::mmap_replacement_.empty()) {
  175. return InvokeMunmapReplacementSlow(p, size, result);
  176. }
  177. return false;
  178. }
  179. // The following method is DEPRECATED
  180. inline MallocHook::MremapHook MallocHook::GetMremapHook() {
  181. return base::internal::mremap_hooks_.GetSingular();
  182. }
  183. inline void MallocHook::InvokeMremapHook(const void* result,
  184. const void* old_addr,
  185. size_t old_size,
  186. size_t new_size,
  187. int flags,
  188. const void* new_addr) {
  189. if (!base::internal::mremap_hooks_.empty()) {
  190. InvokeMremapHookSlow(result, old_addr, old_size, new_size, flags, new_addr);
  191. }
  192. }
  193. // The following method is DEPRECATED
  194. inline MallocHook::PreSbrkHook MallocHook::GetPreSbrkHook() {
  195. return base::internal::presbrk_hooks_.GetSingular();
  196. }
  197. inline void MallocHook::InvokePreSbrkHook(ptrdiff_t increment) {
  198. if (!base::internal::presbrk_hooks_.empty() && increment != 0) {
  199. InvokePreSbrkHookSlow(increment);
  200. }
  201. }
  202. // The following method is DEPRECATED
  203. inline MallocHook::SbrkHook MallocHook::GetSbrkHook() {
  204. return base::internal::sbrk_hooks_.GetSingular();
  205. }
  206. inline void MallocHook::InvokeSbrkHook(const void* result,
  207. ptrdiff_t increment) {
  208. if (!base::internal::sbrk_hooks_.empty() && increment != 0) {
  209. InvokeSbrkHookSlow(result, increment);
  210. }
  211. }
  212. #endif /* _MALLOC_HOOK_INL_H_ */