eina_lock: modify mutex debugging to ignore recursive locks
authorMike Blumenkrantz <zmike@samsung.com>
Fri, 15 Jun 2018 19:37:56 +0000 (15:37 -0400)
committerJongmin Lee <jm105.lee@samsung.com>
Sun, 17 Jun 2018 22:18:39 +0000 (07:18 +0900)
Summary:
recursive locks are locked multiple times in the same thread, leading to
failure with the tracking infrastructure which was written prior to
the addition of recursive locks and assumed that locks would only be
taken exactly once

given that this debug info is meant to handle non-recursive locks,
it makes little sense to include them in the handling

@fix

Depends on D6264

Reviewers: stefan_schmidt, ManMower, devilhorns

Reviewed By: ManMower

Subscribers: cedric, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D6265

src/lib/eina/eina_inline_lock_posix.x

index d48d27b..83bac7b 100644 (file)
@@ -108,6 +108,7 @@ struct _Eina_Lock
    Eina_Lock_Bt_Func lock_bt[EINA_LOCK_DEBUG_BT_NUM]; /**< The function that will produce a backtrace on the thread that has the lock */
    int               lock_bt_num; /**< Number of addresses in the backtrace */
    Eina_Bool         locked : 1;  /**< Indicates locked or not locked */
+   Eina_Bool         recursive : 1;  /**< Indicates recursive lock */
 #endif
 };
 
@@ -158,13 +159,21 @@ EAPI Eina_Lock_Result _eina_spinlock_macos_release(Eina_Spinlock *spinlock);
 static inline Eina_Bool
 eina_lock_new(Eina_Lock *mutex)
 {
-   return _eina_lock_new(mutex, EINA_FALSE);
+   Eina_Bool ret = _eina_lock_new(mutex, EINA_FALSE);
+#ifdef EINA_HAVE_DEBUG_THREADS
+   mutex->recursive = EINA_FALSE;
+#endif
+   return ret;
 }
 
 static inline Eina_Bool
 eina_lock_recursive_new(Eina_Lock *mutex)
 {
-   return _eina_lock_new(mutex, EINA_TRUE);
+   Eina_Bool ret = _eina_lock_new(mutex, EINA_TRUE);
+#ifdef EINA_HAVE_DEBUG_THREADS
+   mutex->recursive = EINA_TRUE;
+#endif
+   return ret;
 }
 
 static inline void
@@ -228,6 +237,8 @@ eina_lock_take(Eina_Lock *mutex)
    else EINA_LOCK_ABORT_DEBUG(ok, lock, mutex);
 
 #ifdef EINA_HAVE_DEBUG_THREADS
+   /* recursive locks can't make use of any of this */
+   if (mutex->recursive) return ret;
    mutex->locked = 1;
    mutex->lock_thread_id = pthread_self();
    mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
@@ -273,6 +284,8 @@ eina_lock_take_try(Eina_Lock *mutex)
 #ifdef EINA_HAVE_DEBUG_THREADS
    if (ret == EINA_LOCK_SUCCEED)
      {
+        /* recursive locks can't make use of any of this */
+        if (mutex->recursive) return ret;
         mutex->locked = 1;
         mutex->lock_thread_id = pthread_self();
         mutex->lock_bt_num = backtrace((void **)(mutex->lock_bt), EINA_LOCK_DEBUG_BT_NUM);
@@ -303,15 +316,18 @@ eina_lock_release(Eina_Lock *mutex)
 #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));
-   mutex->lock_bt_num = 0;
+/* recursive locks can't make use of any of this */
+   if (!mutex->recursive)
+     {
+        mutex->locked = 0;
+        mutex->lock_thread_id = 0;
+        memset(mutex->lock_bt, 0, EINA_LOCK_DEBUG_BT_NUM * sizeof(Eina_Lock_Bt_Func));
+        mutex->lock_bt_num = 0;
+        pthread_mutex_lock(&_eina_tracking_lock);
+        _eina_tracking = eina_inlist_remove(_eina_tracking,
+                                            EINA_INLIST_GET(mutex));
+        pthread_mutex_unlock(&_eina_tracking_lock);
+     }
 #endif
    ok = pthread_mutex_unlock(&(mutex->mutex));
    if (ok == 0) ret = EINA_LOCK_SUCCEED;