summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphintuka <phintuka>2006-12-19 17:21:50 +0000
committerphintuka <phintuka>2006-12-19 17:21:50 +0000
commit7134f4b13a4c4b8b68dd16aec4dfa56ba28ef7d7 (patch)
treeeeb69ea1f2e92372db92d7b4537fbe5e931da661
parent268993689835d54ae2b9bbf33e8fc3ead06cff93 (diff)
downloadxineliboutput-7134f4b13a4c4b8b68dd16aec4dfa56ba28ef7d7.tar.gz
xineliboutput-7134f4b13a4c4b8b68dd16aec4dfa56ba28ef7d7.tar.bz2
Initial import
-rw-r--r--tools/debug_mutex.h137
1 files changed, 137 insertions, 0 deletions
diff --git a/tools/debug_mutex.h b/tools/debug_mutex.h
new file mode 100644
index 00000000..dc25ec7e
--- /dev/null
+++ b/tools/debug_mutex.h
@@ -0,0 +1,137 @@
+/*
+ * debug_mutex.h: debugging wrappers for pthread_mutex_ functions
+ *
+ * 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 $
+ *
+ */
+
+#ifndef DEBUG_MUTEX_H
+#define DEBUG_MUTEX_H
+
+#ifndef _PTHREAD_H
+# error pthread.h must be included before debug_mutex.h
+#endif
+
+static struct {
+ pthread_mutex_t *lock;
+ int line;
+} dbgdata[64] = {{NULL,0}};
+
+static void dbg_setdata(pthread_mutex_t *mutex, int line)
+{
+ int i;
+ for(i=0; i<32; i++)
+ if(dbgdata[i].lock == mutex) {
+ dbgdata[i].line = line;
+ return;
+ }
+ else if(!dbgdata[i].lock) {
+ dbgdata[i].lock = mutex;
+ dbgdata[i].line = line;
+ return;
+ }
+
+ LOGMSG("********** dbg_setdata: table full !");
+}
+
+static int dbg_getdata(pthread_mutex_t *mutex, int line)
+{
+ int i;
+ for(i=0; i<32; i++)
+ if(dbgdata[i].lock == mutex)
+ return dbgdata[i].line;
+
+ LOGMSG("********** dbg_getdata: NO ENTRY ! (%d)", line);
+ return -1;
+}
+
+static int dbg_init(pthread_mutex_t *mutex, pthread_mutexattr_t *pattr, int line)
+{
+ int r;
+
+ if(!pattr) {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
+ r = pthread_mutex_init(mutex, &attr);
+ } else {
+ LOGMSG("********** dbg_init: mutex attribute already given !");
+ r = pthread_mutex_init(mutex, pattr);
+ }
+
+ if(r)
+ LOGERR("********** dbg_init: pthread_mutex_init FAILED at %d", line);
+
+ dbg_setdata(mutex, line);
+
+ return r;
+}
+
+static int dbg_free(pthread_mutex_t *mutex, int line)
+{
+ int r;
+
+ 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));
+
+ return r;
+}
+
+static int dbg_lock(pthread_mutex_t *mutex, int line)
+{
+ int r;
+ /*struct timespec abs_timeout;*/
+
+ /* try lock first to reduce logging */
+ r = pthread_mutex_trylock(mutex);
+ if(!r) {
+ dbg_setdata(mutex,line);
+ return r;
+ }
+
+ /* 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)",
+ line, dbg_getdata(mutex, line));
+
+ /* int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
+ const struct timespec *restrict abs_timeout); */
+
+ r = pthread_mutex_lock(mutex);
+
+ if(r)
+ LOGERR("********** dbg_lock: pthread_mutex_lock FAILED at %d", line);
+
+ dbg_setdata(mutex, line);
+ LOGMSG("********** dbg_lock: pthread_mutex_lock done at %d", line);
+
+ return r;
+}
+
+static int dbg_unlock(pthread_mutex_t *mutex, int line)
+{
+ int r;
+
+ r = pthread_mutex_unlock(mutex);
+
+ if(r)
+ LOGERR("********** dbg_unlock: pthread_mutex_unlock FAILED at %d (last locket at %d)",
+ line, dbg_getdata(mutex, line));
+
+ return r;
+}
+
+/* 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_unlock(l) dbg_unlock(l, __LINE__)
+#define pthread_mutex_destroy(l) dbg_free(l, __LINE__)
+
+#else
+# error debug_mutex.h included twice
+#endif /* DEBUG_MUTEX_H */