summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--mutrace.c115
2 files changed, 69 insertions, 48 deletions
diff --git a/Makefile b/Makefile
index 55fdbf6..2912f61 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
SONAME=libmutrace.so
-CFLAGS=-Wextra -Wall -O0 -g -DPACKAGE_VERSION=\"0.1\" -fPIC -DSONAME=\"$(SONAME)\"
+CFLAGS=-pipe -pthread -Wextra -Wall -O0 -g -DPACKAGE_VERSION=\"0.1\" -fPIC -DSONAME=\"$(SONAME)\"
LIBS=-lrt -ldl
$(SONAME): mutrace.o
diff --git a/mutrace.c b/mutrace.c
index 7feb4a9..efab759 100644
--- a/mutrace.c
+++ b/mutrace.c
@@ -1,5 +1,24 @@
/*-*- Mode: C; c-basic-offset: 8 -*-*/
+/***
+ This file is part of mutrace.
+
+ Copyright 2009 Lennart Poettering
+
+ mutrace is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ mutrace is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with mutrace. If not, see <http://www.gnu.org/licenses/>.
+***/
+
#define _GNU_SOURCE
#include <pthread.h>
@@ -19,7 +38,6 @@
/* FIXMES:
*
* - we probably should cover rwlocks, too
- * - and conds, too!
*
*/
@@ -29,8 +47,6 @@
#define DEBUG_TRAP raise(SIGTRAP)
#endif
-typedef void (*fnptr_t)(void);
-
struct mutex_info {
pthread_mutex_t *mutex;
@@ -79,6 +95,7 @@ static int (*real_pthread_mutex_unlock)(pthread_mutex_t *mutex) = NULL;
static int (*real_pthread_cond_wait)(pthread_cond_t *cond, pthread_mutex_t *mutex) = NULL;
static int (*real_pthread_cond_timedwait)(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) = NULL;
static void (*real_exit)(int status) __attribute__((noreturn)) = NULL;
+static void (*real__exit)(int status) __attribute__((noreturn)) = NULL;
static void (*real__Exit)(int status) __attribute__((noreturn)) = NULL;
static struct mutex_info **alive_mutexes = NULL, **dead_mutexes = NULL;
@@ -91,13 +108,6 @@ static uint64_t nsec_timestamp_setup;
static void setup(void) __attribute ((constructor));
static void shutdown(void) __attribute ((destructor));
-/* dlsym() violates ISO C, so confide the breakage into this function
- * to avoid warnings. */
-
-static inline fnptr_t dlsym_fn(void *handle, const char *symbol) {
- return (fnptr_t) (long) dlsym(handle, symbol);
-}
-
static pid_t _gettid(void) {
return (pid_t) syscall(SYS_gettid);
}
@@ -135,32 +145,38 @@ static int parse_env(const char *n, unsigned *t) {
return 0;
}
+#define LOAD_FUNC(name) \
+ do { \
+ *(void**) (&real_##name) = dlsym(RTLD_NEXT, #name); \
+ assert(real_##name); \
+ } while (false)
+
+#define LOAD_FUNC_VERSIONED(name, version) \
+ do { \
+ *(void**) (&real_##name) = dlvsym(RTLD_NEXT, #name, version); \
+ assert(real_##name); \
+ } while (false)
+
static void setup(void) {
pthread_mutex_t *m, *last;
int r;
unsigned t;
- real_pthread_mutex_init = dlsym_fn(RTLD_NEXT, "pthread_mutex_init");
- real_pthread_mutex_destroy = dlsym_fn(RTLD_NEXT, "pthread_mutex_destroy");
- real_pthread_mutex_lock = dlsym_fn(RTLD_NEXT, "pthread_mutex_lock");
- real_pthread_mutex_trylock = dlsym_fn(RTLD_NEXT, "pthread_mutex_trylock");
- real_pthread_mutex_timedlock = dlsym_fn(RTLD_NEXT, "pthread_mutex_timedlock");
- real_pthread_mutex_unlock = dlsym_fn(RTLD_NEXT, "pthread_mutex_unlock");
- real_pthread_cond_wait = dlsym_fn(RTLD_NEXT, "pthread_cond_wait");
- real_pthread_cond_timedwait = dlsym_fn(RTLD_NEXT, "pthread_cond_timedwait");
- real_exit = dlsym_fn(RTLD_NEXT, "exit");
- real__Exit = dlsym_fn(RTLD_NEXT, "_Exit");
-
- assert(real_pthread_mutex_init);
- assert(real_pthread_mutex_destroy);
- assert(real_pthread_mutex_lock);
- assert(real_pthread_mutex_trylock);
- assert(real_pthread_mutex_timedlock);
- assert(real_pthread_mutex_unlock);
- assert(real_pthread_cond_wait);
- assert(real_pthread_cond_timedwait);
- assert(real_exit);
- assert(real__Exit);
+ LOAD_FUNC(pthread_mutex_init);
+ LOAD_FUNC(pthread_mutex_destroy);
+ LOAD_FUNC(pthread_mutex_lock);
+ LOAD_FUNC(pthread_mutex_trylock);
+ LOAD_FUNC(pthread_mutex_timedlock);
+ LOAD_FUNC(pthread_mutex_unlock);
+
+ /* There's some kind of weird incompatibility problem if we
+ * don't ask for this explicit version of these functions */
+ LOAD_FUNC_VERSIONED(pthread_cond_wait, "GLIBC_2.3.2");
+ LOAD_FUNC_VERSIONED(pthread_cond_timedwait, "GLIBC_2.3.2");
+
+ LOAD_FUNC(exit);
+ LOAD_FUNC(_exit);
+ LOAD_FUNC(_Exit);
t = hash_size;
if (parse_env("MUTRACE_HASH_SIZE", &t) < 0 || t <= 0)
@@ -469,6 +485,11 @@ void exit(int status) {
real_exit(status);
}
+void _exit(int status) {
+ show_summary();
+ real_exit(status);
+}
+
void _Exit(int status) {
show_summary();
real__Exit(status);
@@ -775,25 +796,25 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex) {
return real_pthread_mutex_unlock(mutex);
}
-/* int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { */
-/* int r; */
+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
+ int r;
-/* mutex_unlock(mutex); */
-/* r = real_pthread_cond_wait(cond, mutex); */
+ mutex_unlock(mutex);
+ r = real_pthread_cond_wait(cond, mutex);
-/* /\* Unfortunately we cannot distuingish mutex contention and */
-/* * the condition not being signalled here. *\/ */
-/* mutex_lock(mutex, false); */
+ /* Unfortunately we cannot distuingish mutex contention and
+ * the condition not being signalled here. */
+ mutex_lock(mutex, false);
-/* return r; */
-/* } */
+ return r;
+}
-/* int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { */
-/* int r; */
+int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) {
+ int r;
-/* mutex_unlock(mutex); */
-/* r = real_pthread_cond_timedwait(cond, mutex, abstime); */
-/* mutex_lock(mutex, false); */
+ mutex_unlock(mutex);
+ r = real_pthread_cond_timedwait(cond, mutex, abstime);
+ mutex_lock(mutex, false);
-/* return r; */
-/* } */
+ return r;
+}