CMS 3D CMS Logo

memory_proxies.cc
Go to the documentation of this file.
1 #include <memory>
2 #include <cassert>
3 #include <atomic>
4 #include <cstddef>
5 #include <malloc.h>
6 
9 
10 #include <dlfcn.h> // dlsym
11 
12 #if !defined(__x86_64__) && !defined(__i386__)
13 #define USE_LOCAL_MALLOC
14 #endif
15 #if defined(__GLIBC__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ < 28)
16 //needed for sl7
17 #define USE_LOCAL_MALLOC
18 #endif
19 
20 namespace {
21  std::atomic<bool>& alloc_monitor_running_state() {
22  static std::atomic<bool> s_state = false;
23  return s_state;
24  }
25 
26  template <typename T>
27  T get(const char* iName) {
28  void* original = dlsym(RTLD_NEXT, iName);
30  return reinterpret_cast<T>(original);
31  }
32 
33 #ifdef USE_LOCAL_MALLOC
34  // this is a very simple-minded allocator used for any allocations
35  // before we've finished our setup. In particular, this avoids a
36  // chicken/egg problem if dlsym() allocates any memory.
37  // Size was chosen to be 2x what ARM64 uses as an emergency buffer
38  // for libstdc++ exception handling.
39  constexpr auto max_align = alignof(std::max_align_t);
40  alignas(max_align) char tmpbuff[131072];
41  unsigned long tmppos = 0;
42  unsigned long tmpallocs = 0;
43 
44  void* local_malloc(size_t size) noexcept {
45  // round up so next alloc is aligned
46  size = ((size + max_align - 1) / max_align) * max_align;
47  if (tmppos + size < sizeof(tmpbuff)) {
48  void* retptr = tmpbuff + tmppos;
49  tmppos += size;
50  ++tmpallocs;
51  return retptr;
52  } else {
53  return nullptr;
54  }
55  }
56 
57  //can use local_malloc since static memory buffers are guaranteed to be zero initialized
58  void* local_calloc(size_t nitems, size_t item_size) noexcept { return local_malloc(nitems * item_size); }
59 
60  inline bool is_local_alloc(void* ptr) noexcept { return ptr >= (void*)tmpbuff && ptr <= (void*)(tmpbuff + tmppos); }
61 
62  // the pointers in this struct should only be modified during
63  // global construction at program startup, so thread safety
64  // should not be an issue.
65  struct Originals {
66  inline static void init() noexcept {
67  if (not set) {
68  set = true; // must be first to avoid recursion
69  malloc = get<decltype(&::malloc)>("malloc");
70  calloc = get<decltype(&::calloc)>("calloc");
71  }
72  }
73  CMS_SA_ALLOW static decltype(&::malloc) malloc;
74  CMS_SA_ALLOW static decltype(&::calloc) calloc;
75  CMS_SA_ALLOW static bool set;
76  };
77 
78  decltype(&::malloc) Originals::malloc = local_malloc;
79  decltype(&::calloc) Originals::calloc = local_calloc;
80  bool Originals::set = false;
81 #else
82  constexpr inline bool is_local_alloc(void* ptr) noexcept { return false; }
83 #endif
84 } // namespace
85 
86 using namespace cms::perftools;
87 
88 extern "C" {
89 void alloc_monitor_start() { alloc_monitor_running_state() = true; }
90 void alloc_monitor_stop() { alloc_monitor_running_state() = false; }
91 
92 //----------------------------------------------------------------
93 //C memory functions
94 
95 #ifdef USE_LOCAL_MALLOC
96 void* malloc(size_t size) noexcept {
97  const auto original = Originals::malloc;
99  if (not alloc_monitor_running_state()) {
100  return original(size);
101  }
102  auto& reg = AllocMonitorRegistry::instance();
103  return reg.allocCalled(
104  size, [size, original]() { return original(size); }, [](auto ret) { return malloc_usable_size(ret); });
105 }
106 
107 void* calloc(size_t nitems, size_t item_size) noexcept {
108  const auto original = Originals::calloc;
109  Originals::init();
110  if (not alloc_monitor_running_state()) {
111  return original(nitems, item_size);
112  }
113  auto& reg = AllocMonitorRegistry::instance();
114  return reg.allocCalled(
115  nitems * item_size,
116  [nitems, item_size, original]() { return original(nitems, item_size); },
117  [](auto ret) { return malloc_usable_size(ret); });
118 }
119 #else
120 void* malloc(size_t size) noexcept {
121  CMS_SA_ALLOW static const auto original = get<decltype(&::malloc)>("malloc");
122  if (not alloc_monitor_running_state()) {
123  return original(size);
124  }
125  auto& reg = AllocMonitorRegistry::instance();
126  return reg.allocCalled(
127  size, [size]() { return original(size); }, [](auto ret) { return malloc_usable_size(ret); });
128 }
129 
130 void* calloc(size_t nitems, size_t item_size) noexcept {
131  CMS_SA_ALLOW static const auto original = get<decltype(&::calloc)>("calloc");
132  if (not alloc_monitor_running_state()) {
133  return original(nitems, item_size);
134  }
135  auto& reg = AllocMonitorRegistry::instance();
136  return reg.allocCalled(
137  nitems * item_size,
138  [nitems, item_size]() { return original(nitems, item_size); },
139  [](auto ret) { return malloc_usable_size(ret); });
140 }
141 #endif
142 
143 void* realloc(void* ptr, size_t size) noexcept {
144  CMS_SA_ALLOW static const auto original = get<decltype(&::realloc)>("realloc");
145  if (not alloc_monitor_running_state()) {
146  return original(ptr, size);
147  }
148  size_t oldsize = malloc_usable_size(ptr);
149  void* ret;
150  auto& reg = AllocMonitorRegistry::instance();
151  {
152  //incase this calls malloc/free
153  [[maybe_unused]] auto g = reg.makeGuard();
154  ret = original(ptr, size);
155  }
156  size_t used = malloc_usable_size(ret);
157  if (used != oldsize) {
158  reg.deallocCalled(
159  ptr, [](auto) {}, [oldsize](auto) { return oldsize; });
160  reg.allocCalled(
161  size, []() { return nullptr; }, [used](auto) { return used; });
162  }
163  return ret;
164 }
165 
166 void* aligned_alloc(size_t alignment, size_t size) noexcept {
167  CMS_SA_ALLOW static const auto original = get<decltype(&::aligned_alloc)>("aligned_alloc");
168  if (not alloc_monitor_running_state()) {
169  return original(alignment, size);
170  }
171 
172  auto& reg = AllocMonitorRegistry::instance();
173  return reg.allocCalled(
174  size,
175  [alignment, size]() { return original(alignment, size); },
176  [](auto ret) { return malloc_usable_size(ret); });
177 }
178 
179 //used by tensorflow
180 int posix_memalign(void** memptr, size_t alignment, size_t size) noexcept {
181  CMS_SA_ALLOW static const auto original = get<decltype(&::posix_memalign)>("posix_memalign");
182  if (not alloc_monitor_running_state()) {
183  return original(memptr, alignment, size);
184  }
185 
186  auto& reg = AllocMonitorRegistry::instance();
187  int ret;
188  reg.allocCalled(
189  size,
190  [&ret, memptr, alignment, size]() {
191  ret = original(memptr, alignment, size);
192  return *memptr;
193  },
194  [](auto ret) { return malloc_usable_size(ret); });
195  return ret;
196 }
197 
198 //used by libc
199 void* memalign(size_t alignment, size_t size) noexcept {
200  CMS_SA_ALLOW static const auto original = get<decltype(&::memalign)>("memalign");
201  if (not alloc_monitor_running_state()) {
202  return original(alignment, size);
203  }
204 
205  auto& reg = AllocMonitorRegistry::instance();
206  return reg.allocCalled(
207  size,
208  [alignment, size]() { return original(alignment, size); },
209  [](auto ret) { return malloc_usable_size(ret); });
210 }
211 
212 void free(void* ptr) noexcept {
213  CMS_SA_ALLOW static const auto original = get<decltype(&::free)>("free");
214  // ignore memory allocated from our static array at startup
215  if (not is_local_alloc(ptr)) {
216  if (not alloc_monitor_running_state()) {
217  original(ptr);
218  return;
219  }
220 
221  auto& reg = AllocMonitorRegistry::instance();
222  reg.deallocCalled(
223  ptr, [](auto ptr) { original(ptr); }, [](auto ptr) { return malloc_usable_size(ptr); });
224  }
225 }
226 } // extern "C"
227 
228 //----------------------------------------------------------------
229 //C++ memory functions
230 
231 #define CPP_MEM_OVERRIDE
232 
233 #if defined(CPP_MEM_OVERRIDE)
234 #include <new>
235 
236 void* operator new(std::size_t size) {
237  CMS_SA_ALLOW static const auto original = get<void* (*)(std::size_t)>("_Znwm");
238  if (not alloc_monitor_running_state()) {
239  return original(size);
240  }
241 
242  auto& reg = AllocMonitorRegistry::instance();
243  return reg.allocCalled(
244  size, [size]() { return original(size); }, [](auto ret) { return malloc_usable_size(ret); });
245 } //_Znwm
246 
247 void operator delete(void* ptr) noexcept {
248  CMS_SA_ALLOW static const auto original = get<void (*)(void*)>("_ZdlPv");
249  if (not alloc_monitor_running_state()) {
250  original(ptr);
251  return;
252  }
253 
254  auto& reg = AllocMonitorRegistry::instance();
255  reg.deallocCalled(
256  ptr, [](auto ptr) { original(ptr); }, [](auto ptr) { return malloc_usable_size(ptr); });
257 } //_ZdlPv
258 
259 void* operator new[](std::size_t size) {
260  CMS_SA_ALLOW static const auto original = get<void* (*)(std::size_t)>("_Znam");
261  if (not alloc_monitor_running_state()) {
262  return original(size);
263  }
264 
265  auto& reg = AllocMonitorRegistry::instance();
266  return reg.allocCalled(
267  size, [size]() { return original(size); }, [](auto ret) { return malloc_usable_size(ret); });
268 } //_Znam
269 
270 void operator delete[](void* ptr) noexcept {
271  CMS_SA_ALLOW static const auto original = get<void (*)(void*)>("_ZdaPv");
272 
273  if (not alloc_monitor_running_state()) {
274  original(ptr);
275  return;
276  }
277  auto& reg = AllocMonitorRegistry::instance();
278  reg.deallocCalled(
279  ptr, [](auto ptr) { original(ptr); }, [](auto ptr) { return malloc_usable_size(ptr); });
280 } //_ZdaPv
281 
282 void* operator new(std::size_t size, std::align_val_t al) {
283  CMS_SA_ALLOW static const auto original = get<void* (*)(std::size_t, std::align_val_t)>("_ZnwmSt11align_val_t");
284  if (not alloc_monitor_running_state()) {
285  return original(size, al);
286  }
287 
288  auto& reg = AllocMonitorRegistry::instance();
289  return reg.allocCalled(
290  size, [size, al]() { return original(size, al); }, [](auto ret) { return malloc_usable_size(ret); });
291 } //_ZnwmSt11align_val_t
292 
293 void* operator new[](std::size_t size, std::align_val_t al) {
294  CMS_SA_ALLOW static const auto original = get<void* (*)(std::size_t, std::align_val_t)>("_ZnamSt11align_val_t");
295 
296  if (not alloc_monitor_running_state()) {
297  return original(size, al);
298  }
299 
300  auto& reg = AllocMonitorRegistry::instance();
301  return reg.allocCalled(
302  size, [size, al]() { return original(size, al); }, [](auto ret) { return malloc_usable_size(ret); });
303 } //_ZnamSt11align_val_t
304 
305 void* operator new(std::size_t size, const std::nothrow_t& tag) noexcept {
306  CMS_SA_ALLOW static const auto original =
307  get<void* (*)(std::size_t, const std::nothrow_t&) noexcept>("_ZnwmRKSt9nothrow_t");
308 
309  if (not alloc_monitor_running_state()) {
310  return original(size, tag);
311  }
312 
313  auto& reg = AllocMonitorRegistry::instance();
314  return reg.allocCalled(
315  size, [size, &tag]() { return original(size, tag); }, [](auto ret) { return malloc_usable_size(ret); });
316 } //_ZnwmRKSt9nothrow_t
317 
318 void* operator new[](std::size_t size, const std::nothrow_t& tag) noexcept {
319  CMS_SA_ALLOW static const auto original =
320  get<void* (*)(std::size_t, const std::nothrow_t&) noexcept>("_ZnamRKSt9nothrow_t");
321 
322  if (not alloc_monitor_running_state()) {
323  return original(size, tag);
324  }
325 
326  auto& reg = AllocMonitorRegistry::instance();
327  return reg.allocCalled(
328  size, [size, &tag]() { return original(size, tag); }, [](auto ret) { return malloc_usable_size(ret); });
329 } //_ZnamRKSt9nothrow_t
330 
331 void* operator new(std::size_t size, std::align_val_t al, const std::nothrow_t& tag) noexcept {
332  CMS_SA_ALLOW static const auto original =
333  get<void* (*)(std::size_t, std::align_val_t, const std::nothrow_t&) noexcept>(
334  "_ZnwmSt11align_val_tRKSt9nothrow_t");
335 
336  if (not alloc_monitor_running_state()) {
337  return original(size, al, tag);
338  }
339 
340  auto& reg = AllocMonitorRegistry::instance();
341  return reg.allocCalled(
342  size, [size, al, &tag]() { return original(size, al, tag); }, [](auto ret) { return malloc_usable_size(ret); });
343 } //_ZnwmSt11align_val_tRKSt9nothrow_t
344 
345 void* operator new[](std::size_t size, std::align_val_t al, const std::nothrow_t& tag) noexcept {
346  CMS_SA_ALLOW static const auto original =
347  get<void* (*)(std::size_t, std::align_val_t, const std::nothrow_t&) noexcept>(
348  "_ZnamSt11align_val_tRKSt9nothrow_t");
349 
350  if (not alloc_monitor_running_state()) {
351  return original(size, al, tag);
352  }
353 
354  auto& reg = AllocMonitorRegistry::instance();
355  return reg.allocCalled(
356  size, [size, al, &tag]() { return original(size, al, tag); }, [](auto ret) { return malloc_usable_size(ret); });
357 } //_ZnamSt11align_val_tRKSt9nothrow_t
358 
359 void operator delete(void* ptr, std::align_val_t al) noexcept {
360  CMS_SA_ALLOW static const auto original = get<void (*)(void*, std::align_val_t) noexcept>("_ZdlPvSt11align_val_t");
361 
362  if (not alloc_monitor_running_state()) {
363  original(ptr, al);
364  return;
365  }
366  auto& reg = AllocMonitorRegistry::instance();
367  reg.deallocCalled(
368  ptr, [al](auto ptr) { original(ptr, al); }, [](auto ptr) { return malloc_usable_size(ptr); });
369 } //_ZdlPvSt11align_val_t
370 
371 void operator delete[](void* ptr, std::align_val_t al) noexcept {
372  CMS_SA_ALLOW static const auto original = get<void (*)(void*, std::align_val_t) noexcept>("_ZdaPvSt11align_val_t");
373 
374  if (not alloc_monitor_running_state()) {
375  original(ptr, al);
376  return;
377  }
378  auto& reg = AllocMonitorRegistry::instance();
379  reg.deallocCalled(
380  ptr, [al](auto ptr) { original(ptr, al); }, [](auto ptr) { return malloc_usable_size(ptr); });
381 } //_ZdaPvSt11align_val_t
382 
383 void operator delete(void* ptr, std::size_t sz) noexcept {
384  CMS_SA_ALLOW static const auto original = get<void (*)(void*, std::size_t) noexcept>("_ZdlPvm");
385 
386  if (not alloc_monitor_running_state()) {
387  original(ptr, sz);
388  return;
389  }
390  auto& reg = AllocMonitorRegistry::instance();
391  reg.deallocCalled(
392  ptr, [sz](auto ptr) { original(ptr, sz); }, [](auto ptr) { return malloc_usable_size(ptr); });
393 } //_ZdlPvm
394 
395 void operator delete[](void* ptr, std::size_t sz) noexcept {
396  CMS_SA_ALLOW static const auto original = get<void (*)(void*, std::size_t) noexcept>("_ZdaPvm");
397 
398  if (not alloc_monitor_running_state()) {
399  original(ptr, sz);
400  return;
401  }
402  auto& reg = AllocMonitorRegistry::instance();
403  reg.deallocCalled(
404  ptr, [sz](auto ptr) { original(ptr, sz); }, [](auto ptr) { return malloc_usable_size(ptr); });
405 } //_ZdaPvm
406 
407 void operator delete(void* ptr, std::size_t sz, std::align_val_t al) noexcept {
408  CMS_SA_ALLOW static const auto original =
409  get<void (*)(void*, std::size_t, std::align_val_t) noexcept>("_ZdlPvmSt11align_val_t");
410 
411  if (not alloc_monitor_running_state()) {
412  original(ptr, sz, al);
413  return;
414  }
415  auto& reg = AllocMonitorRegistry::instance();
416  reg.deallocCalled(
417  ptr, [sz, al](auto ptr) { original(ptr, sz, al); }, [](auto ptr) { return malloc_usable_size(ptr); });
418 } //_ZdlPvmSt11align_val_t
419 
420 void operator delete[](void* ptr, std::size_t sz, std::align_val_t al) noexcept {
421  CMS_SA_ALLOW static const auto original =
422  get<void (*)(void*, std::size_t, std::align_val_t) noexcept>("_ZdaPvmSt11align_val_t");
423 
424  if (not alloc_monitor_running_state()) {
425  original(ptr, sz, al);
426  return;
427  }
428  auto& reg = AllocMonitorRegistry::instance();
429  reg.deallocCalled(
430  ptr, [sz, al](auto ptr) { original(ptr, sz, al); }, [](auto ptr) { return malloc_usable_size(ptr); });
431 } //_ZdaPvmSt11align_val_t
432 
433 void operator delete(void* ptr, const std::nothrow_t& tag) noexcept {
434  CMS_SA_ALLOW static const auto original =
435  get<void (*)(void*, const std::nothrow_t&) noexcept>("_ZdlPvRKSt9nothrow_t");
436 
437  if (not alloc_monitor_running_state()) {
438  original(ptr, tag);
439  return;
440  }
441  auto& reg = AllocMonitorRegistry::instance();
442  reg.deallocCalled(
443  ptr, [&tag](auto ptr) { original(ptr, tag); }, [](auto ptr) { return malloc_usable_size(ptr); });
444 } //_ZdlPvRKSt9nothrow_t
445 
446 void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept {
447  CMS_SA_ALLOW static const auto original =
448  get<void (*)(void*, const std::nothrow_t&) noexcept>("_ZdaPvRKSt9nothrow_t");
449 
450  if (not alloc_monitor_running_state()) {
451  original(ptr, tag);
452  return;
453  }
454  auto& reg = AllocMonitorRegistry::instance();
455  reg.deallocCalled(
456  ptr, [&tag](auto ptr) { original(ptr, tag); }, [](auto ptr) { return malloc_usable_size(ptr); });
457 } //_ZdaPvRKSt9nothrow_t
458 
459 void operator delete(void* ptr, std::align_val_t al, const std::nothrow_t& tag) noexcept {
460  CMS_SA_ALLOW static const auto original =
461  get<void (*)(void*, std::align_val_t, const std::nothrow_t&) noexcept>("_ZdlPvSt11align_val_tRKSt9nothrow_t");
462 
463  if (not alloc_monitor_running_state()) {
464  original(ptr, al, tag);
465  return;
466  }
467  auto& reg = AllocMonitorRegistry::instance();
468  reg.deallocCalled(
469  ptr, [al, &tag](auto ptr) { original(ptr, al, tag); }, [](auto ptr) { return malloc_usable_size(ptr); });
470 } //_ZdlPvSt11align_val_tRKSt9nothrow_t
471 
472 void operator delete[](void* ptr, std::align_val_t al, const std::nothrow_t& tag) noexcept {
473  CMS_SA_ALLOW static const auto original =
474  get<void (*)(void*, std::align_val_t, const std::nothrow_t&) noexcept>("_ZdaPvSt11align_val_tRKSt9nothrow_t");
475 
476  if (not alloc_monitor_running_state()) {
477  original(ptr, al, tag);
478  return;
479  }
480  auto& reg = AllocMonitorRegistry::instance();
481  reg.deallocCalled(
482  ptr, [al, &tag](auto ptr) { original(ptr, al, tag); }, [](auto ptr) { return malloc_usable_size(ptr); });
483 } //_ZdaPvSt11align_val_tRKSt9nothrow_t
484 
485 #endif
size
Write out results.
#define CMS_SA_ALLOW
ret
prodAgent to be discontinued
int init
Definition: HydjetWrapper.h:66
int posix_memalign(void **memptr, size_t alignment, size_t size) noexcept
assert(be >=bs)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
void free(void *ptr) noexcept
static AllocMonitorRegistry & instance()
void * aligned_alloc(size_t alignment, size_t size) noexcept
void * malloc(size_t size) noexcept
void * realloc(void *ptr, size_t size) noexcept
void alloc_monitor_start()
void * memalign(size_t alignment, size_t size) noexcept
void alloc_monitor_stop()
long double T
void * calloc(size_t nitems, size_t item_size) noexcept