ATLAS Offline Software
memory_hooks-stdcmalloc.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // memory_hooks which are used for the AthMemoryAuditor
6 // Rolf Seuster, August 2015
7 
8 #ifndef ATHENAAUDITORS_MEMORYHOOKSSTDCMALLOC_H
9 #define ATHENAAUDITORS_MEMORYHOOKSSTDCMALLOC_H
10 
11 // This auditor is not thread-safe without significant work.
12 // Disable checking for now.
13 // We'll also report an ERROR is this is used in an MT job.
16 
17 #include "CxxUtils/features.h"
18 
19 #include <iostream>
20 #include <fstream>
21 #include <iomanip>
22 
23 #include <map>
24 
25 /* for Prototypes for __malloc_hook, __free_hook */
26 #include <malloc.h>
27 
28 #include <cstdint>
29 #include <string.h>
30 #include <stdlib.h> // for getenv
31 
32 // needed for placement new
33 #include <new>
34 
35 static std::string name;
36 
37 //#define MYDEBUG
38 #undef MYDEBUG
39 
40 #ifdef MYDEBUG
41 static void printAllocation( void*ptr, size_t n );
42 #endif // MYDEBUG
43 
44 #ifdef __GNUC__
45 # pragma GCC diagnostic push
46 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
47 #endif
48 
49 /* structure of redzones:
50  bytes 0- 7: pointer to next
51  bytes 8-15: pointer to prev
52  bytes 16-17: delta to payload
53  bytes 18-23: size of payload
54  bytes 24-31: ascii " redzone"
55 
56  payload -22-23: delta to payload
57  payload -16-21: size of payload
58  payload - 7 -0: ascii " redzone"
59  // last three might be same as above, will be different for 'memalign' with alignment > 32
60 
61  payload
62 
63  payload +0-7: ascii "enozder "
64  payload 8-15: size of payload
65  payload +16-19: stage
66  payload +20-23: index to algorithm name
67  */
68 
69 // deltaLow must be multiple of 16 - Eigen / AV requires this alignment
70 const unsigned int deltaLow=32;
71 const unsigned int deltaHigh=32;
72 
73 class node
74 {
75  public:
77  m_sizeHigh(0), m_sizeLow(0)
78  {
79  m_canary[0]='r'; m_canary[1]='e'; m_canary[2]='d'; m_canary[3]='z';
80  m_canary[4]='o'; m_canary[5]='n'; m_canary[6]='e'; m_canary[7]=' ';
81  };
83  m_sizeHigh(0), m_sizeLow(0)
84  {
85  m_canary[0]='r'; m_canary[1]='e'; m_canary[2]='d'; m_canary[3]='z';
86  m_canary[4]='o'; m_canary[5]='n'; m_canary[6]='e'; m_canary[7]=' ';
87  };
88  node(bool b)
89  : m_sizeHigh(0), m_sizeLow(0)
90  {
91  if(b)
92  {
93  m_next=0;
94  m_prev=0;
95  m_deltaPayload=32;
96  m_canary[0]='r'; m_canary[1]='e'; m_canary[2]='d'; m_canary[3]='z';
97  m_canary[4]='o'; m_canary[5]='n'; m_canary[6]='e'; m_canary[7]=' ';
98  }
99  };
100  void setNext(node* n) { m_next=n; };
101  void setPrev(node* p) { m_prev=p; };
102  node* getNext() { return m_next; };
103  node* getPrev() { return m_prev; };
104  void setSize(size_t s) { m_sizeLow=(uint32_t)(s&0xFFFFFFFF); m_sizeHigh=(s>>32); };
105  size_t getSize() { return (size_t)m_sizeLow+(((size_t)m_sizeHigh)<<32); };
107  void fillRedZone()
108  {
109  m_canary[0]='r'; m_canary[1]='e'; m_canary[2]='d'; m_canary[3]='z';
110  m_canary[4]='o'; m_canary[5]='n'; m_canary[6]='e'; m_canary[7]=' ';
111  };
112 
113  private:
119  char m_canary[8];
120 };
121 
122 class redzone
123 {
124 public:
125  redzone() : m_s(0), m_stage(0), m_algIndex(0)
126  {
127  m_canary[0] ='e'; m_canary[1] ='n'; m_canary[2] ='o'; m_canary[3] ='z';
128  m_canary[4] ='d'; m_canary[5] ='e'; m_canary[6] ='r'; m_canary[7] =' ';
129  m_canary[8] ='r'; m_canary[9] ='e'; m_canary[10]='d'; m_canary[11]='z';
130  m_canary[12]='o'; m_canary[13]='n'; m_canary[14]='e'; m_canary[15]=' ';
131  };
132  redzone(bool b)
133  {
134  if(b)
135  {
136  m_s=0;
137  m_stage=0;
138  m_algIndex=0;
139  m_canary[0] ='e'; m_canary[1] ='n'; m_canary[2] ='o'; m_canary[3] ='z';
140  m_canary[4] ='d'; m_canary[5] ='e'; m_canary[6] ='r'; m_canary[7] =' ';
141  m_canary[8] ='r'; m_canary[9] ='e'; m_canary[10]='d'; m_canary[11]='z';
142  m_canary[12]='o'; m_canary[13]='n'; m_canary[14]='e'; m_canary[15]=' ';
143  }
144  };
145  redzone(size_t s, uint32_t st, uint32_t ai) : m_s(s), m_stage(st), m_algIndex(ai)
146  {
147  m_canary[0] ='e'; m_canary[1] ='n'; m_canary[2] ='o'; m_canary[3] ='z';
148  m_canary[4] ='d'; m_canary[5] ='e'; m_canary[6] ='r'; m_canary[7] =' ';
149  m_canary[8] ='R'; m_canary[9] ='E'; m_canary[10]='D'; m_canary[11]='-';
150  m_canary[12]='Z'; m_canary[13]='O'; m_canary[14]='N'; m_canary[15]='E';
151  };
152  size_t getSize() { return m_s; };
153  uint32_t getStage() { return m_stage; };
154  void clearStage() { m_stage=0; };
156 
157 private:
158  char m_canary[16];
159  size_t m_s;
162 };
163 
164 static node s_first;
165 static node s_last;
166 
167 /* Prototypes for our hooks. */
168 static void my_init_hook (void);
169 #if HAVE_MALLOC_HOOKS
170 static void *my_malloc_hook (size_t, const void *);
171 static void *my_realloc_hook (void *, size_t, const void *);
172 static void *my_memalign_hook (size_t, size_t, const void *);
173 static void my_free_hook (void*, const void *);
174 #endif
175 
176 // static void *my_malloc_hook_fini (size_t, const void *);
177 // static void *my_realloc_hook_fini (void *, size_t, const void *);
178 // static void *my_memalign_hook_fini (size_t, size_t, const void *);
179 
180 #if HAVE_MALLOC_HOOKS
181 static void *(*old_malloc_hook)(size_t, const void *);
182 static void *(*old_realloc_hook)(void *, size_t, const void *);
183 static void *(*old_memalign_hook)(size_t, size_t, const void *);
184 static void (*old_free_hook)(void*, const void *);
185 #endif
186 
187 // various counters needed
188 static long long counter_m(0);
189 static long long counter_f(0);
190 static long long counter_fna(0);
191 static long long counter_r(0);
192 static long long counter_rs(0);
193 static long long counter_rnr(0);
194 static long long counter_rg(0);
195 static long long counter_rm(0);
196 static long long counter_rf(0);
197 static long long counter_ma(0);
198 
202 
203 #if HAVE_MALLOC_HOOKS
204 static void *my_malloc_hook (size_t size, const void* /* caller */)
205 {
206  uintptr_t result(0);
207  /* Restore all old hooks */
208  __malloc_hook = old_malloc_hook;
209  __realloc_hook = old_realloc_hook;
210  __memalign_hook = old_memalign_hook;
211  __free_hook = old_free_hook;
212  /* Call recursively */
213 
214  result = (uintptr_t) malloc (size+deltaLow+deltaHigh);
215 
216  if ( ! finished )
217  {
218  node* n = new ((void*)result) node( s_first.getNext(), &s_first );
219  s_first.getNext()->setPrev(n);
220  s_first.setNext(n);
221  n->setSize(size);
222 
223  counter_m++;
224 
225  // placement new of redzone, compiler complains about r unused ...
226  __attribute__ ((unused)) redzone *r = new ((void*)(result+deltaLow+size)) redzone( size, current_stage, curIndex );
227 
228  result+=deltaLow;
229 
230  myBlocks_tc *b = new myBlocks_tc( (uintptr_t)result, deltaLow, curIndex, current_stage, stacktraceDepth );
231  if(collectStacktraces)
232  unw_backtrace (b->allocatedFrom.data(), b->allocatedFrom.capacity());
233  allocSet_tc::iterator i = allocset_tc.find( *b );
234  if ( i == allocset_tc.end() )
235  {
236  allocset_tc.insert( *b );
237  }
238  else
239  {
240  std::cerr << "ALREADY EXISTRING " << std::hex << result << std::dec << "\n";
241  }
242  }
243  // if(finished)
244  // std::cerr << "MALLOC " << std::hex << result << " " << size << std::dec << "\n";
245 
246  /* Save underlying hooks */
247  old_malloc_hook = __malloc_hook;
248  old_realloc_hook = __realloc_hook;
249  old_memalign_hook = __memalign_hook;
250  old_free_hook = __free_hook;
251 
252  /* Restore our own hooks */
253  __malloc_hook = my_malloc_hook;
254  __realloc_hook = my_realloc_hook;
255  __memalign_hook = my_memalign_hook;
256  __free_hook = my_free_hook;
257  return (void*)result;
258 }
259 
260 static void
261 my_free_hook (void *ptr, const void* /* caller */)
262 {
263  /* Restore all old hooks */
264  __malloc_hook = old_malloc_hook;
265  __realloc_hook = old_realloc_hook;
266  __memalign_hook = old_memalign_hook;
267  __free_hook = old_free_hook;
268 
269  /* Call recursively */
270  // only free if allocation was done with redzone, i.e. above m_sbtr_ptr
271  // using uintptr_t to silence compiler warnings
272  uintptr_t p=(uintptr_t)ptr;
273 
274  // did we allocate this memory ?
275  bg_tc->allocated=p;
276  allocSet_tc::iterator i = allocset_tc.find( *bg_tc );
277  if ( i != allocset_tc.end() )
278  {
279  // first placement new with deltaLow to get deltaPayload - if different from 32, then second placement new
280  // at the right position
281  node* n=new ((void*)(p-deltaLow)) node(false);
282  // if(finished)
283  // std::cerr << "free: " << std::hex << p << " " << n << " " << n->getDeltaPayload() << " - " << deltaLow << std::dec << "\n";
284  if(n->getDeltaPayload() != deltaLow)
285  {
286  std::cerr << "free d: " << p << " " << n << " " << n->getDeltaPayload() << " - " << deltaLow << "\n";
287  }
288  // TEST p-=i->size;
289  p-=n->getDeltaPayload();
290 
291  node* nn=n->getNext();
292  node* np=n->getPrev();
293 
294  nn->setPrev(np);
295  np->setNext(nn);
296 
297 
298  allocset_tc.erase_and_dispose(i, allocSet_deleter());
299  }
300  else
301  {
302  // if(finished)
303  // std::cerr << "free na: " << std::hex << p << std::dec << "\n";
304  counter_fna++;
305  // FIXME fake to prevent rare crash in some jobs, leaks ...
306  if(finished)
307  p=0;
308  }
309  ptr=(void*)p;
310  free (ptr);
311 
312  /* Save underlying hooks */
313  old_malloc_hook = __malloc_hook;
314  old_realloc_hook = __realloc_hook;
315  old_memalign_hook = __memalign_hook;
316  old_free_hook = __free_hook;
317 
318  /* Restore our own hooks */
319  __malloc_hook = my_malloc_hook;
320  __realloc_hook = my_realloc_hook;
321  __memalign_hook = my_memalign_hook;
322  __free_hook = my_free_hook;
323  counter_f++;
324 }
325 
326 static void *
327 my_realloc_hook(void *ptr, size_t size, const void * /* caller */)
328 {
329  uintptr_t result(0);
330  /* Restore all old hooks */
331  __malloc_hook = old_malloc_hook;
332  __realloc_hook = old_realloc_hook;
333  __memalign_hook = old_memalign_hook;
334  __free_hook = old_free_hook;
335 
336  /* Call recursively */
337  size_t oldsize(0);
338  size_t sizeNoRedZones(size);
339  node* n(0);
340  node* nn(0);
341  node* np(0);
342  bool we_allocated(false);
343 
344  // using uintptr_t to silence compiler warnings
345  uintptr_t p=(uintptr_t)ptr;
346  // did initial allocation had redzones ?
347  bg_tc->allocated=p;
348  allocSet_tc::iterator i = allocset_tc.find( *bg_tc );
349  if ( i != allocset_tc.end() )
350  {
351  // yes - reduce p by size of redzone
352  p-=deltaLow;
353  // then we also know the size of the old allocation
354  n=new ((void*)p) node(false);
355  oldsize=n->getSize();
356  nn=n->getNext();
357  np=n->getPrev();
358  we_allocated=true;
359  }
360 
361  // size==0 means free'ing memory
362  if(size)
364  else
365  counter_rf++;
366 
367  // distinguish the case when used as free, modify linked list before deallocation
368  if (size == 0 && we_allocated )
369  {
370  nn->setPrev(np);
371  np->setNext(nn);
372 
373  // remove from list
374  allocset_tc.erase_and_dispose(i, allocSet_deleter());
375  }
376 
377  // call real realloc
378  // FIXME = initial allocation w/o redzone; allocate new memory, move around, add redzone (all via malloc ??) and free old one
379  result = (uintptr_t)realloc((void*)p, size);
380 
381  // if(finished)
382  // std::cerr << "REALLOC " << std::hex << result << " " << size << " " << p << std::dec << "\n";
383 
384  // test, if we are dealing with a real allocation
385  // FIXME = initial allocation w/o redzone; and pointer same
386  if( size>0 && ! finished )
387  {
388  // we didn't allocate the payload
389  if ( ! we_allocated )
390  {
391  // realloc possibly moved the payload for us - but w/o redzones
392  char* start((char*)result);
393  for( int s(size-1-deltaLow-deltaHigh); s>=0; --s )
394  {
395  start[deltaLow+s]=start[s];
396  }
397  // fake exiting allocation without redzone
398  p=1;
399  }
400 
401  char* start((char*)result);
402 
403  // constructor with placement new, no overwriting of memory (parameter to constructor is false)
404  n = new ((void*)result) node(false);
405 
406  // same pointer ? Then just size was increased / decreased
407  if ( p == result )
408  {
409  // adjust new size
410  n->setSize(sizeNoRedZones);
411 
412  // put redzone at new end of allocation, silence compiler about unused variable
413  __attribute__ ((unused)) redzone *r = new ((void*)(result+deltaLow+sizeNoRedZones)) redzone( sizeNoRedZones, current_stage, curIndex );
414  if ( oldsize < sizeNoRedZones )
415  {
416  // fill extended memory with dummy value, conditons guarantee alloction is and was with redzones
417  memset((void*)(result+deltaLow+oldsize),0xaa,sizeNoRedZones-oldsize);
418  counter_rg++;
419  }
420  else
421  counter_rs++;
422  }
423  else
424  {
425  // different pointer, need to overwrite some values...
426  if ( p && (p != result ) && ( size > deltaLow+deltaHigh ) )
427  {
428  // check that memory was accounted for by us
429  if ( we_allocated )
430  {
431  n = new ((void*)result) node( nn, np );
432  nn->setPrev(n);
433  np->setNext(n);
434 
435  // size and redzone done later
436  if ( oldsize < sizeNoRedZones )
437  {
438  memset((void*)(result+deltaLow+oldsize),0xaa,sizeNoRedZones-oldsize);
439  }
440 
441  // remove old location from current list
442  allocset_tc.erase_and_dispose(i, allocSet_deleter());
443  }
444  else
445  // memory was not with redzones, but stayed at the same place in memory
446  {
447  for( int s(size-1-deltaLow-deltaHigh); s>=0; --s )
448  {
449  start[deltaLow+s]=start[s];
450  }
451  n = new ((void*)result) node( s_first.getNext(), &s_first );
452  s_first.getNext()->setPrev(n);
453  s_first.setNext(n);
454  }
455  }
456  // initial pointer was zero, so new allocation...
457  if ( p == 0 && ( result > 0 ) && ( size > deltaLow+deltaHigh ) )
458  {
459  n = new ((void*)result) node( s_first.getNext(), &s_first );
460  s_first.getNext()->setPrev(n);
461  s_first.setNext(n);
462 
463  memset((void*)(result+deltaLow),0x55,sizeNoRedZones);
464 
465  counter_rm++;
466  }
467 
468  // now create new entry at new position
469  myBlocks_tc *b = new myBlocks_tc( (uintptr_t)(result+deltaLow), deltaLow, curIndex, current_stage, stacktraceDepth );
470  if(collectStacktraces)
471  unw_backtrace (b->allocatedFrom.data(), b->allocatedFrom.capacity());
472  allocset_tc.insert( *b );
473 
474  //required for both
475  n->setSize(sizeNoRedZones);
476 
477  // placement new of redzone, compiler complains about r unused ...
478  __attribute__ ((unused)) redzone *r = new ((void*)(result+deltaLow+sizeNoRedZones)) redzone( sizeNoRedZones, current_stage, curIndex );
479  }
480  if (result > 0 )
481  result+=deltaLow;
482  }
483 
484  // very special case, realloc after finishing.
485  // need to move payload by the size of the first redzone and return pointer as is
486  if( size > 0 && finished && we_allocated )
487  {
488  // remove from list of allocations
489  nn->setPrev(np);
490  np->setNext(nn);
491 
492  // remove from list
493  allocset_tc.erase_and_dispose(i, allocSet_deleter());
494 
495  char* start((char*)result);
496  if ( size > deltaLow+deltaHigh )
497  // silence compiler warning
498  for( int s(0) ; s+deltaLow+deltaHigh<size; ++s )
499  {
500  start[s]=start[deltaLow+s];
501  }
502  }
503 
504  /* Save underlying hooks */
505  old_malloc_hook = __malloc_hook;
506  old_realloc_hook = __realloc_hook;
507  old_memalign_hook = __memalign_hook;
508  old_free_hook = __free_hook;
509 
510  /* Restore our own hooks */
511  __malloc_hook = my_malloc_hook;
512  __realloc_hook = my_realloc_hook;
513  __memalign_hook = my_memalign_hook;
514  __free_hook = my_free_hook;
515  counter_r++;
516  return (void*)result;
517 }
518 #endif
519 
520 /* static void * */
521 /* my_realloc_hook_new(void *ptr, size_t size, const void * /\* caller *\/) */
522 /* { */
523 /* uintptr_t result(0); */
524 /* /\* Restore all old hooks *\/ */
525 /* __malloc_hook = old_malloc_hook; */
526 /* __realloc_hook = old_realloc_hook; */
527 /* __memalign_hook = old_memalign_hook; */
528 /* __free_hook = old_free_hook; */
529 
530 /* /\* Call recursively *\/ */
531 /* size_t oldsize(0); */
532 /* size_t sizeNoRedZones(size); */
533 /* node* n(0); */
534 /* node* nn(0); */
535 /* node* np(0); */
536 
537 /* // using uintptr_t to silence compiler warnings */
538 /* uintptr_t p=(uintptr_t)ptr; */
539 /* // did initial allocation had redzones ? */
540 /* bg_tc->allocated=p; */
541 /* allocSet_tc::iterator i = allocset_tc.find( *bg_tc ); */
542 /* if ( i != allocset_tc.end() ) */
543 /* { */
544 /* // yes - reduce p by size of redzone */
545 /* p-=deltaLow; */
546 /* // then we also know the size of the old allocation */
547 /* n=new ((void*)p) node(false); */
548 /* oldsize=n->getSize(); */
549 /* nn=n->getNext(); */
550 /* np=n->getPrev(); */
551 
552 /* // distinguish the case when used as free, modify linked list before deallocation */
553 /* if ( size == 0 ) */
554 /* { */
555 /* nn->setPrev(np); */
556 /* np->setNext(nn); */
557 
558 /* // remove from list */
559 /* allocset_tc.erase_and_dispose(i, allocSet_deleter()); */
560 /* } */
561 /* } */
562 
563 /* // size==0 means free'ing memory */
564 /* if(size) */
565 /* size+=deltaLow+deltaHigh; */
566 /* else */
567 /* counter_rf++; */
568 
569 /* // call real realloc */
570 /* result = (uintptr_t)realloc((void*)p, size); */
571 
572 /* if(size>0) */
573 /* { */
574 /* // check if memory was accounted for by us */
575 /* if ( i == allocset_tc.end() ) */
576 /* { */
577 /* // memory was initially not with redzones - move memory by deltaLow */
578 /* char* start((char*)result); */
579 /* for( int s(size-1-deltaLow-deltaHigh); s>=0; --s ) */
580 /* { */
581 /* start[deltaLow+s]=start[s]; */
582 /* } */
583 /* n = new ((void*)result) node( s_first.getNext(), &s_first ); */
584 /* s_first.getNext()->setPrev(n); */
585 /* s_first.setNext(n); */
586 /* n->setSize(sizeNoRedZones); */
587 /* // cannot decide of grow or shrink */
588 /* counter_rnr++; */
589 /* } */
590 /* else */
591 /* { */
592 /* // constructor with placement new, no overwriting of memory (parameter to constructor is false) */
593 /* n = new ((void*)result) node(false); */
594 /* } */
595 
596 /* // same pointer ? Then just size was increased / decreased */
597 /* if ( p == result ) */
598 /* { */
599 /* // adjust new size */
600 /* n->setSize(sizeNoRedZones); */
601 
602 /* // put redzone at new end of allocation, silence compiler about unused variable */
603 /* __attribute__ ((unused)) redzone *r = new ((void*)(result+deltaLow+sizeNoRedZones)) redzone( sizeNoRedZones, current_stage, curIndex ); */
604 
605 /* // do we know oldsize ? I.e. had redzomes ? */
606 /* if ( i != allocset_tc.end() ) */
607 /* { */
608 /* if ( oldsize < sizeNoRedZones ) */
609 /* { */
610 /* // fill extended memory with dummy value, conditons guarantee alloction is and was with redzones */
611 /* memset((void*)(result+deltaLow+oldsize),0xaa,sizeNoRedZones-oldsize); */
612 /* counter_rg++; */
613 /* } */
614 /* else */
615 /* counter_rs++; */
616 /* } */
617 /* } */
618 /* else */
619 /* { */
620 /* // remove old allocation from list */
621 /* if ( i != allocset_tc.end() ) */
622 /* { */
623 /* // remove from list */
624 /* allocset_tc.erase_and_dispose(i, allocSet_deleter()); */
625 /* } */
626 
627 /* // different pointer, need to overwrite some values... */
628 /* if ( p && ( size > deltaLow+deltaHigh ) ) */
629 /* { */
630 /* n = new ((void*)result) node( nn, np ); */
631 /* nn->setPrev(n); */
632 /* np->setNext(n); */
633 
634 /* // size and redzone done later */
635 /* if ( oldsize < sizeNoRedZones ) */
636 /* { */
637 /* memset((void*)(result+deltaLow+oldsize),0xaa,sizeNoRedZones-oldsize); */
638 /* counter_rg++; */
639 /* } */
640 /* else */
641 /* counter_rs++; */
642 
643 /* // remove old location from current list */
644 /* allocset_tc.erase_and_dispose(i, allocSet_deleter()); */
645 /* } */
646 
647 /* // now create new entry at new position */
648 /* // myBlocks *b = new myBlocks( (uintptr_t)(result+deltaLow), deltaLow, stacktraceDepth ); */
649 /* myBlocks_tc *b = new myBlocks_tc( (uintptr_t)(result+deltaLow), deltaLow, curIndex, current_stage, stacktraceDepth ); */
650 /* if(collectStacktraces) */
651 /* unw_backtrace (b->allocatedFrom.data(), b->allocatedFrom.capacity()); */
652 /* allocSet_tc::iterator i = allocset_tc.find( *b ); */
653 /* if ( i == allocset_tc.end() ) */
654 /* { */
655 /* allocset_tc.insert( *b ); */
656 /* } */
657 
658 /* n->setSize(sizeNoRedZones); */
659 
660 /* // placement new of redzone, compiler complains about r unused ... */
661 /* __attribute__ ((unused)) redzone *r = new ((void*)(result+deltaLow+sizeNoRedZones)) redzone( sizeNoRedZones, current_stage, curIndex ); */
662 /* } */
663 /* } */
664 /* if (result > 0 ) */
665 /* result+=deltaLow; */
666 
667 /* /\* Save underlying hooks *\/ */
668 /* old_malloc_hook = __malloc_hook; */
669 /* old_realloc_hook = __realloc_hook; */
670 /* old_memalign_hook = __memalign_hook; */
671 /* old_free_hook = __free_hook; */
672 
673 /* /\* Restore our own hooks *\/ */
674 /* __malloc_hook = my_malloc_hook; */
675 /* __realloc_hook = my_realloc_hook; */
676 /* __memalign_hook = my_memalign_hook; */
677 /* __free_hook = my_free_hook; */
678 /* counter_r++; */
679 /* return (void*)result; */
680 /* } */
681 
682 #include <stdlib.h>
683 
684 #if HAVE_MALLOC_HOOKS
685 static void *
686 my_memalign_hook (size_t alignment, size_t size, const void * /* caller */ )
687 {
688  uintptr_t result;
689  /* Restore all old hooks */
690  __malloc_hook = old_malloc_hook;
691  __realloc_hook = old_realloc_hook;
692  __memalign_hook = old_memalign_hook;
693  __free_hook = old_free_hook;
694 
695  /* Call recursively */
696  uintptr_t delta(alignment);
697  while(delta<deltaLow)
698  delta+=alignment;
699 
700  result = (uintptr_t)memalign(alignment, size+delta+deltaHigh);
701 
702  // std::cerr << "RS ALIGN " << std::hex << std::setfill('0') << result << " " << alignment << " " << delta << std::dec << "\n";
703 
704  node* n = new ((void*)result) node( s_first.getNext(), &s_first, delta );
705  s_first.getNext()->setPrev(n);
706  s_first.setNext(n);
707  n->setSize(size);
708 
709  // placement new of redzone, compiler complains about r unused ...
710  __attribute__ ((unused)) redzone *r = new ((void*)(result+delta+size)) redzone( size, current_stage, curIndex );
711 
712  result+=delta;
713 
714  // myBlocks *b = new myBlocks( (uintptr_t)result, delta, stacktraceDepth );
715  myBlocks_tc *b = new myBlocks_tc( (uintptr_t)result, delta, curIndex, current_stage, stacktraceDepth );
716  if(collectStacktraces)
717  unw_backtrace (b->allocatedFrom.data(), b->allocatedFrom.capacity());
718  allocSet_tc::iterator i = allocset_tc.find( *b );
719  if ( i == allocset_tc.end() )
720  {
721  allocset_tc.insert( *b );
722  }
723 
724 #if HAVE_MALLOC_HOOKS
725  /* Save underlying hooks */
726  old_malloc_hook = __malloc_hook;
727  old_realloc_hook = __realloc_hook;
728  old_memalign_hook = __memalign_hook;
729  old_free_hook = __free_hook;
730 
731  /* Restore our own hooks */
732  __malloc_hook = my_malloc_hook;
733  __realloc_hook = my_realloc_hook;
734  __memalign_hook = my_memalign_hook;
735  __free_hook = my_free_hook;
736 #endif
737  counter_ma++;
738  return (void*)result;
739 }
740 #endif
741 
742 #ifdef MYDEBUG
743 
744 static int s_level;
745 
746 static
747 void
748 my_stop ()
749 {
750  s_level--;
751  std::cerr << "STOP " << s_level << "\n";
752  /* Restore all old hooks */
753  __malloc_hook = old_malloc_hook;
754  __realloc_hook = old_realloc_hook;
755  __memalign_hook = old_memalign_hook;
756  __free_hook = old_free_hook;
757 
758  old_malloc_hook = __malloc_hook;
759  old_realloc_hook = __realloc_hook;
760  old_memalign_hook = __memalign_hook;
761  old_free_hook = __free_hook;
762 }
763 
764 static
765 void
766 my_start ()
767 {
768  /* Restore our own hooks */
769  __malloc_hook = my_malloc_hook;
770  __realloc_hook = my_realloc_hook;
771  __memalign_hook = my_memalign_hook;
772  __free_hook = my_free_hook;
773 
774  s_level++;
775  std::cerr << "START " << s_level << "\n";
776 }
777 
778 static
779 void printAllocation( void*ptr, size_t n )
780 {
781  bool hasRedzone=false;
782  unsigned char *cptr=(unsigned char*)ptr;
783  int nread;
784  unsigned char buf[16];
785 
786  std::cerr << "Printing information about allocation at: " << ptr << " of size " << n << "\n";
787 
788  std::cerr << "Payload:\n";
789  std::cerr << std::hex << std::setfill('0');
790  for( unsigned int l(0); l<n; l+=16 )
791  {
792  for( nread = 0; nread < 16; nread++ )
793  buf[nread]= *(cptr+l+nread);
794 
795  // Show the hex codes
796  for( int i = 0; i < 16; i++ )
797  {
798  if( i % 8 == 0 ) std::cerr << ' ';
799  if( i < nread && l+i<n )
800  std::cerr << ' ' << std::setw(2) << (unsigned)buf[i];
801  else
802  std::cerr << " ";
803  }
804 
805  // Show printable characters
806  std::cerr << " >";
807  for( int i = 0; i < nread; i++)
808  {
809  if( buf[i] < 32 || buf[i] > 128 ) std::cerr << '.';
810  else std::cerr << buf[i];
811  }
812 
813  std::cerr << "<\n";
814  }
815 
816  if( hasRedzone )
817  {
818  std::cerr << "Redzone after" << "\n";
819  std::cerr << std::hex << std::setfill('0');
820  for( int l(0); l<32; l+=16 )
821  {
822  for( nread = 0; nread < 16; nread++ )
823  buf[nread]= *(cptr+n+l+nread);
824 
825  // Show the hex codes
826  for( int i = 0; i < 16; i++ )
827  {
828  if( i % 8 == 0 ) std::cerr << ' ';
829  if( i < nread )
830  std::cerr << ' ' << std::setw(2) << (unsigned int)buf[i];
831  else
832  std::cerr << " ";
833  }
834 
835  // Show printable characters
836  std::cerr << " >";
837  for( int i = 0; i < nread; i++)
838  {
839  if( buf[i] < 32 || buf[i] > 128 ) std::cerr << '.';
840  else std::cerr << buf[i];
841  }
842 
843  std::cerr << "<\n";
844  }
845  }
846  std::cerr << std::dec << "\n";
847 }
848 
849 static void my_test()
850 {
851  void *p0=malloc(20);
852  memset(p0,0x1,20);
853 
854  my_stop();
855  printAllocation(p0,20);
856  my_start();
857 
858  void *p1=malloc(32);
859  memset(p1,0x2,32);
860  void *pd=malloc(32);
861  memset(pd,0x7,32);
862 
863  my_stop();
864  printAllocation(p1,32);
865  my_start();
866 
867  void *p2=realloc(p1, 48);
868  my_stop();
869  std::cerr << "realloc : " << p2 << " " << p1 << "\n";
870  printAllocation(p2,48);
871  my_start();
872 
873  p1=realloc(p2, 32);
874  my_stop();
875  std::cerr << "realloc : " << p2 << " " << p1 << "\n";
876  printAllocation(p1,32);
877  my_start();
878 
879  p2=realloc(p0, 48);
880  my_stop();
881  std::cerr << "realloc : " << p2 << " " << p0 << "\n";
882  printAllocation(p2,48);
883  my_start();
884 
885  free(p2);
886  my_stop();
887  std::cerr << "free :\n";
888  printAllocation(pd,32);
889  my_start();
890 }
891 #endif // MYDEBUG
892 
893 static void
894 my_init_hook (void)
895 {
896  // for glibc's malloc called stdcmalloc for athena.py
897  // disable using mmap for large allocations
898  mallopt(M_MMAP_MAX, 0);
899  // disable fast bins
900  mallopt(M_MXFAST, 0);
901 
902 #ifdef MYDEBUG
903  // std::cerr << "INIT : " << s_sbrk_ptr << "\n";
904  std::cerr << "INIT : redzone before / after " << deltaLow << " / " << deltaHigh << " bytes\n";
905 
906  std::cerr << "INIT : sizes " << sizeof(node) << " / " << sizeof(redzone) << "\n";
907 
908  std::cerr << "INIT : s_first / s_last " << &s_first << " / " << &s_last << "\n";
909 #endif // MYDEBUG
910 
911  s_first.setNext(&s_last);
912  s_last.setPrev(&s_first);
913 
914  bg_tc = new myBlocks_tc();
915 
916 #if HAVE_MALLOC_HOOKS
917  // save underying old hooks
918  old_malloc_hook = __malloc_hook;
919  old_realloc_hook = __realloc_hook;
920  old_memalign_hook = __memalign_hook;
921  old_free_hook = __free_hook;
922  // set new hooks
923  __malloc_hook = my_malloc_hook;
924  __realloc_hook = my_realloc_hook;
925  __memalign_hook = my_memalign_hook;
926  __free_hook = my_free_hook;
927 #endif
928  initialized=true;
929 
930 #ifdef MYDEBUG
931  s_level=1;
932 #endif // MYDEBUG
933 }
934 
935 
936 #ifdef __GNUC__
937 # pragma GCC diagnostic pop
938 #endif
939 
940 
941 #endif
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
beamspotman.r
def r
Definition: beamspotman.py:676
bg_tc
myBlocks_tc * bg_tc
Definition: memory_hooks-common.h:107
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
node::getPrev
node * getPrev()
Definition: memory_hooks-stdcmalloc.h:103
features.h
Some additional feature test macros.
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
get_generator_info.result
result
Definition: get_generator_info.py:21
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
node::node
node(bool b)
Definition: memory_hooks-stdcmalloc.h:88
deltaLow
const unsigned int deltaLow
Definition: memory_hooks-stdcmalloc.h:70
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
node::setPrev
void setPrev(node *p)
Definition: memory_hooks-stdcmalloc.h:101
hist_file_dump.d
d
Definition: hist_file_dump.py:137
deltaHigh
const unsigned int deltaHigh
Definition: memory_hooks-stdcmalloc.h:71
redzone::m_s
size_t m_s
Definition: memory_hooks-stdcmalloc.h:159
mergePhysValFiles.start
start
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:14
plotBeamSpotCompare.x2
x2
Definition: plotBeamSpotCompare.py:218
redzone::redzone
redzone()
Definition: memory_hooks-stdcmalloc.h:125
node::setNext
void setNext(node *n)
Definition: memory_hooks-stdcmalloc.h:100
redzone::m_algIndex
uint32_t m_algIndex
Definition: memory_hooks-stdcmalloc.h:161
PlotPulseshapeFromCool.np
np
Definition: PlotPulseshapeFromCool.py:64
node::getDeltaPayload
uint16_t getDeltaPayload()
Definition: memory_hooks-stdcmalloc.h:106
xAOD::unsigned
unsigned
Definition: RingSetConf_v1.cxx:662
redzone::m_canary
char m_canary[16]
Definition: memory_hooks-stdcmalloc.h:155
myBlocks_tc::allocated
uintptr_t allocated
Definition: memory_hooks-common.h:68
redzone
Definition: memory_hooks-stdcmalloc.h:123
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
allocSet_deleter
std::default_delete< myBlocks_tc > allocSet_deleter
Definition: memory_hooks-common.h:110
myBlocks_tc
Definition: memory_hooks-common.h:66
xAOD::uint16_t
setWord1 uint16_t
Definition: eFexEMRoI_v1.cxx:88
node::setSize
void setSize(size_t s)
Definition: memory_hooks-stdcmalloc.h:104
lumiFormat.i
int i
Definition: lumiFormat.py:92
python.DecayParser.buf
buf
print ("=> [%s]"cmd)
Definition: DecayParser.py:27
python.LArBadChannelDBAlg.xFFFFFFFF
xFFFFFFFF
Definition: LArBadChannelDBAlg.py:73
redzone::getSize
size_t getSize()
Definition: memory_hooks-stdcmalloc.h:152
beamspotman.n
n
Definition: beamspotman.py:731
TrigInDetValidation_Base.malloc
malloc
Definition: TrigInDetValidation_Base.py:124
node::node
node()
Definition: memory_hooks-stdcmalloc.h:76
SG::ArenaBlockAlignDetail::alignment
constexpr size_t alignment
Definition: ArenaBlockAlignDetail.h:39
redzone::getStage
uint32_t getStage()
Definition: memory_hooks-stdcmalloc.h:153
PyPoolBrowser.node
node
Definition: PyPoolBrowser.py:131
node::m_deltaPayload
uint16_t m_deltaPayload
Definition: memory_hooks-stdcmalloc.h:116
redzone::redzone
redzone(size_t s, uint32_t st, uint32_t ai)
Definition: memory_hooks-stdcmalloc.h:145
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
redzone::m_stage
uint32_t m_stage
Definition: memory_hooks-stdcmalloc.h:160
node::getNext
node * getNext()
Definition: memory_hooks-stdcmalloc.h:102
node::fillRedZone
void fillRedZone()
Definition: memory_hooks-stdcmalloc.h:107
beamspotCoolDiff.l
l
Definition: beamspotCoolDiff.py:354
unused
void unused(Args &&...)
Definition: VP1ExpertSettings.cxx:31
node::m_sizeHigh
uint16_t m_sizeHigh
Definition: memory_hooks-stdcmalloc.h:117
__attribute__
__attribute__((always_inline)) inline uint16_t TileCalibDrawerBase
Definition: TileCalibDrawerBase.h:190
node::m_prev
node * m_prev
Definition: memory_hooks-stdcmalloc.h:115
node::m_next
node * m_next
Definition: memory_hooks-stdcmalloc.h:111
ATLAS_NO_CHECK_FILE_THREAD_SAFETY
ATLAS_NO_CHECK_FILE_THREAD_SAFETY
Definition: memory_hooks-stdcmalloc.h:15
redzone::redzone
redzone(bool b)
Definition: memory_hooks-stdcmalloc.h:132
redzone::getAlgIndex
uint32_t getAlgIndex()
Definition: memory_hooks-stdcmalloc.h:155
redzone::clearStage
void clearStage()
Definition: memory_hooks-stdcmalloc.h:154
node::m_sizeLow
uint32_t m_sizeLow
Definition: memory_hooks-stdcmalloc.h:118
checker_macros.h
Define macros for attributes used to control the static checker.
node::m_canary
char m_canary[8]
Definition: memory_hooks-stdcmalloc.h:119
node
Definition: memory_hooks-stdcmalloc.h:74
node::getSize
size_t getSize()
Definition: memory_hooks-stdcmalloc.h:105
node::node
node(node *n, node *p, uint16_t d=deltaLow)
Definition: memory_hooks-stdcmalloc.h:82