AM_CONDITIONAL([EINA_HAVE_THREADS], [! test "x${have_threads}" = "xno"])
if ! test "x${have_debug_threads}" = "xno"; then
- EINA_CONFIGURE_HAVE_DEBUG_THREADS="#define EINA_DEBUG_THREADS"
+ EINA_CONFIGURE_HAVE_DEBUG_THREADS="#define EINA_HAVE_DEBUG_THREADS"
fi
AC_SUBST(EINA_CONFIGURE_HAVE_DEBUG_THREADS)
AM_CONDITIONAL([EINA_DEBUG_THREADS], [! test "x${have_debug_threads}" = "xno"])
if ! test "x${have_on_off_threads}" = "xno"; then
- EINA_CONFIGURE_HAVE_ON_OFF_THREADS="#define EINA_ON_OFF_THREADS"
+ EINA_CONFIGURE_HAVE_ON_OFF_THREADS="#define EINA_HAVE_ON_OFF_THREADS"
fi
AC_SUBST(EINA_CONFIGURE_HAVE_ON_OFF_THREADS)
AM_CONDITIONAL([EINA_ON_OFF_THREADS], [! test "x${have_on_off_threads}" = "xno"])
#endif
#ifdef EINA_HAVE_DEBUG_THREADS
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
#include <execinfo.h>
#define EINA_LOCK_DEBUG_BT_NUM 64
typedef void (*Eina_Lock_Bt_Func) ();
+
+#include "eina_inlist.h"
#endif
typedef struct _Eina_Lock Eina_Lock;
struct _Eina_Lock
{
+#ifdef EINA_HAVE_DEBUG_THREADS
+ EINA_INLIST;
+#endif
pthread_mutex_t mutex;
#ifdef EINA_HAVE_DEBUG_THREADS
pthread_t lock_thread_id;
EAPI extern int _eina_threads_debug;
EAPI extern pthread_t _eina_main_loop;
+EAPI extern pthread_mutex_t _eina_tracking_lock;
+EAPI extern Eina_Inlist *_eina_tracking;
#endif
static inline Eina_Bool
if (pthread_mutexattr_init(&attr) != 0)
return EINA_FALSE;
-/* use errorcheck locks. detect deadlocks.
-#ifdef PTHREAD_MUTEX_RECURSIVE
- if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
- return EINA_FALSE;
-#endif
- */
+ /* NOTE: PTHREAD_MUTEX_RECURSIVE is not allowed at all, you will break on/off
+ feature for sure with that change. */
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
return EINA_FALSE;
#ifdef EINA_HAVE_DEBUG_THREADS
#ifdef EINA_HAVE_DEBUG_THREADS
assert(pthread_equal(_eina_main_loop, pthread_self()));
#endif
- return EINA_LOCK_FAIL;
+ return EINA_LOCK_SUCCEED;
}
#endif
int dt;
gettimeofday(&t0, NULL);
- pthread_mutex_lock(&(x));
+ ok = pthread_mutex_lock(&(mutex->mutex));
gettimeofday(&t1, NULL);
dt = (t1.tv_sec - t0.tv_sec) * 1000000;
if (dt > _eina_threads_debug) abort();
}
+ else
+ {
+#endif
+ ok = pthread_mutex_lock(&(mutex->mutex));
+#ifdef EINA_HAVE_DEBUG_THREADS
+ }
#endif
- ok = pthread_mutex_lock(&(mutex->mutex));
+
if (ok == 0) ret = EINA_LOCK_SUCCEED;
else if (ok == EDEADLK)
{
printf("ERROR ERROR: DEADLOCK on lock %p\n", mutex);
ret = EINA_LOCK_DEADLOCK; // magic
}
+
#ifdef EINA_HAVE_DEBUG_THREADS
mutex->locked = 1;
mutex->lock_thread_id = pthread_self();
mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
+
+ pthread_mutex_lock(&_eina_tracking_lock);
+ _eina_tracking = eina_inlist_append(_eina_tracking,
+ EINA_INLIST_GET(mutex));
+ pthread_mutex_unlock(&_eina_tracking_lock);
#endif
+
return ret;
}
#ifdef EINA_HAVE_DEBUG_THREADS
assert(pthread_equal(_eina_main_loop, pthread_self()));
#endif
- return EINA_LOCK_FAIL;
+ return EINA_LOCK_SUCCEED;
}
#endif
mutex->locked = 1;
mutex->lock_thread_id = pthread_self();
mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
+
+ pthread_mutex_lock(&_eina_tracking_lock);
+ _eina_tracking = eina_inlist_append(_eina_tracking,
+ EINA_INLIST_GET(mutex));
+ pthread_mutex_unlock(&_eina_tracking_lock);
}
#endif
return ret;
#ifdef EINA_HAVE_DEBUG_THREADS
assert(pthread_equal(_eina_main_loop, pthread_self()));
#endif
- return EINA_LOCK_FAIL;
+ return EINA_LOCK_SUCCEED;
}
#endif
#ifdef EINA_HAVE_DEBUG_THREADS
+ pthread_mutex_lock(&_eina_tracking_lock);
+ _eina_tracking = eina_inlist_remove(_eina_tracking,
+ EINA_INLIST_GET(mutex));
+ pthread_mutex_unlock(&_eina_tracking_lock);
+
mutex->locked = 0;
mutex->lock_thread_id = 0;
memset(mutex->lock_bt, 0, EINA_LOCK_DEBUG_BT_NUM * sizeof(Eina_Lock_Bt_Func));
}
static inline void
-eina_lock_debug(Eina_Lock *mutex)
+eina_lock_debug(const Eina_Lock *mutex)
{
#ifdef EINA_HAVE_DEBUG_THREADS
printf("lock %p, locked: %i, by %i\n",
#ifdef EINA_HAVE_DEBUG_THREADS
EAPI int _eina_threads_debug = 0;
-EAPI pthread_t _eina_main_loop = NULL;
+EAPI pthread_t _eina_main_loop;;
+EAPI pthread_mutex_t _eina_tracking_lock;
+EAPI Eina_Inlist *_eina_tracking = NULL;
#endif
static Eina_Lock _mutex;
return 0;
}
+#ifdef EINA_HAVE_DEBUG_THREADS
+ _eina_main_loop = pthread_self();
+ pthread_mutex_init(&_eina_tracking_lock, NULL);
+
+ if (getenv("EINA_DEBUG_THREADS"))
+ _eina_threads_debug = atoi(getenv("EINA_DEBUG_THREADS"));
+#endif
+
itr = _eina_desc_setup;
itr_end = itr + _eina_desc_setup_len;
for (; itr < itr_end; itr++)
}
}
-
eina_lock_new(&_mutex);
-#ifdef EINA_HAVE_DEBUG_THREADS
- _eina_main_loop = pthread_self();
-
- if (getenv("EINA_DEBUG_THREADS"))
- _eina_threads_debug = atoi(getenv("EINA_DEBUG_THREADS");
-#endif
_eina_main_count = 1;
return 1;
{
_eina_shutdown_from_desc(_eina_desc_setup + _eina_desc_setup_len);
+#ifdef EINA_HAVE_DEBUG_THREADS
+ pthread_mutex_destroy(&_eina_tracking_lock);
+#endif
+
eina_lock_free(&_mutex);
}
int ret;
#ifdef EINA_HAVE_DEBUG_THREADS
+ const Eina_Lock *lk;
+
assert(pthread_equal(_eina_main_loop, pthread_self()));
assert(_eina_main_thread_count > 0);
+
+ pthread_mutex_lock(&_eina_tracking_lock);
+ if (_eina_tracking)
+ {
+ fprintf(stderr, "*************************\n");
+ fprintf(stderr, "* The IMPOSSIBLE HAPPEN *\n");
+ fprintf(stderr, "* LOCK STILL TAKEN : *\n");
+ fprintf(stderr, "*************************\n");
+ EINA_INLIST_FOREACH(_eina_tracking, lk)
+ eina_lock_debug(lk);
+ fprintf(stderr, "*************************\n");
+ abort();
+ }
+ pthread_mutex_unlock(&_eina_tracking_lock);
+
#endif
eina_lock_take(&_mutex);