From: cedric Date: Wed, 4 May 2011 13:53:22 +0000 (+0000) Subject: eina: improve on/off and debugging lock. X-Git-Tag: submit/2.0alpha-wayland/20121127.222009~690 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=46c630125397502b5ca3f2e05832515a8019832f;p=profile%2Fivi%2Feina.git eina: improve on/off and debugging lock. Now if a lock is still taken when shutdown occur, you will know where it come from ! git-svn-id: http://svn.enlightenment.org/svn/e/trunk/eina@59191 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- diff --git a/configure.ac b/configure.ac index 2886ec6..a917ba5 100644 --- a/configure.ac +++ b/configure.ac @@ -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"]) diff --git a/src/include/eina_inline_lock_posix.x b/src/include/eina_inline_lock_posix.x index 397e1f2..96a8cfd 100644 --- a/src/include/eina_inline_lock_posix.x +++ b/src/include/eina_inline_lock_posix.x @@ -29,15 +29,23 @@ #endif #ifdef EINA_HAVE_DEBUG_THREADS +#include +#include +#include #include #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", diff --git a/src/include/eina_lock.h b/src/include/eina_lock.h index 769a5cb..9b55e78 100644 --- a/src/include/eina_lock.h +++ b/src/include/eina_lock.h @@ -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); /** * @} diff --git a/src/lib/eina_main.c b/src/lib/eina_main.c index e468280..6f2f7c5 100644 --- a/src/lib/eina_main.c +++ b/src/lib/eina_main.c @@ -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); diff --git a/src/lib/eina_object.c b/src/lib/eina_object.c index 80a6b67..0d69833 100644 --- a/src/lib/eina_object.c +++ b/src/lib/eina_object.c @@ -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 }