SWI portability
This commit is contained in:
116
os/pl-cstack.c
116
os/pl-cstack.c
@@ -89,15 +89,49 @@ get_trace_store(void)
|
||||
}
|
||||
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
next_btrace_id() produces the id for the next backtrace and sets
|
||||
bt->current to the subsequent id. Although bt is thread-local, it may be
|
||||
called from a signal handler or (Windows) exception. We cannot use
|
||||
locking because the mutex functions are not async signal safe. So, we
|
||||
use atomic instructions if possible. Otherwise, we ensure consistency of
|
||||
the datastructures, but we may overwrite an older stack trace.
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
static int
|
||||
next_btrace_id(btrace *bt)
|
||||
{ int current;
|
||||
#ifdef COMPARE_AND_SWAP
|
||||
int next;
|
||||
|
||||
do
|
||||
{ current = bt->current;
|
||||
next = current+1;
|
||||
if ( next == SAVE_TRACES )
|
||||
next = 0;
|
||||
} while ( !COMPARE_AND_SWAP(&bt->current, current, next) );
|
||||
#else
|
||||
current = bt->current++ % SAVE_TRACES;
|
||||
|
||||
if ( bt->current >= SAVE_TRACES )
|
||||
bt->current %= SAVE_TRACES;
|
||||
#endif
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
save_backtrace(const char *why)
|
||||
{ btrace *bt = get_trace_store();
|
||||
|
||||
if ( bt )
|
||||
{ btrace_stack *s = &bt->dumps[bt->current];
|
||||
{ btrace_stack *s;
|
||||
unw_cursor_t cursor; unw_context_t uc;
|
||||
int depth;
|
||||
int current = next_btrace_id(bt);
|
||||
|
||||
s = &bt->dumps[current];
|
||||
unw_getcontext(&uc);
|
||||
unw_init_local(&cursor, &uc);
|
||||
for(depth=0; unw_step(&cursor) > 0 && depth < MAX_DEPTH; depth++)
|
||||
@@ -107,9 +141,6 @@ save_backtrace(const char *why)
|
||||
}
|
||||
s->name = why;
|
||||
s->depth = depth;
|
||||
|
||||
if ( ++bt->current == SAVE_TRACES )
|
||||
bt->current = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -228,6 +259,33 @@ get_trace_store(void)
|
||||
}
|
||||
|
||||
|
||||
/* Copy of same function above. Relies on a different btrace structure.
|
||||
Ideally, this should be shared :-(
|
||||
*/
|
||||
|
||||
static int
|
||||
next_btrace_id(btrace *bt)
|
||||
{ int current;
|
||||
#ifdef COMPARE_AND_SWAP
|
||||
int next;
|
||||
|
||||
do
|
||||
{ current = bt->current;
|
||||
next = current+1;
|
||||
if ( next == SAVE_TRACES )
|
||||
next = 0;
|
||||
} while ( !COMPARE_AND_SWAP(&bt->current, current, next) );
|
||||
#else
|
||||
current = bt->current++ % SAVE_TRACES;
|
||||
|
||||
if ( bt->current >= SAVE_TRACES )
|
||||
bt->current %= SAVE_TRACES;
|
||||
#endif
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
save_backtrace(const char *why)
|
||||
{ btrace *bt = get_trace_store();
|
||||
@@ -235,15 +293,14 @@ save_backtrace(const char *why)
|
||||
if ( bt )
|
||||
{ void *array[100];
|
||||
size_t frames;
|
||||
int current = next_btrace_id(bt);
|
||||
|
||||
frames = backtrace(array, sizeof(array)/sizeof(void *));
|
||||
bt->sizes[bt->current] = frames;
|
||||
if ( bt->symbols[bt->current] )
|
||||
free(bt->symbols[bt->current]);
|
||||
bt->symbols[bt->current] = backtrace_symbols(array, frames);
|
||||
bt->why[bt->current] = why;
|
||||
if ( ++bt->current == SAVE_TRACES )
|
||||
bt->current = 0;
|
||||
bt->sizes[current] = frames;
|
||||
if ( bt->symbols[current] )
|
||||
free(bt->symbols[current]);
|
||||
bt->symbols[current] = backtrace_symbols(array, frames);
|
||||
bt->why[current] = why;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,6 +415,9 @@ initBackTrace(void)
|
||||
*/
|
||||
#define MAX_MODULE_NAME_LENGTH 64
|
||||
|
||||
#define LOCK() PL_LOCK(L_CSTACK)
|
||||
#define UNLOCK() PL_UNLOCK(L_CSTACK)
|
||||
|
||||
typedef struct
|
||||
{ char name[MAX_FUNCTION_NAME_LENGTH]; /* function called */
|
||||
DWORD64 offset; /* offset in function */
|
||||
@@ -397,6 +457,32 @@ get_trace_store(void)
|
||||
return LD->btrace_store;
|
||||
}
|
||||
|
||||
/* Copy of same function above. Relies on a different btrace structure.
|
||||
Ideally, this should be shared :-(
|
||||
*/
|
||||
|
||||
static int
|
||||
next_btrace_id(btrace *bt)
|
||||
{ int current;
|
||||
#ifdef COMPARE_AND_SWAP
|
||||
int next;
|
||||
|
||||
do
|
||||
{ current = bt->current;
|
||||
next = current+1;
|
||||
if ( next == SAVE_TRACES )
|
||||
next = 0;
|
||||
} while ( !COMPARE_AND_SWAP(&bt->current, current, next) );
|
||||
#else
|
||||
current = bt->current++ % SAVE_TRACES;
|
||||
|
||||
if ( bt->current >= SAVE_TRACES )
|
||||
bt->current %= SAVE_TRACES;
|
||||
#endif
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
int backtrace(btrace_stack* trace, PEXCEPTION_POINTERS pExceptionInfo)
|
||||
{ STACKFRAME64 frame;
|
||||
CONTEXT context;
|
||||
@@ -406,7 +492,6 @@ int backtrace(btrace_stack* trace, PEXCEPTION_POINTERS pExceptionInfo)
|
||||
char symbolScratch[sizeof(SYMBOL_INFO) + MAX_SYMBOL_LEN];
|
||||
SYMBOL_INFO* symbol = (SYMBOL_INFO*)&symbolScratch;
|
||||
IMAGEHLP_MODULE64 moduleInfo;
|
||||
EXCEPTION_POINTERS *pExp = NULL;
|
||||
DWORD64 offset;
|
||||
DWORD imageType;
|
||||
int skip = 0;
|
||||
@@ -529,11 +614,12 @@ void
|
||||
win_save_backtrace(const char *why, PEXCEPTION_POINTERS pExceptionInfo)
|
||||
{ btrace *bt = get_trace_store();
|
||||
if ( bt )
|
||||
{ btrace_stack *s = &bt->dumps[bt->current];
|
||||
{ int current = next_btrace_id(bt);
|
||||
btrace_stack *s = &bt->dumps[current];
|
||||
LOCK();
|
||||
s->depth = backtrace(s, pExceptionInfo);
|
||||
UNLOCK();
|
||||
s->name = why;
|
||||
if ( ++bt->current == SAVE_TRACES )
|
||||
bt->current = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user