| The Gaudi Framework v30r0 (c919700c)

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

IgHook_IgHookTrace.cpp
Go to the documentation of this file.
1 //<<<<<< INCLUDES >>>>>>
2
3 #include "IgHook_IgHookTrace.h"
4 #include <cstdio>
5 #include <cstdlib>
6 #include <dlfcn.h>
7 #include <sys/mman.h>
8 #include <unistd.h>
9 #if __linux
10 #include <execinfo.h>
11 #include <sys/syscall.h>
12 #include <ucontext.h>
13 #if __x86_64__
14 #define UNW_LOCAL_ONLY
15 #include <libunwind.h>
16 #endif
17 #endif
18 #if __APPLE__
19 extern "C" void _sigtramp( void );
20 #endif
21
22 //<<<<<< PRIVATE DEFINES >>>>>>
23
24 #if !defined MAP_ANONYMOUS && defined MAP_ANON
25 #define MAP_ANONYMOUS MAP_ANON
26 #endif
27
28 //<<<<<< PRIVATE CONSTANTS >>>>>>
29 //<<<<<< PRIVATE TYPES >>>>>>
30 //<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>>
31 //<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>>
32 //<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>>
33 //<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>>
34
35 #if 0 && __x86_64__ && __linux
36 // Linux x86-64 does not use regular call frames, like IA-32 does for
37 // example, and it would be a very difficult job to decipher the call
38 // stack. In order to walk the call stack correctly, we have to use
39 // the DWARF-2 unwind data. This alone is incredibly, uselessly slow
40 // for our purposes.
41 //
42 // We avoid using the unwind data by caching frame structures for
43 // recently seen functions. This is slow to start with, but very
44 // quickly gets fast enough for our purposes. Fortunately the x86-64
45 // unwind library appears to be robust enough to be called in signal
46 // handlers (unlike at least some IA-32 versions).
47 //
48 // The cache consists of two arrays arranged as an open-addressed
49 // unprobed hash table. Hash collisions overwrite the entry with the
50 // latest data. We try to avoid making this a problem by using a
51 // high-quality hash function and pure brute force in the form of a
52 // large hash table. A couple of megabytes goes a long way to help!
53 //
54 // The first of the cache arrays, of "void *", tracks program counter
55 // addresses. A parallel array of "int" tracks the size of the call
56 // frame at that address. Given a program counter and the canonical
57 // frame address (CFA) of the previous (= above) call frame, the new
58 // frame address is the previous plus the delta. We find the address
59 // of the caller just above this new frame address.
60 //
61 // We use the cache as long as we can find the addresses there. When
62 // we fall off the cache, we resort to the language run time unwinder.
63
64 struct IgHookTraceArgs
65 {
66 struct
67 {
68 void **pc;
69 int **frame;
70 } cache;
71 struct
72 {
73 void **addresses;
74 int top;
75 int size;
76 } stack;
77 void **prevframe;
78 };
79
80 static _Unwind_Reason_Code
81 GCCBackTrace (_Unwind_Context *context, void *arg)
82 {
83 IgHookTraceArgs *args = (IgHookTraceArgs *) arg;
84 if (args->stack.top < 0 || args->stack.top >= args->stack.size)
85 return _URC_END_OF_STACK;
86
87 args->stack.addresses [args->stack.top++] = (void *) _Unwind_GetIP (context);
88 args->prevframe = (void **) _Unwind_GetCFA (context);
89 return _URC_NO_REASON;
90 }
91 #endif
92
93 //<<<<<< PUBLIC FUNCTION DEFINITIONS >>>>>>
94 //<<<<<< MEMBER FUNCTION DEFINITIONS >>>>>>
95
99 IgHookTraceAlloc::IgHookTraceAlloc( void ) : m_pool( 0 ), m_left( 0 ) {}
100
101 void* IgHookTraceAlloc::allocate( size_t bytes )
102 {
103 // The reason for the existence of this class is to allocate
104 // memory directly using mmap() so we don't create calls to
105 // malloc() and friends. This is for two reasons: it must be
106 // possible to use this in asynchronous signal handlers, and
107 // calling malloc() in those is a really bad idea; and this is
108 // meant to be used by profiling code and it's nicer to not
109 // allocate memory in ways tracked by the profiler.
110 if ( m_left < bytes ) {
111 size_t psize = getpagesize();
112 size_t hunk = psize * 20;
113 if ( hunk < bytes ) hunk = ( hunk + psize - 1 ) & ~( psize - 1 );
114 void* addr = mmap( 0, hunk, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 );
115 if ( addr == MAP_FAILED ) return 0;
116
117 m_pool = addr;
118 m_left = hunk;
119 }
120
121 void* ptr = m_pool;
122 m_pool = (char*)m_pool + bytes;
123 m_left -= bytes;
124 return ptr;
125 }
126
130 void* IgHookTrace::CounterValue::operator new( size_t n, IgHookTraceAlloc* alloc /* = 0 */ )
131 {
132 return alloc ? alloc->allocate( n ) : ::operator new( n );
133 }
134
135 IgHookTrace::CounterValue::CounterValue( Counter* counter, CounterValue* next /* = 0 */,
136 unsigned long long value /* = 0 */ )
137 : m_counter( counter ), m_next( next ), m_value( value ), m_count( 0 )
138 {
139 }
140
141 IgHookTrace::Counter* IgHookTrace::CounterValue::counter( void ) { return m_counter; }
142
143 IgHookTrace::CounterValue* IgHookTrace::CounterValue::next( void ) { return m_next; }
144
145 unsigned long long IgHookTrace::CounterValue::value( void ) { return m_value; }
146
147 unsigned long long IgHookTrace::CounterValue::count( void ) { return m_count; }
148
149 unsigned long long IgHookTrace::CounterValue::tick( void )
150 {
151 ++m_count;
152 return ++m_value;
153 }
154
155 unsigned long long IgHookTrace::CounterValue::untick( void )
156 {
157 --m_count;
158 return --m_value;
159 }
160
161 unsigned long long IgHookTrace::CounterValue::add( unsigned long long value )
162 {
163 ++m_count;
164 return m_value += value;
165 }
166
167 unsigned long long IgHookTrace::CounterValue::sub( unsigned long long value )
168 {
169 --m_count;
170 return m_value -= value;
171 }
172
173 unsigned long long IgHookTrace::CounterValue::max( unsigned long long value )
174 {
175 ++m_count;
176 if ( m_value < value ) m_value = value;
177 return m_value;
178 }
179
180 unsigned long long IgHookTrace::CounterValue::add( CounterValue& x )
181 {
182 m_count += x.m_count;
183 m_value += x.m_value;
184 return m_value;
185 }
186
187 unsigned long long IgHookTrace::CounterValue::sub( CounterValue& x )
188 {
189 m_count -= x.m_count;
190 m_value -= x.m_value;
191 return m_value;
192 }
193
194 unsigned long long IgHookTrace::CounterValue::max( CounterValue& x )
195 {
196 m_count += x.m_count;
197 if ( m_value < x.m_value ) m_value = x.m_value;
198 return m_value;
199 }
200
204 void* IgHookTrace::operator new( size_t n, IgHookTraceAlloc* alloc /* = 0 */ )
205 {
206 return alloc ? alloc->allocate( n ) : ::operator new( n );
207 }
208
209 IgHookTrace::IgHookTrace( IgHookTrace* parent /* = 0 */, void* address /* = 0 */ )
210 : m_alloc( parent ? parent->m_alloc : new IgHookTraceAlloc )
211 , m_parent( parent )
212 , m_next( parent ? parent->m_children : 0 )
213 , m_children( 0 )
214 , m_address( address )
215 , m_counters( 0 )
216 {
217 if ( m_parent ) m_parent->m_children = this;
218 }
219
220 IgHookTrace* IgHookTrace::parent( void ) { return m_parent; }
221
222 IgHookTrace* IgHookTrace::next( void ) { return m_next; }
223
224 void* IgHookTrace::address( void ) { return m_address; }
225
226 bool IgHookTrace::symbol( void* address, const char*& sym, const char*& lib, int& offset, int& liboffset )
227 {
228 sym = lib = 0;
229 offset = 0;
230 liboffset = (unsigned long)address;
231
232 Dl_info info;
233 if ( dladdr( address, &info ) ) {
234 if ( info.dli_fname && info.dli_fname[0] ) lib = info.dli_fname;
235
236 if ( info.dli_fbase ) liboffset = (unsigned long)address - (unsigned long)info.dli_fbase;
237
238 if ( info.dli_saddr ) offset = (unsigned long)address - (unsigned long)info.dli_saddr;
239
240 if ( info.dli_sname && info.dli_sname[0] ) sym = info.dli_sname;
241
242 return true;
243 }
244
245 return false;
246 }
247
248 bool IgHookTrace::symbol( const char*& sym, const char*& lib, int& offset, int& liboffset )
249 {
250 return symbol( m_address, sym, lib, offset, liboffset );
251 }
252
253 void* IgHookTrace::tosymbol( void* address )
254 {
255 Dl_info info;
256 return ( dladdr( address, &info ) && info.dli_fname && info.dli_fname[0] && info.dli_saddr ) ? info.dli_saddr
257 : address;
258 }
IgHookTrace::CounterValue::next
CounterValue * next(void)
Definition: IgHook_IgHookTrace.cpp:143
gaudirun.args
args
Definition: gaudirun.py:244
IgHookTrace::tosymbol
static void * tosymbol(void *address)
Definition: IgHook_IgHookTrace.cpp:253
IgHookTraceAlloc::m_left
size_t m_left
Definition: IgHook_IgHookTrace.h:25
IgHookTrace::parent
IgHookTrace * parent(void)
Definition: IgHook_IgHookTrace.cpp:220
Gaudi::Units::pc
constexpr double pc
Definition: SystemOfUnits.h:102
IgHookTrace::CounterValue::untick
unsigned long long untick(void)
Definition: IgHook_IgHookTrace.cpp:155
IgHookTrace::CounterValue::m_next
CounterValue * m_next
Definition: IgHook_IgHookTrace.h:63
IgHookTrace::CounterValue::m_counter
Counter * m_counter
Definition: IgHook_IgHookTrace.h:62
IgHookTrace
Definition: IgHook_IgHookTrace.h:28
GaudiPluginService.cpluginsvc.n
n
Definition: cpluginsvc.py:228
IgHookTrace::m_children
IgHookTrace * m_children
Definition: IgHook_IgHookTrace.h:96
IgHookTrace::CounterValue::add
unsigned long long add(unsigned long long value)
Definition: IgHook_IgHookTrace.cpp:161
IgHookTrace::m_parent
IgHookTrace * m_parent
Definition: IgHook_IgHookTrace.h:94
IgHookTrace::CounterValue::counter
Counter * counter(void)
Definition: IgHook_IgHookTrace.cpp:141
IgHookTrace::CounterValue::tick
unsigned long long tick(void)
Definition: IgHook_IgHookTrace.cpp:149
IgHookTrace::address
void * address(void)
Definition: IgHook_IgHookTrace.cpp:224
IgHookTrace::CounterValue
Value for a counter chained from a trace.
Definition: IgHook_IgHookTrace.h:37
IgHookTrace::symbol
static bool symbol(void *address, const char *&sym, const char *&lib, int &offset, int &liboffset)
Definition: IgHook_IgHookTrace.cpp:226
IgHookTrace::CounterValue::max
unsigned long long max(unsigned long long value)
Definition: IgHook_IgHookTrace.cpp:173
IgHookTrace::CounterValue::value
unsigned long long value(void)
Definition: IgHook_IgHookTrace.cpp:145
IgHookTrace::CounterValue::m_value
unsigned long long m_value
Definition: IgHook_IgHookTrace.h:64
IgHookTrace::CounterValue::sub
unsigned long long sub(unsigned long long value)
Definition: IgHook_IgHookTrace.cpp:167
IgHookTrace::Counter
Nearly dummy object type to identify a counter.
Definition: IgHook_IgHookTrace.h:32
IgHook_IgHookTrace.h
IgHookTrace::m_next
IgHookTrace * m_next
Definition: IgHook_IgHookTrace.h:95
IgHookTrace::CounterValue::CounterValue
CounterValue(Counter *counter, CounterValue *next=0, unsigned long long value=0)
Definition: IgHook_IgHookTrace.cpp:135
plotSpeedupsPyRoot.counter
int counter
Definition: plotSpeedupsPyRoot.py:149
IgHookTrace::CounterValue::m_count
unsigned long long m_count
Definition: IgHook_IgHookTrace.h:65
IgHookTrace::m_counters
CounterValue * m_counters
Definition: IgHook_IgHookTrace.h:98
IgHookTrace::m_alloc
IgHookTraceAlloc * m_alloc
Definition: IgHook_IgHookTrace.h:93
IgHookTrace::m_address
void * m_address
Definition: IgHook_IgHookTrace.h:97
IgHookTrace::CounterValue::count
unsigned long long count(void)
Definition: IgHook_IgHookTrace.cpp:147
IgHookTrace::IgHookTrace
IgHookTrace(IgHookTrace *parent=0, void *address=0)
Definition: IgHook_IgHookTrace.cpp:209
IgHookTraceAlloc::IgHookTraceAlloc
IgHookTraceAlloc(void)
Definition: IgHook_IgHookTrace.cpp:99
IgHookTraceAlloc
Definition: IgHook_IgHookTrace.h:16
IgHookTrace::next
IgHookTrace * next(void)
Definition: IgHook_IgHookTrace.cpp:222
IgHookTraceAlloc::m_pool
void * m_pool
Definition: IgHook_IgHookTrace.h:24
IgHookTraceAlloc::allocate
void * allocate(size_t bytes)
Definition: IgHook_IgHookTrace.cpp:101