This is Unofficial EPICS BASE Doxygen Site
epicsStackTrace.c
Go to the documentation of this file.
1 /*
2  * Copyright: Stanford University / SLAC National Laboratory.
3  *
4  * EPICS BASE is distributed subject to a Software License Agreement found
5  * in file LICENSE that is included with this distribution.
6  *
7  * Author: Till Straumann <strauman@slac.stanford.edu>, 2011, 2014
8  */
9 
10 #include <stdlib.h>
11 
12 #include "epicsThread.h"
13 #include "epicsMutex.h"
14 #include "errlog.h"
15 #include "epicsStackTracePvt.h"
16 #include "epicsStackTrace.h"
17 
18 /* How many stack frames to capture */
19 #define MAXDEPTH 100
20 
21 static epicsThreadOnceId stackTraceInitId = EPICS_THREAD_ONCE_INIT;
22 static epicsMutexId stackTraceMtx;
23 
24 static void stackTraceInit(void *unused)
25 {
26  stackTraceMtx = epicsMutexMustCreate();
27 }
28 
29 static void stackTraceLock(void)
30 {
31  epicsThreadOnce( &stackTraceInitId, stackTraceInit, 0 );
32  epicsMutexLock( stackTraceMtx );
33 }
34 
35 static void stackTraceUnlock(void)
36 {
37  epicsMutexUnlock( stackTraceMtx );
38 }
39 
40 static int
41 dumpInfo(void *addr, epicsSymbol *sym_p)
42 {
43 int rval = 0;
44 
45  rval += errlogPrintf("[%*p]", (int)(sizeof(addr)*2 + 2), addr);
46  if ( sym_p ) {
47  if ( sym_p->f_nam ) {
48  rval += errlogPrintf(": %s", sym_p->f_nam);
49  }
50  if ( sym_p->s_nam ) {
51  rval += errlogPrintf("(%s+0x%lx)", sym_p->s_nam, (unsigned long)((char*)addr - (char*)sym_p->s_val));
52  } else {
53  rval += errlogPrintf("(<no symbol information>)");
54  }
55  }
56  rval += errlogPrintf("\n");
57  errlogFlush();
58 
59  return rval;
60 }
61 
62 void epicsStackTrace(void)
63 {
64 void **buf;
65 int i,n;
66 epicsSymbol sym;
67 
68  if ( 0 == epicsStackTraceGetFeatures() ) {
69  /* unsupported on this platform */
70  return;
71  }
72 
73  if ( ! (buf = malloc(sizeof(*buf) * MAXDEPTH))) {
74  free(buf);
75  errlogPrintf("epicsStackTrace(): not enough memory for backtrace\n");
76  return;
77  }
78 
79  n = epicsBackTrace(buf, MAXDEPTH);
80 
81  if ( n > 0 ) {
82 
83  stackTraceLock();
84 
85  errlogPrintf("Dumping a stack trace of thread '%s':\n", epicsThreadGetNameSelf());
86 
87  errlogFlush();
88 
89  for ( i=0; i<n; i++ ) {
90  if ( 0 == epicsFindAddr(buf[i], &sym) )
91  dumpInfo(buf[i], &sym);
92  else
93  dumpInfo(buf[i], 0);
94  }
95 
96  errlogFlush();
97 
98  stackTraceUnlock();
99 
100  }
101 
102  free(buf);
103 }
104 
106 {
107 void *test[2];
108 
109 static int initflag = 10; /* init to a value larger than the test snapshot */
110 
111  /* don't bother about epicsOnce -- if there should be a race and
112  * the detection code is executed multiple times that is no big deal.
113  */
114  if ( 10 == initflag ) {
115  initflag = epicsBackTrace(test, sizeof(test)/sizeof(test[0]));
116  }
117 
118  if ( initflag <= 0 )
119  return 0; /* backtrace doesn't work or is not supported */
120 
122 }
void errlogFlush(void)
Definition: errlog.c:529
#define EPICS_STACKTRACE_ADDRESSES
int i
Definition: scan.c:967
LIBCOM_API int epicsFindAddr(void *addr, epicsSymbol *sym_p)
Definition: osdFindAddr.c:20
LIBCOM_API const char *epicsStdCall epicsThreadGetNameSelf(void)
Definition: osdThread.c:846
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
Definition: epicsMutex.h:179
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
Definition: epicsMutex.cpp:140
#define EPICS_THREAD_ONCE_INIT
Definition: epicsThread.h:109
int epicsStackTraceGetFeatures()
const char * f_nam
APIs for the epicsMutex mutual exclusion semaphore.
LIBCOM_API void epicsStdCall epicsThreadOnce(epicsThreadOnceId *id, EPICSTHREADFUNC, void *arg)
#define MAXDEPTH
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
void epicsStackTrace(void)
epicsMutexLockStatus epicsStdCall epicsMutexLock(epicsMutexId pmutexNode)
Claim the semaphore, waiting until it&#39;s free if currently owned owned by a different thread...
Definition: epicsMutex.cpp:145
const char * s_nam
LIBCOM_API int epicsFindAddrGetFeatures()
Definition: osdFindAddr.c:37
C++ and C descriptions for a thread.
LIBCOM_API int epicsBackTrace(void **buf, int buf_sz)