summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphintuka <phintuka>2006-12-21 08:07:24 +0000
committerphintuka <phintuka>2006-12-21 08:07:24 +0000
commit5a0b4592eb0edb4329f8c6c78f582a46ec3ad9a6 (patch)
treec524f3081daf7e1045d70d50f00b1fa569fbceed
parente46704b696a35238a4e43648559138e7f4989e4b (diff)
downloadxineliboutput-5a0b4592eb0edb4329f8c6c78f582a46ec3ad9a6.tar.gz
xineliboutput-5a0b4592eb0edb4329f8c6c78f582a46ec3ad9a6.tar.bz2
Added small description and pthread_mutex_trylock wrapper
-rw-r--r--tools/debug_mutex.h75
1 files changed, 69 insertions, 6 deletions
diff --git a/tools/debug_mutex.h b/tools/debug_mutex.h
index dc25ec7e..38bb12ce 100644
--- a/tools/debug_mutex.h
+++ b/tools/debug_mutex.h
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: debug_mutex.h,v 1.1 2006-12-19 17:21:50 phintuka Exp $
+ * $Id: debug_mutex.h,v 1.2 2006-12-21 08:07:24 phintuka Exp $
*
*/
@@ -15,20 +15,44 @@
# error pthread.h must be included before debug_mutex.h
#endif
+/*
+ * Override pthread_mutex_ calls:
+ *
+ * Change type of each mutex to PTHREAD_MUTEX_ERRORCHECK_NP
+ *
+ * Store line number of last succeed pthread_mutex_lock call
+ * for each initialized mutex
+ *
+ * Check every pthread_mutex_ call for errors and log all errors
+ *
+ * To help detecting deadlocks and minimize logging:
+ * - Try locking first in pthread_mutex_lock
+ * - If pthread_mutex_trylock fails, log a message and retry.
+ * - When trylock failed, log another message when lock is acquired.
+ *
+ *
+ * NOTE: debugging itself is not thread-safe and may indicate wrong line numbers !
+ *
+ */
+
+#define MAX_DBG_MUTEX 64
static struct {
pthread_mutex_t *lock;
int line;
-} dbgdata[64] = {{NULL,0}};
+} dbgdata[MAX_DBG_MUTEX+1] = {{NULL,0}};
static void dbg_setdata(pthread_mutex_t *mutex, int line)
{
int i;
- for(i=0; i<32; i++)
+ for(i=0; i<MAX_DBG_MUTEX; i++)
if(dbgdata[i].lock == mutex) {
dbgdata[i].line = line;
return;
}
- else if(!dbgdata[i].lock) {
+
+ LOGMSG("********** dbg_setdata: new entry (0x%x at %d)", (unsigned long int)mutex, line);
+ for(i=0; i<MAX_DBG_MUTEX; i++)
+ if(!dbgdata[i].lock) {
dbgdata[i].lock = mutex;
dbgdata[i].line = line;
return;
@@ -40,7 +64,7 @@ static void dbg_setdata(pthread_mutex_t *mutex, int line)
static int dbg_getdata(pthread_mutex_t *mutex, int line)
{
int i;
- for(i=0; i<32; i++)
+ for(i=0; i<MAX_DBG_MUTEX; i++)
if(dbgdata[i].lock == mutex)
return dbgdata[i].line;
@@ -48,10 +72,24 @@ static int dbg_getdata(pthread_mutex_t *mutex, int line)
return -1;
}
+static void dbg_deldata(pthread_mutex_t *mutex, int line)
+{
+ int i;
+ for(i=0; i<MAX_DBG_MUTEX; i++)
+ if(dbgdata[i].lock == mutex) {
+ dbgdata[i].lock = NULL;
+ return;
+ }
+
+ LOGMSG("********** dbg_deldata: NO ENTRY ! (%d)", line);
+ return;
+}
+
static int dbg_init(pthread_mutex_t *mutex, pthread_mutexattr_t *pattr, int line)
{
int r;
+ errno = 0;
if(!pattr) {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
@@ -74,11 +112,13 @@ static int dbg_free(pthread_mutex_t *mutex, int line)
{
int r;
+ errno = 0;
r = pthread_mutex_destroy(mutex);
if(r)
LOGERR("********** dbg_free: pthread_mutex_destroy FAILED at %d ; last lock at %d",
line, dbg_getdata(mutex, line));
+ dbg_deldata(mutex, line);
return r;
}
@@ -89,6 +129,7 @@ static int dbg_lock(pthread_mutex_t *mutex, int line)
/*struct timespec abs_timeout;*/
/* try lock first to reduce logging */
+ errno = 0;
r = pthread_mutex_trylock(mutex);
if(!r) {
dbg_setdata(mutex,line);
@@ -96,12 +137,13 @@ static int dbg_lock(pthread_mutex_t *mutex, int line)
}
/* try failed - we're going to wait, so log at wait start and end to detect deadlocks */
- LOGMSG("********** dbg_lock: pthread_mutex_trylock failed at %d (locked at %d)",
+ LOGERR("********** dbg_lock: pthread_mutex_trylock failed at %d (locked at %d)",
line, dbg_getdata(mutex, line));
/* int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
const struct timespec *restrict abs_timeout); */
+ errno = 0;
r = pthread_mutex_lock(mutex);
if(r)
@@ -113,10 +155,30 @@ static int dbg_lock(pthread_mutex_t *mutex, int line)
return r;
}
+static int dbg_trylock(pthread_mutex_t *mutex, int line)
+{
+ int r;
+ /*struct timespec abs_timeout;*/
+
+ /* try lock first to reduce logging */
+ errno = 0;
+ r = pthread_mutex_trylock(mutex);
+ if(!r) {
+ dbg_setdata(mutex,line);
+ return r;
+ }
+
+ LOGERR("********** dbg_trylock: pthread_mutex_trylock failed at %d (locked at %d)",
+ line, dbg_getdata(mutex, line));
+
+ return r;
+}
+
static int dbg_unlock(pthread_mutex_t *mutex, int line)
{
int r;
+ errno = 0;
r = pthread_mutex_unlock(mutex);
if(r)
@@ -129,6 +191,7 @@ static int dbg_unlock(pthread_mutex_t *mutex, int line)
/* override pthread_ functions with own ones */
#define pthread_mutex_init(l,a) dbg_init(l, a, __LINE__)
#define pthread_mutex_lock(l) dbg_lock(l, __LINE__)
+#define pthread_mutex_trylock(l) dbg_trylock(l, __LINE__)
#define pthread_mutex_unlock(l) dbg_unlock(l, __LINE__)
#define pthread_mutex_destroy(l) dbg_free(l, __LINE__)