libcsdbg  1.28
C++ exception (and generic) stack trace debug library
thread.cpp
Go to the documentation of this file.
1 #include "../include/thread.hpp"
2 
9 namespace csdbg {
10 
18 thread::thread(const i8 *nm)
19 try:
20 m_name(NULL),
21 m_handle(pthread_self()),
22 m_stack(NULL),
23 m_lag(0)
24 {
25  if ( unlikely(nm != NULL) ) {
26  m_name = new i8[strlen(nm) + 1];
27  strcpy(m_name, nm);
28  }
29 
30  m_stack = new stack<call>;
31 }
32 
33 catch (...) {
34  delete[] m_name;
35  m_name = NULL;
36 }
37 
38 
47 try:
48 m_name(NULL),
49 m_handle(src.m_handle),
50 m_stack(NULL),
51 m_lag(src.m_lag)
52 {
53  const i8 *nm = src.m_name;
54  if ( unlikely(nm != NULL) ) {
55  m_name = new i8[strlen(nm) + 1];
56  strcpy(m_name, nm);
57  }
58 
59  m_stack = src.m_stack->clone();
60 }
61 
62 catch (...) {
63  delete[] m_name;
64  m_name = NULL;
65 }
66 
67 
72 {
73  delete[] m_name;
74  delete m_stack;
75  m_name = NULL;
76  m_stack = NULL;
77 }
78 
79 
87 inline thread* thread::clone() const
88 {
89  return new thread(*this);
90 }
91 
92 
98 inline const i8* thread::name() const
99 {
100  return m_name;
101 }
102 
103 
109 inline pthread_t thread::handle() const
110 {
111  return m_handle;
112 }
113 
114 
123 inline i32 thread::lag() const
124 {
125  return m_lag;
126 }
127 
128 
139 {
140  if ( unlikely(nm == NULL) ) {
141  delete[] m_name;
142  m_name = NULL;
143  return *this;
144  }
145 
146  u32 len = strlen(nm);
147  if ( likely(m_name == NULL || len > strlen(m_name)) ) {
148  delete[] m_name;
149  m_name = NULL;
150  m_name = new i8[len + 1];
151  }
152 
153  strcpy(m_name, nm);
154  return *this;
155 }
156 
157 
168 {
169  if ( unlikely(this == &rval) )
170  return *this;
171 
172  *m_stack = *rval.m_stack;
173  m_handle = rval.m_handle;
174  m_lag = rval.m_lag;
175 
176  return set_name(rval.m_name);
177 }
178 
179 
185 inline bool thread::is_current() const
186 {
187  return pthread_equal(m_handle, pthread_self()) != 0;
188 }
189 
190 
196 inline u32 thread::call_depth() const
197 {
198  return m_stack->size();
199 }
200 
201 
211 inline const call* thread::backtrace(u32 i) const
212 {
213  return m_stack->peek(i);
214 }
215 
216 
231 {
232  /*
233  * If the function is called while an exception is unwinding the stack, keep
234  * track of the call depth difference between the simulated and the real call
235  * stack (the 'lag')
236  */
237  if ( unlikely(std::uncaught_exception()) ) {
238  m_lag--;
239  return *this;
240  }
241 
242  call *c = NULL;
243  try {
244  __D_ASSERT(nm != NULL);
245  c = new call(addr, site, nm);
246  m_stack->push(c);
247  return *this;
248  }
249 
250  catch (...) {
251  delete c;
252  throw;
253  }
254 }
255 
256 
263 {
264  /*
265  * If the function returned because an exception is propagating, unwinding the
266  * stack, keep track of the call depth difference between the simulated and
267  * the real call stack (the 'lag')
268  */
269  if ( unlikely(std::uncaught_exception()) )
270  m_lag++;
271  else
272  m_stack->pop();
273 
274  return *this;
275 }
276 
277 
284 {
285  while ( likely(m_lag > 0) ) {
286  m_stack->pop();
287  m_lag--;
288  }
289 
290  return *this;
291 }
292 
293 
301 inline thread& thread::foreach(void (*pfunc)(u32, call*)) const
302 {
303  m_stack->foreach(pfunc);
304  return const_cast<thread&> (*this);
305 }
306 
307 }
308 
virtual thread & foreach(void(*)(u32, call *)) const
Traverse the simulated stack with a callback for each call.
Definition: thread.cpp:301
i8 * m_name
Thread name.
Definition: thread.hpp:33
virtual thread & called(mem_addr_t, mem_addr_t, const i8 *)
Simulate a function call.
Definition: thread.cpp:230
virtual pthread_t handle() const
Get the thread handle.
Definition: thread.cpp:109
char i8
8-bit signed integer
Definition: config.hpp:72
stack< call > * m_stack
Simulated call stack.
Definition: thread.hpp:37
Lightweight, templated, singly-linked LIFO queue (stack)
Definition: stack.hpp:28
virtual bool is_current() const
Check if this is the currently executing thread.
Definition: thread.cpp:185
#define likely(expr)
Offer a hint (positive) to the pipeline branch predictor.
Definition: config.hpp:344
This class represents a program/library runtime function call.
Definition: call.hpp:17
virtual thread & returned()
Simulate a function return.
Definition: thread.cpp:262
This class represents a thread of execution in the instrumented process.
Definition: thread.hpp:27
virtual ~thread()
Object destructor.
Definition: thread.cpp:71
virtual thread & operator=(const thread &)
Assignment operator.
Definition: thread.cpp:167
virtual thread & unwind()
Unwind the simulated call stack to meet the real call stack.
Definition: thread.cpp:283
virtual u32 call_depth() const
Get the size (call depth) of the simulated call stack.
Definition: thread.cpp:196
virtual i32 lag() const
Get the size (call depth) of the simulated call stack with respect to the real call stack...
Definition: thread.cpp:123
thread(const i8 *=NULL)
Object constructor.
Definition: thread.cpp:18
virtual thread * clone() const
Object virtual copy constructor.
Definition: thread.cpp:87
unsigned int u32
32-bit unsigned integer
Definition: config.hpp:102
int i32
32-bit signed integer
Definition: config.hpp:82
virtual const call * backtrace(u32) const
Peek at the simulated call stack.
Definition: thread.cpp:211
virtual const i8 * name() const
Get the thread name.
Definition: thread.cpp:98
unsigned long long mem_addr_t
64-bit memory address
Definition: config.hpp:120
i32 m_lag
The number of calls that must be popped off the simulated stack for it to match the real one...
Definition: thread.hpp:39
#define unlikely(expr)
Offer a hint (negative) to the pipeline branch predictor.
Definition: config.hpp:349
#define __D_ASSERT(x)
Assertion macro.
Definition: config.hpp:268
pthread_t m_handle
Thread handle.
Definition: thread.hpp:35
virtual thread & set_name(const i8 *)
Set the thread name.
Definition: thread.cpp:138