| The Gaudi Framework v27r1

- 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 <cstdlib>
5 #include <cstdio>
6 #include <dlfcn.h>
7 #include <unistd.h>
8 #include <sys/mman.h>
9 #if __linux
10 # include <execinfo.h>
11 # include <ucontext.h>
12 # include <sys/syscall.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)
100 : m_pool (0),
101 m_left (0)
102 {}
103
104 void *
105 IgHookTraceAlloc::allocate (size_t bytes)
106 {
107 // The reason for the existence of this class is to allocate
108 // memory directly using mmap() so we don't create calls to
109 // malloc() and friends. This is for two reasons: it must be
110 // possible to use this in asynchronous signal handlers, and
111 // calling malloc() in those is a really bad idea; and this is
112 // meant to be used by profiling code and it's nicer to not
113 // allocate memory in ways tracked by the profiler.
114 if (m_left < bytes)
115 {
116 size_t psize = getpagesize ();
117 size_t hunk = psize * 20;
118 if (hunk < bytes) hunk = (hunk + psize - 1) & ~(psize-1);
119 void *addr = mmap (0, hunk, PROT_READ | PROT_WRITE,
120 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
121 if (addr == MAP_FAILED)
122 return 0;
123
124 m_pool = addr;
125 m_left = hunk;
126 }
127
128 void *ptr = m_pool;
129 m_pool = (char *) m_pool + bytes;
130 m_left -= bytes;
131 return ptr;
132 }
133
137 void *
138 IgHookTrace::CounterValue::operator new (size_t n, IgHookTraceAlloc *alloc /* = 0 */)
139 { return alloc ? alloc->allocate (n) : ::operator new (n); }
140
141 IgHookTrace::CounterValue::CounterValue (Counter *counter,
142 CounterValue *next /* = 0 */,
143 unsigned long long value /* = 0 */)
144 : m_counter (counter),
145 m_next (next),
146 m_value (value),
147 m_count (0)
148 {}
149
150 IgHookTrace::Counter *
151 IgHookTrace::CounterValue::counter (void)
152 { return m_counter; }
153
154 IgHookTrace::CounterValue *
155 IgHookTrace::CounterValue::next (void)
156 { return m_next; }
157
158 unsigned long long
159 IgHookTrace::CounterValue::value (void)
160 { return m_value; }
161
162 unsigned long long
163 IgHookTrace::CounterValue::count (void)
164 { return m_count; }
165
166 unsigned long long
167 IgHookTrace::CounterValue::tick (void)
168 { ++m_count; return ++m_value; }
169
170 unsigned long long
171 IgHookTrace::CounterValue::untick (void)
172 { --m_count; return --m_value; }
173
174 unsigned long long
175 IgHookTrace::CounterValue::add (unsigned long long value)
176 { ++m_count; return m_value += value; }
177
178 unsigned long long
179 IgHookTrace::CounterValue::sub (unsigned long long value)
180 { --m_count; return m_value -= value; }
181
182 unsigned long long
183 IgHookTrace::CounterValue::max (unsigned long long value)
184 { ++m_count; if (m_value < value) m_value = value; return m_value; }
185
186 unsigned long long
187 IgHookTrace::CounterValue::add (CounterValue &x)
188 { m_count += x.m_count; m_value += x.m_value; return m_value; }
189
190 unsigned long long
191 IgHookTrace::CounterValue::sub (CounterValue &x)
192 { m_count -= x.m_count; m_value -= x.m_value; return m_value; }
193
194 unsigned long long
195 IgHookTrace::CounterValue::max (CounterValue &x)
196 { m_count += x.m_count; if (m_value < x.m_value) m_value = x.m_value; return m_value; }
197
201 void *
202 IgHookTrace::operator new (size_t n, IgHookTraceAlloc *alloc /* = 0 */)
203 { return alloc ? alloc->allocate (n) : ::operator new (n); }
204
205 IgHookTrace::IgHookTrace (IgHookTrace *parent /* = 0 */, void *address /* = 0 */)
206 : m_alloc (parent ? parent->m_alloc : new IgHookTraceAlloc),
207 m_parent (parent),
208 m_next (parent ? parent->m_children : 0),
209 m_children (0),
210 m_address (address),
211 m_counters (0)
212 { if (m_parent) m_parent->m_children = this; }
213
214 IgHookTrace *
215 IgHookTrace::parent (void)
216 { return m_parent; }
217
218 IgHookTrace *
219 IgHookTrace::next (void)
220 { return m_next; }
221
222 void *
223 IgHookTrace::address (void)
224 { return m_address; }
225
226 bool
227 IgHookTrace::symbol (void *address,
228 const char *&sym,
229 const char *&lib,
230 int &offset,
231 int &liboffset)
232 {
233 sym = lib = 0;
234 offset = 0;
235 liboffset = (unsigned long) address;
236
237 Dl_info info;
238 if (dladdr (address, &info))
239 {
240 if (info.dli_fname && info.dli_fname [0])
241 lib = info.dli_fname;
242
243 if (info.dli_fbase)
244 liboffset = (unsigned long) address - (unsigned long) info.dli_fbase;
245
246 if (info.dli_saddr)
247 offset = (unsigned long) address - (unsigned long) info.dli_saddr;
248
249 if (info.dli_sname && info.dli_sname [0])
250 sym = info.dli_sname;
251
252 return true;
253 }
254
255 return false;
256 }
257
258 bool
259 IgHookTrace::symbol (const char *&sym, const char *&lib, int &offset, int &liboffset)
260 { return symbol (m_address, sym, lib, offset, liboffset); }
261
262 void *
263 IgHookTrace::tosymbol (void *address)
264 {
265 Dl_info info;
266 return (dladdr (address, &info)
267 && info.dli_fname
268 && info.dli_fname [0]
269 && info.dli_saddr)
270 ? info.dli_saddr : address;
271 }
IgHookTrace::CounterValue::next
CounterValue * next(void)
Definition: IgHook_IgHookTrace.cpp:155
IgHookTrace::tosymbol
static void * tosymbol(void *address)
Definition: IgHook_IgHookTrace.cpp:263
IgHookTraceAlloc::m_left
size_t m_left
Definition: IgHook_IgHookTrace.h:25
IgHookTrace::parent
IgHookTrace * parent(void)
Definition: IgHook_IgHookTrace.cpp:215
Gaudi::Units::pc
constexpr double pc
Definition: SystemOfUnits.h:101
IgHookTrace::CounterValue::untick
unsigned long long untick(void)
Definition: IgHook_IgHookTrace.cpp:171
GaudiPluginService.cpluginsvc.n
list n
Definition: cpluginsvc.py:217
IgHookTrace
Definition: IgHook_IgHookTrace.h:28
IgHookTrace::m_children
IgHookTrace * m_children
Definition: IgHook_IgHookTrace.h:99
IgHookTrace::CounterValue::add
unsigned long long add(unsigned long long value)
Definition: IgHook_IgHookTrace.cpp:175
IgHookTrace::m_parent
IgHookTrace * m_parent
Definition: IgHook_IgHookTrace.h:97
IgHookTrace::CounterValue::counter
Counter * counter(void)
Definition: IgHook_IgHookTrace.cpp:151
IgHookTrace::CounterValue::tick
unsigned long long tick(void)
Definition: IgHook_IgHookTrace.cpp:167
IgHookTrace::address
void * address(void)
Definition: IgHook_IgHookTrace.cpp:223
IgHookTrace::CounterValue
Value for a counter chained from a trace.
Definition: IgHook_IgHookTrace.h:35
IgHookTrace::symbol
static bool symbol(void *address, const char *&sym, const char *&lib, int &offset, int &liboffset)
Definition: IgHook_IgHookTrace.cpp:227
dump_component_properties.value
list value
Definition: dump_component_properties.py:12
IgHookTrace::CounterValue::max
unsigned long long max(unsigned long long value)
Definition: IgHook_IgHookTrace.cpp:183
IgHookTrace::CounterValue::value
unsigned long long value(void)
Definition: IgHook_IgHookTrace.cpp:159
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:179
IgHookTrace::Counter
Nearly dummy object type to identify a counter.
Definition: IgHook_IgHookTrace.h:32
IgHook_IgHookTrace.h
HiveAlgSequencer.top
tuple top
Definition: HiveAlgSequencer.py:29
IgHookTrace::m_next
IgHookTrace * m_next
Definition: IgHook_IgHookTrace.h:98
IgHookTrace::CounterValue::CounterValue
CounterValue(Counter *counter, CounterValue *next=0, unsigned long long value=0)
Definition: IgHook_IgHookTrace.cpp:141
plotSpeedupsPyRoot.counter
int counter
Definition: plotSpeedupsPyRoot.py:141
IgHookTrace::CounterValue::m_count
unsigned long long m_count
Definition: IgHook_IgHookTrace.h:65
gaudirun.args
list args
Definition: gaudirun.py:290
IgHookTrace::m_counters
CounterValue * m_counters
Definition: IgHook_IgHookTrace.h:101
IgHookTrace::m_alloc
IgHookTraceAlloc * m_alloc
Definition: IgHook_IgHookTrace.h:96
IgHookTrace::m_address
void * m_address
Definition: IgHook_IgHookTrace.h:100
IgHookTrace::CounterValue::count
unsigned long long count(void)
Definition: IgHook_IgHookTrace.cpp:163
IgHookTrace::IgHookTrace
IgHookTrace(IgHookTrace *parent=0, void *address=0)
Definition: IgHook_IgHookTrace.cpp:205
IgHookTraceAlloc::IgHookTraceAlloc
IgHookTraceAlloc(void)
Definition: IgHook_IgHookTrace.cpp:99
IgHookTraceAlloc
Definition: IgHook_IgHookTrace.h:16
IgHookTrace::next
IgHookTrace * next(void)
Definition: IgHook_IgHookTrace.cpp:219
IgHookTraceAlloc::m_pool
void * m_pool
Definition: IgHook_IgHookTrace.h:24
IgHookTraceAlloc::allocate
void * allocate(size_t bytes)
Definition: IgHook_IgHookTrace.cpp:105