eina: improve on/off and debugging lock.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 4 May 2011 13:53:22 +0000 (13:53 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 4 May 2011 13:53:22 +0000 (13:53 +0000)
Now if a lock is still taken when shutdown occur, you will know
where it come from !

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@59191 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.ac
src/include/eina_inline_lock_posix.x
src/include/eina_lock.h
src/lib/eina_main.c
src/lib/eina_object.c

index 2886ec6..a917ba5 100644 (file)
@@ -117,13 +117,13 @@ AC_SUBST(EINA_CONFIGURE_HAVE_THREADS)
 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"])
index 397e1f2..96a8cfd 100644 (file)
 #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;
@@ -54,6 +62,8 @@ EAPI extern Eina_Bool _eina_threads_activated;
 
 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
@@ -67,12 +77,8 @@ eina_lock_new(Eina_Lock *mutex)
 
    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
@@ -111,7 +117,7 @@ eina_lock_take(Eina_Lock *mutex)
 #ifdef EINA_HAVE_DEBUG_THREADS
         assert(pthread_equal(_eina_main_loop, pthread_self()));
 #endif
-        return EINA_LOCK_FAIL;
+        return EINA_LOCK_SUCCEED;
      }
 #endif
 
@@ -122,7 +128,7 @@ eina_lock_take(Eina_Lock *mutex)
         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;
@@ -134,19 +140,32 @@ eina_lock_take(Eina_Lock *mutex)
 
         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;
 }
 
@@ -162,7 +181,7 @@ eina_lock_take_try(Eina_Lock *mutex)
 #ifdef EINA_HAVE_DEBUG_THREADS
         assert(pthread_equal(_eina_main_loop, pthread_self()));
 #endif
-        return EINA_LOCK_FAIL;
+        return EINA_LOCK_SUCCEED;
      }
 #endif
 
@@ -184,6 +203,11 @@ eina_lock_take_try(Eina_Lock *mutex)
         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;
@@ -200,11 +224,16 @@ eina_lock_release(Eina_Lock *mutex)
 #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));
@@ -216,7 +245,7 @@ eina_lock_release(Eina_Lock *mutex)
 }
 
 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",
index 769a5cb..9b55e78 100644 (file)
@@ -58,7 +58,7 @@ static inline void eina_lock_free(Eina_Lock *mutex);
 static inline Eina_Lock_Result eina_lock_take(Eina_Lock *mutex);
 static inline Eina_Lock_Result eina_lock_take_try(Eina_Lock *mutex);
 static inline Eina_Lock_Result eina_lock_release(Eina_Lock *mutex);
-static inline void eina_lock_debug(Eina_Lock *mutex);
+static inline void eina_lock_debug(const Eina_Lock *mutex);
 
 /**
  * @}
index e468280..6f2f7c5 100644 (file)
@@ -78,7 +78,9 @@ EAPI Eina_Bool _eina_threads_activated = EINA_FALSE;
 
 #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;
@@ -205,6 +207,14 @@ eina_init(void)
         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++)
@@ -217,14 +227,7 @@ eina_init(void)
           }
      }
 
-
    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;
@@ -238,6 +241,10 @@ eina_shutdown(void)
      {
         _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);
      }
 
@@ -284,8 +291,25 @@ eina_threads_shutdown(void)
    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);
index 80a6b67..0d69833 100644 (file)
@@ -676,8 +676,7 @@ eina_class_repack(Eina_Class *class)
   if (!eina_lock_take(&class->mutex))
     {
 #ifdef EINA_HAVE_DEBUG_THREADS
-  else
-    assert(pthread_equal(class->self, pthread_self()));
+      assert(pthread_equal(class->self, pthread_self()));
 #endif
     }