From 5f635602cee8b7d4a79b0b51a0c7a060bb6575e2 Mon Sep 17 00:00:00 2001 From: vemax78 Date: Sun, 10 Nov 2013 22:10:40 +0100 Subject: [PATCH] Add debug information into mutex calls --- src/common/capwap_lock.c | 75 ++++++++++++++++++++++++++++++++++++---- src/common/capwap_lock.h | 16 +++++++++ 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/src/common/capwap_lock.c b/src/common/capwap_lock.c index 039513b..a63bbd3 100644 --- a/src/common/capwap_lock.c +++ b/src/common/capwap_lock.c @@ -1,5 +1,6 @@ #include "capwap.h" #include "capwap_lock.h" +#include "capwap_logging.h" #ifndef CAPWAP_MULTITHREADING_ENABLE #error "Warning: multithreading is disabled\n" @@ -17,23 +18,85 @@ int capwap_lock_init(capwap_lock_t* lock) { return 1; } +#ifdef DEBUG +/* */ +void capwap_lock_destroy_debug(capwap_lock_t* lock, const char* file, const int line) { + int res; + + ASSERT(lock != NULL); + + res = pthread_mutex_trylock(&lock->mutex); + if (!res) { + pthread_mutex_unlock(&lock->mutex); + } else if (res == EINVAL) { + capwap_logging_debug("Attempt to destroy invalid mutex from '%s' (%d)", file, line); + capwap_backtrace_callstack(); + } else if (res == EBUSY) { + capwap_logging_debug("Attempt to destroy locked mutex by '%s' (%d) from '%s' (%d)", lock->file, lock->line, file, line); + capwap_backtrace_callstack(); + } + + pthread_mutex_destroy(&lock->mutex); +} + +/* */ +void capwap_lock_enter_debug(capwap_lock_t* lock, const char* file, const int line) { + int res; + time_t starttime; + time_t waittime; + time_t lasttime = 0; + + ASSERT(lock != NULL); + + /* */ + starttime = time(NULL); + + do { + res = pthread_mutex_trylock(&lock->mutex); + if (res == EBUSY) { + waittime = time(NULL) - starttime; + if (!(waittime % 5) && (waittime > lasttime)) { + lasttime = waittime; + capwap_logging_debug("Waited %d sec for mutex '%s' (%d) locked by '%s' (%d)", waittime, file, line, lock->file, lock->line); + capwap_backtrace_callstack(); + } + + usleep(200); + } + } while (res == EBUSY); + + /* */ + lock->file = (char*)file; + lock->line = (int)line; +} + +/* */ +void capwap_lock_exit_debug(capwap_lock_t* lock, const char* file, const int line) { + ASSERT(lock != NULL); + + /* */ + lock->file = NULL; + lock->line = 0; + + /* */ + if (pthread_mutex_unlock(&lock->mutex)) { + capwap_logging_debug("Error releasing mutex '%s' (%d)", file, line); + capwap_backtrace_callstack(); + } +} +#else /* */ void capwap_lock_destroy(capwap_lock_t* lock) { - ASSERT(lock != NULL); - pthread_mutex_destroy(&lock->mutex); } /* */ void capwap_lock_enter(capwap_lock_t* lock) { - ASSERT(lock != NULL); - pthread_mutex_lock(&lock->mutex); } /* */ void capwap_lock_exit(capwap_lock_t* lock) { - ASSERT(lock != NULL); - pthread_mutex_unlock(&lock->mutex); } +#endif diff --git a/src/common/capwap_lock.h b/src/common/capwap_lock.h index cf4c1d8..a52c5f4 100644 --- a/src/common/capwap_lock.h +++ b/src/common/capwap_lock.h @@ -7,12 +7,28 @@ typedef struct { pthread_mutex_t mutex; +#ifdef DEBUG + char* file; + int line; +#endif } capwap_lock_t; int capwap_lock_init(capwap_lock_t* lock); + +#ifdef DEBUG +#define capwap_lock_destroy(lock) capwap_lock_destroy_debug(lock, __FILE__, __LINE__) +void capwap_lock_destroy_debug(capwap_lock_t* lock, const char* file, const int line); + +#define capwap_lock_enter(lock) capwap_lock_enter_debug(lock, __FILE__, __LINE__) +void capwap_lock_enter_debug(capwap_lock_t* lock, const char* file, const int line); + +#define capwap_lock_exit(lock) capwap_lock_exit_debug(lock, __FILE__, __LINE__) +void capwap_lock_exit_debug(capwap_lock_t* lock, const char* file, const int line); +#else void capwap_lock_destroy(capwap_lock_t* lock); void capwap_lock_enter(capwap_lock_t* lock); void capwap_lock_exit(capwap_lock_t* lock); +#endif #endif /* CAPWAP_MULTITHREADING_ENABLE */