summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLénaïc Huard <lenaic@lhuard.fr.eu.org>2010-02-17 22:10:12 +0100
committerLennart Poettering <lennart@poettering.net>2010-02-21 22:03:46 +0100
commitb2e4363183b1f33332988b3493e248fc5f6b5d99 (patch)
treee601ea408b3bd5c0646085cee71d33d685df0f49
parentc11673a883ff9fd0d46e75d2f625340cf4a0166a (diff)
Delay the symbols name resolution.
Retrieving the stacktrace is cheap, but resolving symbols name may be expansive. Delaying this process prevents program perturbation and saves process as the symbols name resolution is now done only for the displayed mutexes.
-rw-r--r--mutrace.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/mutrace.c b/mutrace.c
index 9f81bc5..bca604e 100644
--- a/mutrace.c
+++ b/mutrace.c
@@ -59,6 +59,11 @@
#define LIKELY(x) (__builtin_expect(!!(x),1))
#define UNLIKELY(x) (__builtin_expect(!!(x),0))
+struct stacktrace_info {
+ void **frames;
+ int nb_frame;
+};
+
struct mutex_info {
pthread_mutex_t *mutex;
pthread_rwlock_t *rwlock;
@@ -80,7 +85,7 @@ struct mutex_info {
uint64_t nsec_locked_max;
uint64_t nsec_timestamp;
- char *stacktrace;
+ struct stacktrace_info stacktrace;
unsigned id;
@@ -140,6 +145,8 @@ static uint64_t nsec_timestamp_setup;
static void setup(void) __attribute ((constructor));
static void shutdown(void) __attribute ((destructor));
+static char *stacktrace_to_string(struct stacktrace_info stacktrace);
+
static pid_t _gettid(void) {
return (pid_t) syscall(SYS_gettid);
}
@@ -441,13 +448,18 @@ static bool mutex_info_show(struct mutex_info *mi) {
}
static bool mutex_info_dump(struct mutex_info *mi) {
+ char *stacktrace_str;
if (!mutex_info_show(mi))
return false;
+ stacktrace_str = stacktrace_to_string(mi->stacktrace);
+
fprintf(stderr,
"\nMutex #%u (0x%p) first referenced by:\n"
- "%s", mi->id, mi->mutex ? (void*) mi->mutex : (void*) mi->rwlock, mi->stacktrace);
+ "%s", mi->id, mi->mutex ? (void*) mi->mutex : (void*) mi->rwlock, stacktrace_str);
+
+ free(stacktrace_str);
return true;
}
@@ -754,33 +766,36 @@ static int light_backtrace(void **buffer, int size) {
#endif
}
-static char* generate_stacktrace(void) {
- void **buffer;
+static struct stacktrace_info generate_stacktrace(void) {
+ struct stacktrace_info stacktrace;
+
+ stacktrace.frames = malloc(sizeof(void*) * frames_max);
+ assert(stacktrace.frames);
+
+ stacktrace.nb_frame = light_backtrace(stacktrace.frames, frames_max);
+ assert(stacktrace.nb_frame >= 0);
+
+ return stacktrace;
+}
+
+static char *stacktrace_to_string(struct stacktrace_info stacktrace) {
char **strings, *ret, *p;
- int n, i;
+ int i;
size_t k;
bool b;
- buffer = malloc(sizeof(void*) * frames_max);
- assert(buffer);
-
- n = light_backtrace(buffer, frames_max);
- assert(n >= 0);
-
- strings = real_backtrace_symbols(buffer, n);
+ strings = real_backtrace_symbols(stacktrace.frames, stacktrace.nb_frame);
assert(strings);
- free(buffer);
-
k = 0;
- for (i = 0; i < n; i++)
+ for (i = 0; i < stacktrace.nb_frame; i++)
k += strlen(strings[i]) + 2;
ret = malloc(k + 1);
assert(ret);
b = false;
- for (i = 0, p = ret; i < n; i++) {
+ for (i = 0, p = ret; i < stacktrace.nb_frame; i++) {
if (!b && !verify_frame(strings[i]))
continue;